summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub1
-rw-r--r--servers/audio/audio_driver_dummy.cpp2
-rw-r--r--servers/audio/audio_driver_dummy.h2
-rw-r--r--servers/audio/audio_effect.cpp31
-rw-r--r--servers/audio/audio_effect.h18
-rw-r--r--servers/audio/audio_filter_sw.cpp9
-rw-r--r--servers/audio/audio_filter_sw.h36
-rw-r--r--servers/audio/audio_rb_resampler.h4
-rw-r--r--servers/audio/audio_stream.cpp60
-rw-r--r--servers/audio/audio_stream.h25
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp2
-rw-r--r--servers/audio/effects/audio_effect_capture.cpp2
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp40
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp4
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp12
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp2
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp8
-rw-r--r--servers/audio/effects/audio_effect_eq.h2
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp2
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp6
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp6
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp96
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.h41
-rw-r--r--servers/audio/effects/audio_effect_record.cpp11
-rw-r--r--servers/audio/effects/audio_effect_record.h1
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp2
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.cpp2
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp10
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.h20
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp6
-rw-r--r--servers/audio/effects/audio_stream_generator.h2
-rw-r--r--servers/audio/effects/reverb.cpp2
-rw-r--r--servers/audio/effects/reverb.h9
-rw-r--r--servers/audio_server.cpp31
-rw-r--r--servers/audio_server.h98
-rw-r--r--servers/camera/camera_feed.cpp2
-rw-r--r--servers/debugger/servers_debugger.cpp28
-rw-r--r--servers/debugger/servers_debugger.h2
-rw-r--r--servers/display_server.cpp246
-rw-r--r--servers/display_server.h83
-rw-r--r--servers/display_server_headless.h2
-rw-r--r--servers/extensions/SCsub7
-rw-r--r--servers/extensions/physics_server_3d_extension.cpp322
-rw-r--r--servers/extensions/physics_server_3d_extension.h548
-rw-r--r--servers/navigation_server_2d.cpp39
-rw-r--r--servers/navigation_server_2d.h19
-rw-r--r--servers/navigation_server_3d.cpp17
-rw-r--r--servers/navigation_server_3d.h19
-rw-r--r--servers/physics_2d/godot_area_2d.cpp48
-rw-r--r--servers/physics_2d/godot_area_2d.h31
-rw-r--r--servers/physics_2d/godot_body_2d.h4
-rw-r--r--servers/physics_2d/godot_body_pair_2d.cpp12
-rw-r--r--servers/physics_2d/godot_broad_phase_2d_bvh.cpp26
-rw-r--r--servers/physics_2d/godot_broad_phase_2d_bvh.h53
-rw-r--r--servers/physics_2d/godot_collision_object_2d.h6
-rw-r--r--servers/physics_2d/godot_collision_solver_2d.cpp8
-rw-r--r--servers/physics_2d/godot_collision_solver_2d_sat.cpp68
-rw-r--r--servers/physics_2d/godot_joints_2d.cpp20
-rw-r--r--servers/physics_2d/godot_physics_server_2d.cpp24
-rw-r--r--servers/physics_2d/godot_physics_server_2d.h2
-rw-r--r--servers/physics_2d/godot_shape_2d.cpp20
-rw-r--r--servers/physics_2d/godot_shape_2d.h6
-rw-r--r--servers/physics_2d/godot_space_2d.cpp33
-rw-r--r--servers/physics_2d/godot_space_2d.h4
-rw-r--r--servers/physics_2d/godot_step_2d.cpp6
-rw-r--r--servers/physics_3d/gjk_epa.cpp18
-rw-r--r--servers/physics_3d/godot_area_3d.cpp48
-rw-r--r--servers/physics_3d/godot_area_3d.h33
-rw-r--r--servers/physics_3d/godot_area_pair_3d.h12
-rw-r--r--servers/physics_3d/godot_body_3d.h8
-rw-r--r--servers/physics_3d/godot_body_pair_3d.cpp4
-rw-r--r--servers/physics_3d/godot_broad_phase_3d_bvh.cpp28
-rw-r--r--servers/physics_3d/godot_broad_phase_3d_bvh.h55
-rw-r--r--servers/physics_3d/godot_collision_object_3d.h6
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.cpp46
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp80
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp30
-rw-r--r--servers/physics_3d/godot_physics_server_3d.h8
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp26
-rw-r--r--servers/physics_3d/godot_shape_3d.h4
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp28
-rw-r--r--servers/physics_3d/godot_soft_body_3d.h16
-rw-r--r--servers/physics_3d/godot_space_3d.cpp23
-rw-r--r--servers/physics_3d/godot_space_3d.h6
-rw-r--r--servers/physics_3d/godot_step_3d.cpp10
-rw-r--r--servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp10
-rw-r--r--servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp12
-rw-r--r--servers/physics_3d/joints/godot_hinge_joint_3d.cpp26
-rw-r--r--servers/physics_3d/joints/godot_slider_joint_3d.cpp22
-rw-r--r--servers/physics_server_2d.cpp22
-rw-r--r--servers/physics_server_2d.h20
-rw-r--r--servers/physics_server_2d_wrap_mt.cpp22
-rw-r--r--servers/physics_server_2d_wrap_mt.h22
-rw-r--r--servers/physics_server_3d.cpp38
-rw-r--r--servers/physics_server_3d.h45
-rw-r--r--servers/physics_server_3d_wrap_mt.cpp22
-rw-r--r--servers/physics_server_3d_wrap_mt.h24
-rw-r--r--servers/register_server_types.cpp68
-rw-r--r--servers/register_server_types.h1
-rw-r--r--servers/rendering/SCsub1
-rw-r--r--servers/rendering/dummy/rasterizer_canvas_dummy.h63
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h108
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h217
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h147
-rw-r--r--servers/rendering/dummy/storage/light_storage.h135
-rw-r--r--servers/rendering/dummy/storage/material_storage.h95
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h129
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h126
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h173
-rw-r--r--servers/rendering/rasterizer_dummy.h801
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp466
-rw-r--r--servers/rendering/renderer_canvas_cull.h14
-rw-r--r--servers/rendering/renderer_canvas_render.cpp99
-rw-r--r--servers/rendering/renderer_canvas_render.h134
-rw-r--r--servers/rendering/renderer_compositor.cpp1
-rw-r--r--servers/rendering/renderer_compositor.h13
-rw-r--r--servers/rendering/renderer_rd/SCsub2
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp30
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h8
-rw-r--r--servers/rendering/renderer_rd/effects/SCsub5
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.cpp475
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h120
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp683
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h220
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp257
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h152
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp1090
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h345
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp869
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h58
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp269
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h104
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp300
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h11
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp79
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h70
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp394
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h38
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp40
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h30
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp459
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h12
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1068
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h168
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp239
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h49
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp9631
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h2192
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp18
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h8
-rw-r--r--servers/rendering/renderer_rd/shaders/SCsub2
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl21
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/SCsub17
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/blur_raster.glsl)18
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl (renamed from servers/rendering/renderer_rd/shaders/bokeh_dof.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl (renamed from servers/rendering/renderer_rd/shaders/copy.glsl)2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl (renamed from servers/rendering/renderer_rd/shaders/copy_to_fb.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/tonemap.glsl (renamed from servers/rendering/renderer_rd/shaders/tonemap.glsl)72
-rw-r--r--servers/rendering/renderer_rd/shaders/light_data_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl16
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl229
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl24
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl32
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl114
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/sky.glsl9
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_blur.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_interleave.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/taa_resolve.glsl393
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl23
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/SCsub5
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp788
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h370
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp2646
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h342
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp1921
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h706
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp1890
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h564
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp2753
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h567
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.cpp64
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.h221
-rw-r--r--servers/rendering/renderer_scene.h4
-rw-r--r--servers/rendering/renderer_scene_cull.cpp491
-rw-r--r--servers/rendering/renderer_scene_cull.h79
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h22
-rw-r--r--servers/rendering/renderer_scene_render.cpp11
-rw-r--r--servers/rendering/renderer_scene_render.h15
-rw-r--r--servers/rendering/renderer_storage.h447
-rw-r--r--servers/rendering/renderer_viewport.cpp234
-rw-r--r--servers/rendering/renderer_viewport.h13
-rw-r--r--servers/rendering/rendering_device.h69
-rw-r--r--servers/rendering/rendering_device_binds.cpp2
-rw-r--r--servers/rendering/rendering_device_binds.h14
-rw-r--r--servers/rendering/rendering_server_default.cpp31
-rw-r--r--servers/rendering/rendering_server_default.h186
-rw-r--r--servers/rendering/rendering_server_globals.cpp5
-rw-r--r--servers/rendering/rendering_server_globals.h10
-rw-r--r--servers/rendering/shader_compiler.cpp35
-rw-r--r--servers/rendering/shader_compiler.h41
-rw-r--r--servers/rendering/shader_language.cpp1971
-rw-r--r--servers/rendering/shader_language.h126
-rw-r--r--servers/rendering/shader_types.cpp92
-rw-r--r--servers/rendering/shader_types.h12
-rw-r--r--servers/rendering/shader_warnings.cpp6
-rw-r--r--servers/rendering/shader_warnings.h5
-rw-r--r--servers/rendering/storage/SCsub5
-rw-r--r--servers/rendering/storage/light_storage.h139
-rw-r--r--servers/rendering/storage/material_storage.h101
-rw-r--r--servers/rendering/storage/mesh_storage.h136
-rw-r--r--servers/rendering/storage/particles_storage.h129
-rw-r--r--servers/rendering/storage/texture_storage.h137
-rw-r--r--servers/rendering_server.cpp90
-rw-r--r--servers/rendering_server.h26
-rw-r--r--servers/text/text_server_dummy.h48
-rw-r--r--servers/text/text_server_extension.cpp1237
-rw-r--r--servers/text/text_server_extension.h826
-rw-r--r--servers/text_server.cpp228
-rw-r--r--servers/text_server.h466
-rw-r--r--servers/xr/xr_interface.h2
-rw-r--r--servers/xr/xr_interface_extension.cpp7
-rw-r--r--servers/xr/xr_positional_tracker.cpp17
-rw-r--r--servers/xr/xr_positional_tracker.h9
-rw-r--r--servers/xr_server.cpp10
235 files changed, 26627 insertions, 20194 deletions
diff --git a/servers/SCsub b/servers/SCsub
index 2cd4741d56..66a1b9b26f 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -13,6 +13,7 @@ SConscript("rendering/SCsub")
SConscript("audio/SCsub")
SConscript("text/SCsub")
SConscript("debugger/SCsub")
+SConscript("extensions/SCsub")
lib = env.add_library("servers", env.servers_sources)
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 1ba0afd8a1..635e4601c7 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -54,7 +54,7 @@ Error AudioDriverDummy::init() {
};
void AudioDriverDummy::thread_func(void *p_udata) {
- AudioDriverDummy *ad = (AudioDriverDummy *)p_udata;
+ AudioDriverDummy *ad = static_cast<AudioDriverDummy *>(p_udata);
uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000;
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 6324e2f5d3..68b523e086 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -40,7 +40,7 @@ class AudioDriverDummy : public AudioDriver {
Thread thread;
Mutex mutex;
- int32_t *samples_in;
+ int32_t *samples_in = nullptr;
static void thread_func(void *p_udata);
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index b9eca14a4c..f38d0adfb2 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -30,5 +30,36 @@
#include "audio_effect.h"
+void AudioEffectInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
+ if (GDVIRTUAL_REQUIRED_CALL(_process, p_src_frames, p_dst_frames, p_frame_count)) {
+ return;
+ }
+}
+bool AudioEffectInstance::process_silence() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_process_silence, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void AudioEffectInstance::_bind_methods() {
+ GDVIRTUAL_BIND(_process, "src_buffer", "dst_buffer", "frame_count");
+ GDVIRTUAL_BIND(_process_silence);
+}
+
+////
+
+Ref<AudioEffectInstance> AudioEffect::instantiate() {
+ Ref<AudioEffectInstance> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_instantiate, ret)) {
+ return ret;
+ }
+ return Ref<AudioEffectInstance>();
+}
+void AudioEffect::_bind_methods() {
+ GDVIRTUAL_BIND(_instantiate);
+}
+
AudioEffect::AudioEffect() {
}
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 00a5d6c004..3a0578679d 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -33,20 +33,32 @@
#include "core/io/resource.h"
#include "core/math/audio_frame.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
class AudioEffectInstance : public RefCounted {
GDCLASS(AudioEffectInstance, RefCounted);
+protected:
+ GDVIRTUAL3(_process, GDNativeConstPtr<AudioFrame>, GDNativePtr<AudioFrame>, int)
+ GDVIRTUAL0RC(bool, _process_silence)
+ static void _bind_methods();
+
public:
- virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) = 0;
- virtual bool process_silence() const { return false; }
+ virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
+ virtual bool process_silence() const;
};
class AudioEffect : public Resource {
GDCLASS(AudioEffect, Resource);
+protected:
+ GDVIRTUAL0R(Ref<AudioEffectInstance>, _instantiate)
+ static void _bind_methods();
+
public:
- virtual Ref<AudioEffectInstance> instantiate() = 0;
+ virtual Ref<AudioEffectInstance> instantiate();
AudioEffect();
};
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp
index 082931647a..003275f302 100644
--- a/servers/audio/audio_filter_sw.cpp
+++ b/servers/audio/audio_filter_sw.cpp
@@ -211,15 +211,6 @@ float AudioFilterSW::get_response(float p_freq, Coeffs *p_coeffs) {
return H;
}
-AudioFilterSW::AudioFilterSW() {
- sampling_rate = 44100;
- resonance = 0.5;
- cutoff = 5000;
- gain = 1.0;
- mode = LOWPASS;
- stages = 1;
-}
-
AudioFilterSW::Processor::Processor() {
set_filter(nullptr);
}
diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h
index 9e55662d0a..e3f8188997 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -36,11 +36,11 @@
class AudioFilterSW {
public:
struct Coeffs {
- float a1, a2;
- float b0, b1, b2;
-
- //bool operator==(const Coeffs &p_rv) { return (FLOATS_EQ(a1,p_rv.a1) && FLOATS_EQ(a2,p_rv.a2) && FLOATS_EQ(b1,p_rv.b1) && FLOATS_EQ(b2,p_rv.b2) && FLOATS_EQ(b0,p_rv.b0) ); }
- Coeffs() { a1 = a2 = b0 = b1 = b2 = 0.0; }
+ float a1 = 0.0f;
+ float a2 = 0.0f;
+ float b0 = 0.0f;
+ float b1 = 0.0f;
+ float b2 = 0.0f;
};
enum Mode {
@@ -52,14 +52,16 @@ public:
BANDLIMIT,
LOWSHELF,
HIGHSHELF
-
};
- class Processor { // simple filter processor
-
- AudioFilterSW *filter;
+ class Processor { // Simple filter processor.
+ AudioFilterSW *filter = nullptr;
Coeffs coeffs;
- float ha1, ha2, hb1, hb2; //history
+ // History.
+ float ha1 = 0.0f;
+ float ha2 = 0.0f;
+ float hb1 = 0.0f;
+ float hb2 = 0.0f;
Coeffs incr_coeffs;
public:
@@ -73,12 +75,12 @@ public:
};
private:
- float cutoff;
- float resonance;
- float gain;
- float sampling_rate;
- int stages;
- Mode mode;
+ float cutoff = 5000.0f;
+ float resonance = 0.5f;
+ float gain = 1.0f;
+ float sampling_rate = 44100.0f;
+ int stages = 1;
+ Mode mode = LOWPASS;
public:
float get_response(float p_freq, Coeffs *p_coeffs);
@@ -92,7 +94,7 @@ public:
void prepare_coefficients(Coeffs *p_coeffs);
- AudioFilterSW();
+ AudioFilterSW() {}
};
/* inline methods */
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index 3fbe684c3e..81ac6332e2 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -55,8 +55,8 @@ struct AudioRBResampler {
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
};
- float *read_buf;
- float *rb;
+ float *read_buf = nullptr;
+ float *rb = nullptr;
template <int C>
uint32_t _resample(AudioFrame *p_dest, int p_todo, int32_t p_increment);
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index a710658bff..3983bc5cb1 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -76,10 +76,10 @@ void AudioStreamPlayback::seek(float p_time) {
int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
int ret;
- if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
+ if (GDVIRTUAL_REQUIRED_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
return ret;
}
- WARN_PRINT_ONCE("AudioStreamPlayback::mix unimplemented!");
+
return 0;
}
@@ -94,7 +94,7 @@ void AudioStreamPlayback::_bind_methods() {
}
//////////////////////////////
-void AudioStreamPlaybackResampled::_begin_resample() {
+void AudioStreamPlaybackResampled::begin_resample() {
//clear cubic interpolation history
internal_buffer[0] = AudioFrame(0.0, 0.0);
internal_buffer[1] = AudioFrame(0.0, 0.0);
@@ -105,6 +105,30 @@ void AudioStreamPlaybackResampled::_begin_resample() {
mix_offset = 0;
}
+int AudioStreamPlaybackResampled::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_mix_resampled, p_buffer, p_frames, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+float AudioStreamPlaybackResampled::get_stream_sampling_rate() {
+ float ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_stream_sampling_rate, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+void AudioStreamPlaybackResampled::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("begin_resample"), &AudioStreamPlaybackResampled::begin_resample);
+
+ GDVIRTUAL_BIND(_mix_resampled, "dst_buffer", "frame_count");
+ GDVIRTUAL_BIND(_get_stream_sampling_rate);
+}
+
int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
float target_rate = AudioServer::get_singleton()->get_mix_rate();
float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale();
@@ -315,7 +339,7 @@ void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
if (AudioDriver::get_singleton()->capture_start() == OK) {
active = true;
- _begin_resample();
+ begin_resample();
}
}
@@ -363,9 +387,11 @@ void AudioStreamRandomizer::add_stream(int p_index) {
notify_property_list_changed();
}
+// p_index_to is relative to the array prior to the removal of from.
+// Example: [0, 1, 2, 3], move(1, 3) => [0, 2, 1, 3]
void AudioStreamRandomizer::move_stream(int p_index_from, int p_index_to) {
- ERR_FAIL_COND(p_index_from < 0);
- ERR_FAIL_COND(p_index_from >= audio_stream_pool.size());
+ ERR_FAIL_INDEX(p_index_from, audio_stream_pool.size());
+ // p_index_to == audio_stream_pool.size() is valid (move to end).
ERR_FAIL_COND(p_index_to < 0);
ERR_FAIL_COND(p_index_to > audio_stream_pool.size());
audio_stream_pool.insert(p_index_to, audio_stream_pool[p_index_from]);
@@ -379,36 +405,31 @@ void AudioStreamRandomizer::move_stream(int p_index_from, int p_index_to) {
}
void AudioStreamRandomizer::remove_stream(int p_index) {
- ERR_FAIL_COND(p_index < 0);
- ERR_FAIL_COND(p_index >= audio_stream_pool.size());
+ ERR_FAIL_INDEX(p_index, audio_stream_pool.size());
audio_stream_pool.remove_at(p_index);
emit_signal(SNAME("changed"));
notify_property_list_changed();
}
void AudioStreamRandomizer::set_stream(int p_index, Ref<AudioStream> p_stream) {
- ERR_FAIL_COND(p_index < 0);
- ERR_FAIL_COND(p_index >= audio_stream_pool.size());
+ ERR_FAIL_INDEX(p_index, audio_stream_pool.size());
audio_stream_pool.write[p_index].stream = p_stream;
emit_signal(SNAME("changed"));
}
Ref<AudioStream> AudioStreamRandomizer::get_stream(int p_index) const {
- ERR_FAIL_COND_V(p_index < 0, nullptr);
- ERR_FAIL_COND_V(p_index >= audio_stream_pool.size(), nullptr);
+ ERR_FAIL_INDEX_V(p_index, audio_stream_pool.size(), nullptr);
return audio_stream_pool[p_index].stream;
}
void AudioStreamRandomizer::set_stream_probability_weight(int p_index, float p_weight) {
- ERR_FAIL_COND(p_index < 0);
- ERR_FAIL_COND(p_index >= audio_stream_pool.size());
+ ERR_FAIL_INDEX(p_index, audio_stream_pool.size());
audio_stream_pool.write[p_index].weight = p_weight;
emit_signal(SNAME("changed"));
}
float AudioStreamRandomizer::get_stream_probability_weight(int p_index) const {
- ERR_FAIL_COND_V(p_index < 0, 0);
- ERR_FAIL_COND_V(p_index >= audio_stream_pool.size(), 0);
+ ERR_FAIL_INDEX_V(p_index, audio_stream_pool.size(), 0);
return audio_stream_pool[p_index].weight;
}
@@ -678,17 +699,14 @@ void AudioStreamRandomizer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "streams_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_streams_count", "get_streams_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_mode", PROPERTY_HINT_ENUM, "Random (Avoid Repeats),Random,Sequential"), "set_playback_mode", "get_playback_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0"), "set_random_volume_offset_db", "get_random_volume_offset_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db");
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS);
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM);
BIND_ENUM_CONSTANT(PLAYBACK_SEQUENTIAL);
}
-AudioStreamRandomizer::AudioStreamRandomizer() {
- random_pitch_scale = 1.1;
- random_volume_offset_db = 5;
-}
+AudioStreamRandomizer::AudioStreamRandomizer() {}
void AudioStreamPlaybackRandomizer::start(float p_from_pos) {
playing = playback;
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index ce9bcabb9c..bf200e7ecf 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -78,13 +78,18 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
AudioFrame internal_buffer[INTERNAL_BUFFER_LEN + CUBIC_INTERP_HISTORY];
unsigned int internal_buffer_end = -1;
- uint64_t mix_offset;
+ uint64_t mix_offset = 0;
protected:
- void _begin_resample();
+ void begin_resample();
// Returns the number of frames that were mixed.
- virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
- virtual float get_stream_sampling_rate() = 0;
+ virtual int _mix_internal(AudioFrame *p_buffer, int p_frames);
+ virtual float get_stream_sampling_rate();
+
+ GDVIRTUAL2R(int, _mix_resampled, GDNativePtr<AudioFrame>, int)
+ GDVIRTUAL0RC(float, _get_stream_sampling_rate)
+
+ static void _bind_methods();
public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
@@ -120,7 +125,7 @@ class AudioStreamMicrophone : public AudioStream {
GDCLASS(AudioStreamMicrophone, AudioStream);
friend class AudioStreamPlaybackMicrophone;
- Set<AudioStreamPlaybackMicrophone *> playbacks;
+ HashSet<AudioStreamPlaybackMicrophone *> playbacks;
protected:
static void _bind_methods();
@@ -140,8 +145,8 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlaybackResampled);
friend class AudioStreamMicrophone;
- bool active;
- unsigned int input_ofs;
+ bool active = false;
+ unsigned int input_ofs = 0;
Ref<AudioStreamMicrophone> microphone;
@@ -187,10 +192,10 @@ private:
float weight;
};
- Set<AudioStreamPlaybackRandomizer *> playbacks;
+ HashSet<AudioStreamPlaybackRandomizer *> playbacks;
Vector<PoolEntry> audio_stream_pool;
- float random_pitch_scale;
- float random_volume_offset_db;
+ float random_pitch_scale = 1.1f;
+ float random_volume_offset_db = 5.0f;
Ref<AudioStreamPlayback> instance_playback_random();
Ref<AudioStreamPlayback> instance_playback_no_repeats();
diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp
index b01160ea5c..87d46f8bbe 100644
--- a/servers/audio/effects/audio_effect_amplify.cpp
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -64,7 +64,7 @@ void AudioEffectAmplify::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_volume_db", "volume"), &AudioEffectAmplify::set_volume_db);
ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioEffectAmplify::get_volume_db);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_volume_db", "get_volume_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,0.01,suffix:dB"), "set_volume_db", "get_volume_db");
}
AudioEffectAmplify::AudioEffectAmplify() {
diff --git a/servers/audio/effects/audio_effect_capture.cpp b/servers/audio/effects/audio_effect_capture.cpp
index f605cfc9d4..1f5f5e259a 100644
--- a/servers/audio/effects/audio_effect_capture.cpp
+++ b/servers/audio/effects/audio_effect_capture.cpp
@@ -70,7 +70,7 @@ void AudioEffectCapture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer_length_frames"), &AudioEffectCapture::get_buffer_length_frames);
ClassDB::bind_method(D_METHOD("get_pushed_frames"), &AudioEffectCapture::get_pushed_frames);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}
Ref<AudioEffectInstance> AudioEffectCapture::instantiate() {
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 8b1fe9cfd2..e5434eac02 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -313,32 +313,32 @@ void AudioEffectChorus::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wet", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_wet", "get_wet");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 3);
}
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index f75d092dd3..ee71a6dba7 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -221,8 +221,8 @@ void AudioEffectCompressor::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "-60,0,0.1"), "set_threshold", "get_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio", PROPERTY_HINT_RANGE, "1,48,0.1"), "set_ratio", "get_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gain", PROPERTY_HINT_RANGE, "-20,20,0.1"), "set_gain", "get_gain");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attack_us", PROPERTY_HINT_RANGE, "20,2000,1"), "set_attack_us", "get_attack_us");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1"), "set_release_ms", "get_release_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attack_us", PROPERTY_HINT_RANGE, U"20,2000,1,suffix:\u00B5s"), "set_attack_us", "get_attack_us");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1,suffix:ms"), "set_release_ms", "get_release_ms");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_mix", "get_mix");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain");
}
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index 1909ab6eae..80e7a8223c 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -287,18 +287,18 @@ void AudioEffectDelay::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap1/active"), "set_tap1_active", "is_tap1_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_tap1_delay_ms", "get_tap1_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_tap1_level_db", "get_tap1_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap1_delay_ms", "get_tap1_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap1_level_db", "get_tap1_level_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap1_pan", "get_tap1_pan");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap2/active"), "set_tap2_active", "is_tap2_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_tap2_delay_ms", "get_tap2_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_tap2_level_db", "get_tap2_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap2_delay_ms", "get_tap2_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap2_level_db", "get_tap2_level_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap2_pan", "get_tap2_pan");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feedback/active"), "set_feedback_active", "is_feedback_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_feedback_delay_ms", "get_feedback_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_feedback_level_db", "get_feedback_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_feedback_delay_ms", "get_feedback_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_feedback_level_db", "get_feedback_level_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/lowpass", PROPERTY_HINT_RANGE, "1,16000,1"), "set_feedback_lowpass", "get_feedback_lowpass");
}
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index afc4353bd7..6820d796a4 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -161,7 +161,7 @@ void AudioEffectDistortion::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,Wave Shape"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_keep_hf_hz", "get_keep_hf_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain");
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index cc317031d4..b7c373479a 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -90,9 +90,9 @@ int AudioEffectEQ::get_band_count() const {
}
bool AudioEffectEQ::_set(const StringName &p_name, const Variant &p_value) {
- const Map<StringName, int>::Element *E = prop_band_map.find(p_name);
+ HashMap<StringName, int>::ConstIterator E = prop_band_map.find(p_name);
if (E) {
- set_band_gain_db(E->get(), p_value);
+ set_band_gain_db(E->value, p_value);
return true;
}
@@ -100,9 +100,9 @@ bool AudioEffectEQ::_set(const StringName &p_name, const Variant &p_value) {
}
bool AudioEffectEQ::_get(const StringName &p_name, Variant &r_ret) const {
- const Map<StringName, int>::Element *E = prop_band_map.find(p_name);
+ HashMap<StringName, int>::ConstIterator E = prop_band_map.find(p_name);
if (E) {
- r_ret = get_band_gain_db(E->get());
+ r_ret = get_band_gain_db(E->value);
return true;
}
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index 252f931e6c..9b0560223f 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -55,7 +55,7 @@ class AudioEffectEQ : public AudioEffect {
EQ eq;
Vector<float> gain;
- Map<StringName, int> prop_band_map;
+ HashMap<StringName, int> prop_band_map;
Vector<String> band_names;
protected:
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 06e66f22b1..a9409076cd 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -153,7 +153,7 @@ void AudioEffectFilter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_db", "amount"), &AudioEffectFilter::set_db);
ClassDB::bind_method(D_METHOD("get_db"), &AudioEffectFilter::get_db);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_cutoff", "get_cutoff");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_cutoff", "get_cutoff");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain");
ADD_PROPERTY(PropertyInfo(Variant::INT, "db", PROPERTY_HINT_ENUM, "6 dB,12 dB,18 dB,24 dB"), "set_db", "get_db");
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 5923cf8cf5..7bcd68d48b 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -120,9 +120,9 @@ void AudioEffectLimiter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_soft_clip_ratio", "soft_clip"), &AudioEffectLimiter::set_soft_clip_ratio);
ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"), &AudioEffectLimiter::get_soft_clip_ratio);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1"), "set_ceiling_db", "get_ceiling_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1"), "set_threshold_db", "get_threshold_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1"), "set_soft_clip_db", "get_soft_clip_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1,suffix:dB"), "set_ceiling_db", "get_ceiling_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1,suffix:dB"), "set_threshold_db", "get_threshold_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1,suffix:dB"), "set_soft_clip_db", "get_soft_clip_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_ratio", PROPERTY_HINT_RANGE, "3,20,0.1"), "set_soft_clip_ratio", "get_soft_clip_ratio");
}
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
index af5dce707e..2f86630ce9 100644
--- a/servers/audio/effects/audio_effect_phaser.cpp
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -144,9 +144,9 @@ void AudioEffectPhaser::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &AudioEffectPhaser::set_depth);
ClassDB::bind_method(D_METHOD("get_depth"), &AudioEffectPhaser::get_depth);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_min_hz", PROPERTY_HINT_RANGE, "10,10000"), "set_range_min_hz", "get_range_min_hz");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_max_hz", PROPERTY_HINT_RANGE, "10,10000"), "set_range_max_hz", "get_range_max_hz");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rate_hz", PROPERTY_HINT_RANGE, "0.01,20"), "set_rate_hz", "get_rate_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_min_hz", PROPERTY_HINT_RANGE, "10,10000,suffix:Hz"), "set_range_min_hz", "get_range_min_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_max_hz", PROPERTY_HINT_RANGE, "10,10000,suffix:Hz"), "set_range_max_hz", "get_range_max_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rate_hz", PROPERTY_HINT_RANGE, "0.01,20,suffix:Hz"), "set_rate_hz", "get_rate_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback", PROPERTY_HINT_RANGE, "0.1,0.9,0.1"), "set_feedback", "get_feedback");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_depth", "get_depth");
}
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index ba2d257c0a..3c53887931 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -74,7 +74,7 @@
*
*****************************************************************************/
-void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int64_t fftFrameSize, int64_t osamp, float sampleRate, float *indata, float *outdata,int stride) {
+void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata,int stride) {
/*
@@ -85,32 +85,19 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
*/
double magn, phase, tmp, window, real, imag;
- double freqPerBin, expct, reciprocalFftFrameSize;
- int64_t i,k, qpd, index, inFifoLatency, stepSize, fftFrameSize2;
+ double freqPerBin, expct;
+ long i,k, qpd, index, inFifoLatency, stepSize, fftFrameSize2;
/* set up some handy variables */
fftFrameSize2 = fftFrameSize/2;
- reciprocalFftFrameSize = 1./fftFrameSize;
stepSize = fftFrameSize/osamp;
- freqPerBin = reciprocalFftFrameSize * sampleRate;
- expct = Math_TAU * reciprocalFftFrameSize * stepSize;
+ freqPerBin = sampleRate/(double)fftFrameSize;
+ expct = 2.*Math_PI*(double)stepSize/(double)fftFrameSize;
inFifoLatency = fftFrameSize-stepSize;
- if (gRover == 0) {
- gRover = inFifoLatency;
- }
+ if (gRover == 0) { gRover = inFifoLatency;
+}
- // If pitchShift changes clear arrays to prevent some artifacts and quality loss.
- if (lastPitchShift != pitchShift) {
- lastPitchShift = pitchShift;
- memset(gInFIFO, 0, MAX_FRAME_LENGTH * sizeof(float));
- memset(gOutFIFO, 0, MAX_FRAME_LENGTH * sizeof(float));
- memset(gFFTworksp, 0, 2 * MAX_FRAME_LENGTH * sizeof(double));
- memset(gLastPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(double));
- memset(gSumPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(double));
- memset(gOutputAccum, 0, 2 * MAX_FRAME_LENGTH * sizeof(double));
- memset(gAnaFreq, 0, MAX_FRAME_LENGTH * sizeof(double));
- memset(gAnaMagn, 0, MAX_FRAME_LENGTH * sizeof(double));
- }
+ /* initialize our static arrays */
/* main processing loop */
for (i = 0; i < numSampsToProcess; i++){
@@ -125,7 +112,7 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
/* do windowing and re,im interleave */
for (k = 0; k < fftFrameSize;k++) {
- window = -.5*cos(Math_TAU * reciprocalFftFrameSize * k)+.5;
+ window = -.5*cos(2.*Math_PI*(double)k/(double)fftFrameSize)+.5;
gFFTworksp[2*k] = gInFIFO[k] * window;
gFFTworksp[2*k+1] = 0.;
}
@@ -137,7 +124,6 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
/* this is the analysis step */
for (k = 0; k <= fftFrameSize2; k++) {
-
/* de-interlace FFT buffer */
real = gFFTworksp[2*k];
imag = gFFTworksp[2*k+1];
@@ -155,15 +141,13 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
/* map delta phase into +/- Pi interval */
qpd = tmp/Math_PI;
- if (qpd >= 0) {
- qpd += qpd&1;
- } else {
- qpd -= qpd&1;
- }
+ if (qpd >= 0) { qpd += qpd&1;
+ } else { qpd -= qpd&1;
+}
tmp -= Math_PI*(double)qpd;
/* get deviation from bin frequency from the +/- Pi interval */
- tmp = osamp*tmp/Math_TAU;
+ tmp = osamp*tmp/(2.*Math_PI);
/* compute the k-th partials' true frequency */
tmp = (double)k*freqPerBin + tmp*freqPerBin;
@@ -176,8 +160,8 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
/* ***************** PROCESSING ******************* */
/* this does the actual pitch shifting */
- memset(gSynMagn, 0, fftFrameSize*sizeof(double));
- memset(gSynFreq, 0, fftFrameSize*sizeof(double));
+ memset(gSynMagn, 0, fftFrameSize*sizeof(float));
+ memset(gSynFreq, 0, fftFrameSize*sizeof(float));
for (k = 0; k <= fftFrameSize2; k++) {
index = k*pitchShift;
if (index <= fftFrameSize2) {
@@ -200,7 +184,7 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
tmp /= freqPerBin;
/* take osamp into account */
- tmp = Math_TAU*tmp/osamp;
+ tmp = 2.*Math_PI*tmp/osamp;
/* add the overlap phase advance back in */
tmp += (double)k*expct;
@@ -215,35 +199,33 @@ void SMBPitchShift::PitchShift(float pitchShift, int64_t numSampsToProcess, int6
}
/* zero negative frequencies */
- for (k = fftFrameSize+2; k < 2*MAX_FRAME_LENGTH; k++) {
- gFFTworksp[k] = 0.;
- }
+ for (k = fftFrameSize+2; k < 2*fftFrameSize; k++) { gFFTworksp[k] = 0.;
+}
/* do inverse transform */
smbFft(gFFTworksp, fftFrameSize, 1);
/* do windowing and add to output accumulator */
for(k=0; k < fftFrameSize; k++) {
- window = -.5*cos(Math_TAU * reciprocalFftFrameSize * k)+.5;
+ window = -.5*cos(2.*Math_PI*(double)k/(double)fftFrameSize)+.5;
gOutputAccum[k] += 2.*window*gFFTworksp[2*k]/(fftFrameSize2*osamp);
}
- for (k = 0; k < stepSize; k++) {
- gOutFIFO[k] = gOutputAccum[k];
- }
+ for (k = 0; k < stepSize; k++) { gOutFIFO[k] = gOutputAccum[k];
+}
/* shift accumulator */
- memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(double));
+ memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(float));
/* move input FIFO */
- for (k = 0; k < inFifoLatency; k++) {
- gInFIFO[k] = gInFIFO[k+stepSize];
- }
+ for (k = 0; k < inFifoLatency; k++) { gInFIFO[k] = gInFIFO[k+stepSize];
+}
}
}
}
-void SMBPitchShift::smbFft(double *fftBuffer, int64_t fftFrameSize, int64_t sign)
+
+void SMBPitchShift::smbFft(float *fftBuffer, long fftFrameSize, long sign)
/*
FFT routine, (C)1996 S.M.Bernsee. Sign = -1 is FFT, 1 is iFFT (inverse)
Fills fftBuffer[0...2*fftFrameSize-1] with the Fourier transform of the
@@ -256,16 +238,14 @@ void SMBPitchShift::smbFft(double *fftBuffer, int64_t fftFrameSize, int64_t sign
of the frequencies of interest is in fftBuffer[0...fftFrameSize].
*/
{
- double wr, wi, arg, *p1, *p2, temp;
- double tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
- int64_t i, bitm, j, le, le2, k, logN;
- logN = (int64_t)(log(fftFrameSize) / log(2.) + .5);
+ float wr, wi, arg, *p1, *p2, temp;
+ float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
+ long i, bitm, j, le, le2, k;
for (i = 2; i < 2*fftFrameSize-2; i += 2) {
for (bitm = 2, j = 0; bitm < 2*fftFrameSize; bitm <<= 1) {
- if (i & bitm) {
- j++;
- }
+ if (i & bitm) { j++;
+}
j <<= 1;
}
if (i < j) {
@@ -275,8 +255,7 @@ void SMBPitchShift::smbFft(double *fftBuffer, int64_t fftFrameSize, int64_t sign
*p1 = *p2; *p2 = temp;
}
}
-
- for (k = 0, le = 2; k < logN; k++) {
+ for (k = 0, le = 2; k < (long)(log((double)fftFrameSize)/log(2.)+.5); k++) {
le <<= 1;
le2 = le>>1;
ur = 1.0;
@@ -309,14 +288,6 @@ void SMBPitchShift::smbFft(double *fftBuffer, int64_t fftFrameSize, int64_t sign
void AudioEffectPitchShiftInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
float sample_rate = AudioServer::get_singleton()->get_mix_rate();
- // For pitch_scale 1.0 it's cheaper to just pass samples without processing them.
- if (Math::is_equal_approx(base->pitch_scale, 1.0f)) {
- for (int i = 0; i < p_frame_count; i++) {
- p_dst_frames[i] = p_src_frames[i];
- }
- return;
- }
-
float *in_l = (float *)p_src_frames;
float *in_r = in_l + 1;
@@ -390,4 +361,7 @@ AudioEffectPitchShift::AudioEffectPitchShift() {
pitch_scale = 1.0;
oversampling = 4;
fft_size = FFT_SIZE_2048;
+ wet = 0.0;
+ dry = 0.0;
+ filter = false;
}
diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h
index 23da61bb32..0478d05ceb 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.h
+++ b/servers/audio/effects/audio_effect_pitch_shift.h
@@ -40,33 +40,31 @@ class SMBPitchShift {
float gInFIFO[MAX_FRAME_LENGTH];
float gOutFIFO[MAX_FRAME_LENGTH];
- double gFFTworksp[2 * MAX_FRAME_LENGTH];
- double gLastPhase[MAX_FRAME_LENGTH / 2 + 1];
- double gSumPhase[MAX_FRAME_LENGTH / 2 + 1];
- double gOutputAccum[2 * MAX_FRAME_LENGTH];
- double gAnaFreq[MAX_FRAME_LENGTH];
- double gAnaMagn[MAX_FRAME_LENGTH];
- double gSynFreq[MAX_FRAME_LENGTH];
- double gSynMagn[MAX_FRAME_LENGTH];
- int64_t gRover;
- float lastPitchShift;
-
- void smbFft(double *fftBuffer, int64_t fftFrameSize, int64_t sign);
+ float gFFTworksp[2 * MAX_FRAME_LENGTH];
+ float gLastPhase[MAX_FRAME_LENGTH / 2 + 1];
+ float gSumPhase[MAX_FRAME_LENGTH / 2 + 1];
+ float gOutputAccum[2 * MAX_FRAME_LENGTH];
+ float gAnaFreq[MAX_FRAME_LENGTH];
+ float gAnaMagn[MAX_FRAME_LENGTH];
+ float gSynFreq[MAX_FRAME_LENGTH];
+ float gSynMagn[MAX_FRAME_LENGTH];
+ long gRover;
+
+ void smbFft(float *fftBuffer, long fftFrameSize, long sign);
public:
- void PitchShift(float pitchShift, int64_t numSampsToProcess, int64_t fftFrameSize, int64_t osamp, float sampleRate, float *indata, float *outdata, int stride);
+ void PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata, int stride);
SMBPitchShift() {
gRover = 0;
memset(gInFIFO, 0, MAX_FRAME_LENGTH * sizeof(float));
memset(gOutFIFO, 0, MAX_FRAME_LENGTH * sizeof(float));
- memset(gFFTworksp, 0, 2 * MAX_FRAME_LENGTH * sizeof(double));
- memset(gLastPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(double));
- memset(gSumPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(double));
- memset(gOutputAccum, 0, 2 * MAX_FRAME_LENGTH * sizeof(double));
- memset(gAnaFreq, 0, MAX_FRAME_LENGTH * sizeof(double));
- memset(gAnaMagn, 0, MAX_FRAME_LENGTH * sizeof(double));
- lastPitchShift = 1.0;
+ memset(gFFTworksp, 0, 2 * MAX_FRAME_LENGTH * sizeof(float));
+ memset(gLastPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(float));
+ memset(gSumPhase, 0, (MAX_FRAME_LENGTH / 2 + 1) * sizeof(float));
+ memset(gOutputAccum, 0, 2 * MAX_FRAME_LENGTH * sizeof(float));
+ memset(gAnaFreq, 0, MAX_FRAME_LENGTH * sizeof(float));
+ memset(gAnaMagn, 0, MAX_FRAME_LENGTH * sizeof(float));
}
};
@@ -103,6 +101,9 @@ public:
float pitch_scale;
int oversampling;
FFTSize fft_size;
+ float wet;
+ float dry;
+ bool filter;
protected:
static void _bind_methods();
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index a5866bb380..d68522e5b9 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -30,6 +30,11 @@
#include "audio_effect_record.h"
+#ifdef TOOLS_ENABLED
+// FIXME: This file shouldn't depend on editor stuff.
+#include "editor/import/resource_importer_wav.h"
+#endif
+
void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
if (!is_recording) {
for (int i = 0; i < p_frame_count; i++) {
@@ -57,7 +62,7 @@ void AudioEffectRecordInstance::_update_buffer() {
}
void AudioEffectRecordInstance::_update(void *userdata) {
- AudioEffectRecordInstance *ins = (AudioEffectRecordInstance *)userdata;
+ AudioEffectRecordInstance *ins = static_cast<AudioEffectRecordInstance *>(userdata);
ins->_update_buffer();
}
@@ -250,8 +255,12 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
Vector<uint8_t> bleft;
Vector<uint8_t> bright;
+#ifdef TOOLS_ENABLED
ResourceImporterWAV::_compress_ima_adpcm(left, bleft);
ResourceImporterWAV::_compress_ima_adpcm(right, bright);
+#else
+ ERR_PRINT("AudioEffectRecord cannot do IMA ADPCM compression at runtime.");
+#endif
int dl = bleft.size();
dst_data.resize(dl * 2);
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 18b5d4d83c..305484d1cb 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -35,7 +35,6 @@
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/os/thread.h"
-#include "editor/import/resource_importer_wav.h"
#include "scene/resources/audio_stream_sample.h"
#include "servers/audio/audio_effect.h"
#include "servers/audio_server.h"
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
index 0d4eb14e6a..bfc68152a4 100644
--- a/servers/audio/effects/audio_effect_reverb.cpp
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -176,7 +176,7 @@ void AudioEffectReverb::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_hpf"), &AudioEffectReverb::get_hpf);
ADD_GROUP("Predelay", "predelay_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1"), "set_predelay_msec", "get_predelay_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1,suffix:ms"), "set_predelay_msec", "get_predelay_msec");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_feedback", PROPERTY_HINT_RANGE, "0,0.98,0.01"), "set_predelay_feedback", "get_predelay_feedback");
ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "room_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_room_size", "get_room_size");
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
index 10627be74c..30ebf626ae 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -264,7 +264,7 @@ void AudioEffectSpectrumAnalyzer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size);
ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1,suffix:s"), "set_buffer_length", "get_buffer_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size");
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
index c81efc55e2..e567add3e7 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.cpp
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -29,7 +29,9 @@
/*************************************************************************/
#include "audio_effect_stereo_enhance.h"
+
#include "servers/audio_server.h"
+
void AudioEffectStereoEnhanceInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
float intensity = base->pan_pullout;
bool surround_mode = base->surround > 0;
@@ -136,12 +138,8 @@ void AudioEffectStereoEnhance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_surround"), &AudioEffectStereoEnhance::get_surround);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pan_pullout", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_pan_pullout", "get_pan_pullout");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_pullout_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_time_pullout", "get_time_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_pullout_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_time_pullout", "get_time_pullout");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "surround", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_surround", "get_surround");
}
-AudioEffectStereoEnhance::AudioEffectStereoEnhance() {
- pan_pullout = 1;
- time_pullout = 0;
- surround = 0;
-}
+AudioEffectStereoEnhance::AudioEffectStereoEnhance() {}
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h
index 8b8b7b47a0..30ea11f625 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.h
+++ b/servers/audio/effects/audio_effect_stereo_enhance.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTSTEREOENHANCE_H
-#define AUDIOEFFECTSTEREOENHANCE_H
+#ifndef AUDIO_EFFECT_STEREO_ENHANCE_H
+#define AUDIO_EFFECT_STEREO_ENHANCE_H
#include "servers/audio/audio_effect.h"
@@ -44,9 +44,9 @@ class AudioEffectStereoEnhanceInstance : public AudioEffectInstance {
MAX_DELAY_MS = 50
};
- float *delay_ringbuff;
- unsigned int ringbuff_pos;
- unsigned int ringbuff_mask;
+ float *delay_ringbuff = nullptr;
+ unsigned int ringbuff_pos = 0;
+ unsigned int ringbuff_mask = 0;
public:
virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) override;
@@ -58,11 +58,11 @@ class AudioEffectStereoEnhance : public AudioEffect {
GDCLASS(AudioEffectStereoEnhance, AudioEffect);
friend class AudioEffectStereoEnhanceInstance;
- float volume_db;
+ float volume_db = 0.0f;
- float pan_pullout;
- float time_pullout;
- float surround;
+ float pan_pullout = 1.0f;
+ float time_pullout = 0.0f;
+ float surround = 0.0f;
protected:
static void _bind_methods();
@@ -82,4 +82,4 @@ public:
AudioEffectStereoEnhance();
};
-#endif // AUDIOEFFECTSTEREOENHANCE_H
+#endif // AUDIO_EFFECT_STEREO_ENHANCE_H
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index 6c917f3eb6..46de1692e4 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -75,8 +75,8 @@ void AudioStreamGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioStreamGenerator::set_buffer_length);
ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioStreamGenerator::get_buffer_length);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1,suffix:Hz"), "set_mix_rate", "get_mix_rate");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}
AudioStreamGenerator::AudioStreamGenerator() {
@@ -169,7 +169,7 @@ float AudioStreamGeneratorPlayback::get_stream_sampling_rate() {
void AudioStreamGeneratorPlayback::start(float p_from_pos) {
if (mixed == 0.0) {
- _begin_resample();
+ begin_resample();
}
skips = 0;
active = true;
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 51288262b3..2ce4b95fcf 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -65,7 +65,7 @@ class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled {
int skips;
bool active;
float mixed;
- AudioStreamGenerator *generator;
+ AudioStreamGenerator *generator = nullptr;
protected:
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
index 4b5b9ab79f..adfd648514 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2006
-
#include "reverb.h"
#include "core/math/math_funcs.h"
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h
index ff59ab8d82..c9602c5b5a 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb.h
@@ -75,12 +75,13 @@ private:
Comb comb[MAX_COMBS];
AllPass allpass[MAX_ALLPASS];
- float *input_buffer;
+ float *input_buffer = nullptr;
float *echo_buffer = nullptr;
- int echo_buffer_size;
- int echo_buffer_pos;
+ int echo_buffer_size = 0;
+ int echo_buffer_pos = 0;
- float hpf_h1, hpf_h2 = 0;
+ float hpf_h1 = 0.0f;
+ float hpf_h2 = 0.0f;
struct Parameters {
float room_size;
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 9d83e5cacc..8ec3e469d3 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -164,17 +164,6 @@ Array AudioDriver::capture_get_device_list() {
return list;
}
-AudioDriver::AudioDriver() {
- _last_mix_time = 0;
- _last_mix_frames = 0;
- input_position = 0;
- input_size = 0;
-
-#ifdef DEBUG_ENABLED
- prof_time = 0;
-#endif
-}
-
AudioDriverDummy AudioDriverManager::dummy_driver;
AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS] = {
&AudioDriverManager::dummy_driver,
@@ -1117,13 +1106,13 @@ float AudioServer::get_playback_speed_scale() const {
void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) {
ERR_FAIL_COND(p_playback.is_null());
- Map<StringName, Vector<AudioFrame>> map;
+ HashMap<StringName, Vector<AudioFrame>> map;
map[p_bus] = p_volume_db_vector;
start_playback_stream(p_playback, map, p_start_time, p_pitch_scale);
}
-void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) {
+void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) {
ERR_FAIL_COND(p_playback.is_null());
AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode();
@@ -1184,13 +1173,13 @@ void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) {
void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes) {
ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);
- Map<StringName, Vector<AudioFrame>> map;
+ HashMap<StringName, Vector<AudioFrame>> map;
map[p_bus] = p_volumes;
set_playback_bus_volumes_linear(p_playback, map);
}
-void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes) {
+void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes) {
ERR_FAIL_COND(p_bus_volumes.size() > MAX_BUSES_PER_PLAYBACK);
AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
@@ -1226,7 +1215,7 @@ void AudioServer::set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p
ERR_FAIL_COND(p_playback.is_null());
ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);
- Map<StringName, Vector<AudioFrame>> map;
+ HashMap<StringName, Vector<AudioFrame>> map;
AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback);
if (!playback_node) {
@@ -1343,6 +1332,7 @@ void AudioServer::init_channels_and_buffers() {
for (int j = 0; j < channel_count; j++) {
buses.write[i]->channels.write[j].buffer.resize(buffer_size);
}
+ _update_bus_effects(i);
}
}
@@ -1747,15 +1737,6 @@ void AudioServer::_bind_methods() {
AudioServer::AudioServer() {
singleton = this;
- mix_frames = 0;
- channel_count = 0;
- to_mix = 0;
-#ifdef DEBUG_ENABLED
- prof_time = 0;
-#endif
- mix_time = 0;
- mix_size = 0;
- playback_speed_scale = 1;
}
AudioServer::~AudioServer() {
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 0c150427f2..18e173ff0b 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -48,18 +48,18 @@ class AudioStreamPlayback;
class AudioDriver {
static AudioDriver *singleton;
- uint64_t _last_mix_time;
- uint64_t _last_mix_frames;
+ uint64_t _last_mix_time = 0;
+ uint64_t _last_mix_frames = 0;
#ifdef DEBUG_ENABLED
- uint64_t prof_ticks;
- uint64_t prof_time;
+ uint64_t prof_ticks = 0;
+ uint64_t prof_time = 0;
#endif
protected:
Vector<int32_t> input_buffer;
- unsigned int input_position;
- unsigned int input_size;
+ unsigned int input_position = 0;
+ unsigned int input_size = 0;
void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true);
void update_mix_time(int p_frames);
@@ -121,7 +121,7 @@ public:
void reset_profiling_time() { prof_time = 0; }
#endif
- AudioDriver();
+ AudioDriver() {}
virtual ~AudioDriver() {}
};
@@ -169,66 +169,61 @@ public:
typedef void (*AudioCallback)(void *p_userdata);
private:
- uint64_t mix_time;
- int mix_size;
+ uint64_t mix_time = 0;
+ int mix_size = 0;
- uint32_t buffer_size;
- uint64_t mix_count;
- uint64_t mix_frames;
+ uint32_t buffer_size = 0;
+ uint64_t mix_count = 0;
+ uint64_t mix_frames = 0;
#ifdef DEBUG_ENABLED
- uint64_t prof_time;
+ uint64_t prof_time = 0;
#endif
- float channel_disable_threshold_db;
- uint32_t channel_disable_frames;
+ float channel_disable_threshold_db = 0.0f;
+ uint32_t channel_disable_frames = 0;
- int channel_count;
- int to_mix;
+ int channel_count = 0;
+ int to_mix = 0;
- float playback_speed_scale;
+ float playback_speed_scale = 1.0f;
struct Bus {
StringName name;
- bool solo;
- bool mute;
- bool bypass;
+ bool solo = false;
+ bool mute = false;
+ bool bypass = false;
- bool soloed;
+ bool soloed = false;
- //Each channel is a stereo pair.
+ // Each channel is a stereo pair.
struct Channel {
- bool used;
- bool active;
- AudioFrame peak_volume;
+ bool used = false;
+ bool active = false;
+ AudioFrame peak_volume = AudioFrame(AUDIO_MIN_PEAK_DB, AUDIO_MIN_PEAK_DB);
Vector<AudioFrame> buffer;
Vector<Ref<AudioEffectInstance>> effect_instances;
- uint64_t last_mix_with_audio;
- Channel() {
- last_mix_with_audio = 0;
- used = false;
- active = false;
- peak_volume = AudioFrame(AUDIO_MIN_PEAK_DB, AUDIO_MIN_PEAK_DB);
- }
+ uint64_t last_mix_with_audio = 0;
+ Channel() {}
};
Vector<Channel> channels;
struct Effect {
Ref<AudioEffect> effect;
- bool enabled;
+ bool enabled = false;
#ifdef DEBUG_ENABLED
- uint64_t prof_time;
+ uint64_t prof_time = 0;
#endif
};
Vector<Effect> effects;
- float volume_db;
+ float volume_db = 0.0f;
StringName send;
- int index_cache;
+ int index_cache = 0;
};
struct AudioStreamPlaybackBusDetails {
- bool bus_active[MAX_BUSES_PER_PLAYBACK] = { false, false, false, false, false, false };
+ bool bus_active[MAX_BUSES_PER_PLAYBACK] = {};
StringName bus[MAX_BUSES_PER_PLAYBACK];
AudioFrame volume[MAX_BUSES_PER_PLAYBACK][MAX_CHANNELS_PER_BUS];
};
@@ -268,7 +263,7 @@ private:
Vector<Vector<AudioFrame>> temp_buffer; //temp_buffer for each level
Vector<AudioFrame> mix_buffer;
Vector<Bus *> buses;
- Map<StringName, Bus *> bus_map;
+ HashMap<StringName, Bus *> bus_map;
void _update_bus_effects(int p_bus);
@@ -284,7 +279,7 @@ private:
struct CallbackItem {
AudioCallback callback;
- void *userdata;
+ void *userdata = nullptr;
};
SafeList<CallbackItem *> update_callback_list;
@@ -312,7 +307,7 @@ public:
ERR_FAIL_V(1);
}
- //do not use from outside audio thread
+ // Do not use from outside audio thread.
bool thread_has_channel_mix_buffer(int p_bus, int p_buffer) const;
AudioFrame *thread_get_channel_mix_buffer(int p_bus, int p_buffer);
int thread_get_mix_buffer_size() const;
@@ -370,11 +365,11 @@ public:
// Convenience method.
void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1);
// Expose all parameters.
- void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0);
+ void start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0);
void stop_playback_stream(Ref<AudioStreamPlayback> p_playback);
void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes);
- void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes);
+ void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes);
void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes);
void set_playback_pitch_scale(Ref<AudioStreamPlayback> p_playback, float p_pitch_scale);
void set_playback_paused(Ref<AudioStreamPlayback> p_playback, bool p_paused);
@@ -442,26 +437,21 @@ class AudioBusLayout : public Resource {
struct Bus {
StringName name;
- bool solo;
- bool mute;
- bool bypass;
+ bool solo = false;
+ bool mute = false;
+ bool bypass = false;
struct Effect {
Ref<AudioEffect> effect;
- bool enabled;
+ bool enabled = false;
};
Vector<Effect> effects;
- float volume_db;
+ float volume_db = 0.0f;
StringName send;
- Bus() {
- solo = false;
- mute = false;
- bypass = false;
- volume_db = 0;
- }
+ Bus() {}
};
Vector<Bus> buses;
diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp
index 3aab995857..624c06ecf1 100644
--- a/servers/camera/camera_feed.cpp
+++ b/servers/camera/camera_feed.cpp
@@ -33,7 +33,7 @@
#include "servers/rendering_server.h"
void CameraFeed::_bind_methods() {
- // The setters prefixed with _ are only exposed so we can have feeds through GDNative!
+ // The setters prefixed with _ are only exposed so we can have feeds through GDExtension!
// They should not be called by the end user.
ClassDB::bind_method(D_METHOD("get_id"), &CameraFeed::get_id);
diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp
index d1391937d9..222b475be8 100644
--- a/servers/debugger/servers_debugger.cpp
+++ b/servers/debugger/servers_debugger.cpp
@@ -89,7 +89,7 @@ Array ServersDebugger::ServersProfilerFrame::serialize() {
Array arr;
arr.push_back(frame_number);
arr.push_back(frame_time);
- arr.push_back(idle_time);
+ arr.push_back(process_time);
arr.push_back(physics_time);
arr.push_back(physics_frame_time);
arr.push_back(script_time);
@@ -120,7 +120,7 @@ bool ServersDebugger::ServersProfilerFrame::deserialize(const Array &p_arr) {
CHECK_SIZE(p_arr, 7, "ServersProfilerFrame");
frame_number = p_arr[0];
frame_time = p_arr[1];
- idle_time = p_arr[2];
+ process_time = p_arr[2];
physics_time = p_arr[3];
physics_frame_time = p_arr[4];
script_time = p_arr[5];
@@ -199,7 +199,7 @@ class ServersDebugger::ScriptsProfiler : public EngineProfiler {
};
Vector<ScriptLanguage::ProfilingInfo> info;
Vector<ScriptLanguage::ProfilingInfo *> ptrs;
- Map<StringName, int> sig_map;
+ HashMap<StringName, int> sig_map;
int max_frame_functions = 16;
public:
@@ -277,11 +277,11 @@ class ServersDebugger::ServersProfiler : public EngineProfiler {
typedef ServersDebugger::ServerInfo ServerInfo;
typedef ServersDebugger::ServerFunctionInfo ServerFunctionInfo;
- Map<StringName, ServerInfo> server_data;
+ HashMap<StringName, ServerInfo> server_data;
ScriptsProfiler scripts_profiler;
double frame_time = 0;
- double idle_time = 0;
+ double process_time = 0;
double physics_time = 0;
double physics_frame_time = 0;
@@ -289,16 +289,16 @@ class ServersDebugger::ServersProfiler : public EngineProfiler {
ServersDebugger::ServersProfilerFrame frame;
frame.frame_number = Engine::get_singleton()->get_process_frames();
frame.frame_time = frame_time;
- frame.idle_time = idle_time;
+ frame.process_time = process_time;
frame.physics_time = physics_time;
frame.physics_frame_time = physics_frame_time;
- Map<StringName, ServerInfo>::Element *E = server_data.front();
+ HashMap<StringName, ServerInfo>::Iterator E = server_data.begin();
while (E) {
if (!p_final) {
- frame.servers.push_back(E->get());
+ frame.servers.push_back(E->value);
}
- E->get().functions.clear();
- E = E->next();
+ E->value.functions.clear();
+ ++E;
}
uint64_t time = 0;
scripts_profiler.write_frame_data(frame.script_functions, time, p_final);
@@ -340,9 +340,9 @@ public:
srv.functions.push_back(fi);
}
- void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
frame_time = p_frame_time;
- idle_time = p_idle_time;
+ process_time = p_process_time;
physics_time = p_physics_time;
physics_frame_time = p_physics_frame_time;
_send_frame_data(false);
@@ -357,7 +357,7 @@ class ServersDebugger::VisualProfiler : public EngineProfiler {
typedef ServersDebugger::ServerInfo ServerInfo;
typedef ServersDebugger::ServerFunctionInfo ServerFunctionInfo;
- Map<StringName, ServerInfo> server_data;
+ HashMap<StringName, ServerInfo> server_data;
public:
void toggle(bool p_enable, const Array &p_opts) {
@@ -366,7 +366,7 @@ public:
void add(const Array &p_data) {}
- void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
Vector<RS::FrameProfileArea> profile_areas = RS::get_singleton()->get_frame_profile();
ServersDebugger::VisualProfilerFrame frame;
if (!profile_areas.size()) {
diff --git a/servers/debugger/servers_debugger.h b/servers/debugger/servers_debugger.h
index d1c55dc690..f949c436e7 100644
--- a/servers/debugger/servers_debugger.h
+++ b/servers/debugger/servers_debugger.h
@@ -85,7 +85,7 @@ public:
struct ServersProfilerFrame {
int frame_number = 0;
double frame_time = 0;
- double idle_time = 0;
+ double process_time = 0;
double physics_time = 0;
double physics_frame_time = 0;
double script_time = 0;
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 819c151087..59f88844e9 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -44,22 +44,52 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa
int DisplayServer::server_create_count = 1;
-void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) {
+void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
}
-void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) {
+void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
}
-void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu) {
+void DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
}
-void DisplayServer::global_menu_add_separator(const String &p_menu_root) {
+void DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
}
+void DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
+}
+
+int DisplayServer::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
+}
+
void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) {
WARN_PRINT("Global menus not supported by this display server.");
}
@@ -74,26 +104,61 @@ bool DisplayServer::global_menu_is_item_checkable(const String &p_menu_root, int
return false;
}
-Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, int p_idx) {
+bool DisplayServer::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return false;
+}
+
+Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const {
WARN_PRINT("Global menus not supported by this display server.");
return Callable();
}
-Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) {
+Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const {
WARN_PRINT("Global menus not supported by this display server.");
return Variant();
}
-String DisplayServer::global_menu_get_item_text(const String &p_menu_root, int p_idx) {
+String DisplayServer::global_menu_get_item_text(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return String();
+}
+
+String DisplayServer::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const {
WARN_PRINT("Global menus not supported by this display server.");
return String();
}
-String DisplayServer::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) {
+Key DisplayServer::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return Key::NONE;
+}
+
+bool DisplayServer::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return false;
+}
+
+String DisplayServer::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const {
WARN_PRINT("Global menus not supported by this display server.");
return String();
}
+int DisplayServer::global_menu_get_item_state(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
+}
+
+int DisplayServer::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
+}
+
+Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return Ref<Texture2D>();
+}
+
void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) {
WARN_PRINT("Global menus not supported by this display server.");
}
@@ -102,6 +167,10 @@ void DisplayServer::global_menu_set_item_checkable(const String &p_menu_root, in
WARN_PRINT("Global menus not supported by this display server.");
}
+void DisplayServer::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
void DisplayServer::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) {
WARN_PRINT("Global menus not supported by this display server.");
}
@@ -114,6 +183,30 @@ void DisplayServer::global_menu_set_item_submenu(const String &p_menu_root, int
WARN_PRINT("Global menus not supported by this display server.");
}
+void DisplayServer::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
+void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const {
WARN_PRINT("Global menus not supported by this display server.");
return 0;
@@ -127,6 +220,81 @@ void DisplayServer::global_menu_clear(const String &p_menu_root) {
WARN_PRINT("Global menus not supported by this display server.");
}
+bool DisplayServer::tts_is_speaking() const {
+ WARN_PRINT("TTS is not supported by this display server.");
+ return false;
+}
+
+bool DisplayServer::tts_is_paused() const {
+ WARN_PRINT("TTS is not supported by this display server.");
+ return false;
+}
+
+void DisplayServer::tts_pause() {
+ WARN_PRINT("TTS is not supported by this display server.");
+}
+
+void DisplayServer::tts_resume() {
+ WARN_PRINT("TTS is not supported by this display server.");
+}
+
+Array DisplayServer::tts_get_voices() const {
+ WARN_PRINT("TTS is not supported by this display server.");
+ return Array();
+}
+
+PackedStringArray DisplayServer::tts_get_voices_for_language(const String &p_language) const {
+ PackedStringArray ret;
+ Array voices = tts_get_voices();
+ for (int i = 0; i < voices.size(); i++) {
+ const Dictionary &voice = voices[i];
+ if (voice.has("id") && voice.has("language") && voice["language"].operator String().begins_with(p_language)) {
+ ret.push_back(voice["id"]);
+ }
+ }
+ return ret;
+}
+
+void DisplayServer::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
+ WARN_PRINT("TTS is not supported by this display server.");
+}
+
+void DisplayServer::tts_stop() {
+ WARN_PRINT("TTS is not supported by this display server.");
+}
+
+void DisplayServer::tts_set_utterance_callback(TTSUtteranceEvent p_event, const Callable &p_callable) {
+ ERR_FAIL_INDEX(p_event, DisplayServer::TTS_UTTERANCE_MAX);
+ utterance_callback[p_event] = p_callable;
+}
+
+void DisplayServer::tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id, int p_pos) {
+ ERR_FAIL_INDEX(p_event, DisplayServer::TTS_UTTERANCE_MAX);
+ switch (p_event) {
+ case DisplayServer::TTS_UTTERANCE_STARTED:
+ case DisplayServer::TTS_UTTERANCE_ENDED:
+ case DisplayServer::TTS_UTTERANCE_CANCELED: {
+ if (utterance_callback[p_event].is_valid()) {
+ Variant args[1];
+ args[0] = p_id;
+ const Variant *argp[] = { &args[0] };
+ utterance_callback[p_event].call_deferred(argp, 1); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
+ }
+ } break;
+ case DisplayServer::TTS_UTTERANCE_BOUNDARY: {
+ if (utterance_callback[p_event].is_valid()) {
+ Variant args[2];
+ args[0] = p_pos;
+ args[1] = p_id;
+ const Variant *argp[] = { &args[0], &args[1] };
+ utterance_callback[p_event].call_deferred(argp, 2); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
+ }
+ } break;
+ default:
+ break;
+ }
+}
+
void DisplayServer::mouse_set_mode(MouseMode p_mode) {
WARN_PRINT("Mouse is not supported by this display server.");
}
@@ -135,7 +303,7 @@ DisplayServer::MouseMode DisplayServer::mouse_get_mode() const {
return MOUSE_MODE_VISIBLE;
}
-void DisplayServer::mouse_warp_to_position(const Point2i &p_to) {
+void DisplayServer::warp_mouse(const Point2i &p_position) {
WARN_PRINT("Mouse warping is not supported by this display server.");
}
@@ -253,7 +421,7 @@ DisplayServer::CursorShape DisplayServer::cursor_get_shape() const {
return CURSOR_ARROW;
}
-void DisplayServer::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+void DisplayServer::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
WARN_PRINT("Custom cursor shape not supported by this display server.");
}
@@ -341,32 +509,67 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature);
ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name);
- ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag"), &DisplayServer::global_menu_add_item, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag"), &DisplayServer::global_menu_add_check_item, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu"), &DisplayServer::global_menu_add_submenu_item);
- ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root"), &DisplayServer::global_menu_add_separator);
+ ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_icon_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_icon_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_radio_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_radio_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_icon_radio_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_radio_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_multistate_item", "menu_root", "labe", "max_states", "default_state", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu", "index"), &DisplayServer::global_menu_add_submenu_item, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root", "index"), &DisplayServer::global_menu_add_separator, DEFVAL(-1));
+
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_index_from_text", "menu_root", "text"), &DisplayServer::global_menu_get_item_index_from_text);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_index_from_tag", "menu_root", "tag"), &DisplayServer::global_menu_get_item_index_from_tag);
ClassDB::bind_method(D_METHOD("global_menu_is_item_checked", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checked);
ClassDB::bind_method(D_METHOD("global_menu_is_item_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checkable);
+ ClassDB::bind_method(D_METHOD("global_menu_is_item_radio_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_radio_checkable);
ClassDB::bind_method(D_METHOD("global_menu_get_item_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_callback);
ClassDB::bind_method(D_METHOD("global_menu_get_item_tag", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tag);
ClassDB::bind_method(D_METHOD("global_menu_get_item_text", "menu_root", "idx"), &DisplayServer::global_menu_get_item_text);
ClassDB::bind_method(D_METHOD("global_menu_get_item_submenu", "menu_root", "idx"), &DisplayServer::global_menu_get_item_submenu);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_accelerator", "menu_root", "idx"), &DisplayServer::global_menu_get_item_accelerator);
+ ClassDB::bind_method(D_METHOD("global_menu_is_item_disabled", "menu_root", "idx"), &DisplayServer::global_menu_is_item_disabled);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_tooltip", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tooltip);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_icon", "menu_root", "idx"), &DisplayServer::global_menu_get_item_icon);
ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked);
ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_radio_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_radio_checkable);
ClassDB::bind_method(D_METHOD("global_menu_set_item_callback", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_callback);
ClassDB::bind_method(D_METHOD("global_menu_set_item_tag", "menu_root", "idx", "tag"), &DisplayServer::global_menu_set_item_tag);
ClassDB::bind_method(D_METHOD("global_menu_set_item_text", "menu_root", "idx", "text"), &DisplayServer::global_menu_set_item_text);
ClassDB::bind_method(D_METHOD("global_menu_set_item_submenu", "menu_root", "idx", "submenu"), &DisplayServer::global_menu_set_item_submenu);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_accelerator", "menu_root", "idx", "keycode"), &DisplayServer::global_menu_set_item_accelerator);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_disabled", "menu_root", "idx", "disabled"), &DisplayServer::global_menu_set_item_disabled);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_tooltip", "menu_root", "idx", "tooltip"), &DisplayServer::global_menu_set_item_tooltip);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_icon", "menu_root", "idx", "icon"), &DisplayServer::global_menu_set_item_icon);
ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item);
ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear);
+ ClassDB::bind_method(D_METHOD("tts_is_speaking"), &DisplayServer::tts_is_speaking);
+ ClassDB::bind_method(D_METHOD("tts_is_paused"), &DisplayServer::tts_is_paused);
+ ClassDB::bind_method(D_METHOD("tts_get_voices"), &DisplayServer::tts_get_voices);
+ ClassDB::bind_method(D_METHOD("tts_get_voices_for_language", "language"), &DisplayServer::tts_get_voices_for_language);
+
+ ClassDB::bind_method(D_METHOD("tts_speak", "text", "voice", "volume", "pitch", "rate", "utterance_id", "interrupt"), &DisplayServer::tts_speak, DEFVAL(50), DEFVAL(1.f), DEFVAL(1.f), DEFVAL(0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("tts_pause"), &DisplayServer::tts_pause);
+ ClassDB::bind_method(D_METHOD("tts_resume"), &DisplayServer::tts_resume);
+ ClassDB::bind_method(D_METHOD("tts_stop"), &DisplayServer::tts_stop);
+
+ ClassDB::bind_method(D_METHOD("tts_set_utterance_callback", "event", "callable"), &DisplayServer::tts_set_utterance_callback);
+ ClassDB::bind_method(D_METHOD("_tts_post_utterance_event", "event", "id", "char_pos"), &DisplayServer::tts_post_utterance_event);
+
ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode);
ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode);
- ClassDB::bind_method(D_METHOD("mouse_warp_to_position", "position"), &DisplayServer::mouse_warp_to_position);
+ ClassDB::bind_method(D_METHOD("warp_mouse", "position"), &DisplayServer::warp_mouse);
ClassDB::bind_method(D_METHOD("mouse_get_position"), &DisplayServer::mouse_get_position);
ClassDB::bind_method(D_METHOD("mouse_get_button_state"), &DisplayServer::mouse_get_button_state);
@@ -376,6 +579,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary);
ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary);
+ ClassDB::bind_method(D_METHOD("get_display_cutouts"), &DisplayServer::get_display_cutouts);
+ ClassDB::bind_method(D_METHOD("get_display_safe_area"), &DisplayServer::get_display_safe_area);
+
ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count);
ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_size", "screen"), &DisplayServer::screen_get_size, DEFVAL(SCREEN_OF_MAIN_WINDOW));
@@ -506,6 +712,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_ORIENTATION);
BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS);
BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY);
+ BIND_ENUM_CONSTANT(FEATURE_TEXT_TO_SPEECH);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
@@ -574,6 +781,11 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(DISPLAY_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_VIEW);
+
+ BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED);
+ BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED);
+ BIND_ENUM_CONSTANT(TTS_UTTERANCE_CANCELED);
+ BIND_ENUM_CONSTANT(TTS_UTTERANCE_BOUNDARY);
}
void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers) {
@@ -614,14 +826,14 @@ Input::MouseMode DisplayServer::_input_get_mouse_mode() {
}
void DisplayServer::_input_warp(const Vector2 &p_to_pos) {
- singleton->mouse_warp_to_position(p_to_pos);
+ singleton->warp_mouse(p_to_pos);
}
Input::CursorShape DisplayServer::_input_get_current_cursor_shape() {
return (Input::CursorShape)singleton->cursor_get_shape();
}
-void DisplayServer::_input_set_custom_mouse_cursor_func(const RES &p_image, Input::CursorShape p_shape, const Vector2 &p_hostspot) {
+void DisplayServer::_input_set_custom_mouse_cursor_func(const Ref<Resource> &p_image, Input::CursorShape p_shape, const Vector2 &p_hostspot) {
singleton->cursor_set_custom_image(p_image, (CursorShape)p_shape, p_hostspot);
}
diff --git a/servers/display_server.h b/servers/display_server.h
index 67dbab0924..7a15df2f92 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -80,7 +80,7 @@ private:
static Input::MouseMode _input_get_mouse_mode();
static void _input_warp(const Vector2 &p_to_pos);
static Input::CursorShape _input_get_current_cursor_shape();
- static void _input_set_custom_mouse_cursor_func(const RES &, Input::CursorShape, const Vector2 &p_hostspot);
+ static void _input_set_custom_mouse_cursor_func(const Ref<Resource> &, Input::CursorShape, const Vector2 &p_hostspot);
protected:
static void _bind_methods();
@@ -121,35 +121,92 @@ public:
FEATURE_SWAP_BUFFERS,
FEATURE_KEEP_SCREEN_ON,
FEATURE_CLIPBOARD_PRIMARY,
+ FEATURE_TEXT_TO_SPEECH,
};
virtual bool has_feature(Feature p_feature) const = 0;
virtual String get_name() const = 0;
- virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant());
- virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant());
- virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu);
- virtual void global_menu_add_separator(const String &p_menu_root);
+ virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1);
+ virtual void global_menu_add_separator(const String &p_menu_root, int p_index = -1);
+
+ virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const;
+ virtual int global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const;
virtual bool global_menu_is_item_checked(const String &p_menu_root, int p_idx) const;
virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const;
- virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx);
- virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx);
- virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx);
- virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx);
+ virtual bool global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const;
+ virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx) const;
+ virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx) const;
+ virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx) const;
+ virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const;
+ virtual Key global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const;
+ virtual bool global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const;
+ virtual String global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const;
+ virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const;
+ virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const;
+ virtual Ref<Texture2D> global_menu_get_item_icon(const String &p_menu_root, int p_idx) const;
virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked);
virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable);
+ virtual void global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable);
virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback);
virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag);
virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text);
virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu);
+ virtual void global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode);
+ virtual void global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled);
+ virtual void global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip);
+ virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state);
+ virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states);
+ virtual void global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon);
virtual int global_menu_get_item_count(const String &p_menu_root) const;
virtual void global_menu_remove_item(const String &p_menu_root, int p_idx);
virtual void global_menu_clear(const String &p_menu_root);
+ struct TTSUtterance {
+ String text;
+ String voice;
+ int volume = 50;
+ float pitch = 1.f;
+ float rate = 1.f;
+ int id = 0;
+ };
+
+ enum TTSUtteranceEvent {
+ TTS_UTTERANCE_STARTED,
+ TTS_UTTERANCE_ENDED,
+ TTS_UTTERANCE_CANCELED,
+ TTS_UTTERANCE_BOUNDARY,
+ TTS_UTTERANCE_MAX,
+ };
+
+private:
+ Callable utterance_callback[TTS_UTTERANCE_MAX];
+
+public:
+ virtual bool tts_is_speaking() const;
+ virtual bool tts_is_paused() const;
+ virtual Array tts_get_voices() const;
+ virtual PackedStringArray tts_get_voices_for_language(const String &p_language) const;
+
+ virtual void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.f, float p_rate = 1.f, int p_utterance_id = 0, bool p_interrupt = false);
+ virtual void tts_pause();
+ virtual void tts_resume();
+ virtual void tts_stop();
+
+ virtual void tts_set_utterance_callback(TTSUtteranceEvent p_event, const Callable &p_callable);
+ virtual void tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id, int p_pos = 0);
+
enum MouseMode {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
@@ -161,7 +218,7 @@ public:
virtual void mouse_set_mode(MouseMode p_mode);
virtual MouseMode mouse_get_mode() const;
- virtual void mouse_warp_to_position(const Point2i &p_to);
+ virtual void warp_mouse(const Point2i &p_position);
virtual Point2i mouse_get_position() const;
virtual MouseButton mouse_get_button_state() const;
@@ -171,6 +228,9 @@ public:
virtual void clipboard_set_primary(const String &p_text);
virtual String clipboard_get_primary() const;
+ virtual Array get_display_cutouts() const { return Array(); }
+ virtual Rect2i get_display_safe_area() const { return screen_get_usable_rect(); }
+
enum {
SCREEN_OF_MAIN_WINDOW = -1
};
@@ -350,7 +410,7 @@ public:
};
virtual void cursor_set_shape(CursorShape p_shape);
virtual CursorShape cursor_get_shape() const;
- virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
+ virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
virtual bool get_swap_cancel_ok();
@@ -409,5 +469,6 @@ VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
VARIANT_ENUM_CAST(DisplayServer::HandleType)
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
+VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent)
#endif // DISPLAY_SERVER_H
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index f74a8fad23..3853ff4fdc 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -33,7 +33,7 @@
#include "servers/display_server.h"
-#include "servers/rendering/rasterizer_dummy.h"
+#include "servers/rendering/dummy/rasterizer_dummy.h"
class DisplayServerHeadless : public DisplayServer {
private:
diff --git a/servers/extensions/SCsub b/servers/extensions/SCsub
new file mode 100644
index 0000000000..ba73353f2a
--- /dev/null
+++ b/servers/extensions/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env_object = env.Clone()
+
+env_object.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp
new file mode 100644
index 0000000000..3694dcdb9a
--- /dev/null
+++ b/servers/extensions/physics_server_3d_extension.cpp
@@ -0,0 +1,322 @@
+/*************************************************************************/
+/* physics_server_3d_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "physics_server_3d_extension.h"
+
+bool PhysicsDirectSpaceState3DExtension::is_body_excluded_from_query(const RID &p_body) const {
+ return exclude && exclude->has(p_body);
+}
+
+thread_local const HashSet<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr;
+
+void PhysicsDirectSpaceState3DExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "hit_back_faces", "result");
+ GDVIRTUAL_BIND(_intersect_point, "position", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results");
+ GDVIRTUAL_BIND(_intersect_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "result_count", "max_results");
+ GDVIRTUAL_BIND(_cast_motion, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "closest_safe", "closest_unsafe", "info");
+ GDVIRTUAL_BIND(_collide_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results", "result_count");
+ GDVIRTUAL_BIND(_rest_info, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "rest_info");
+ GDVIRTUAL_BIND(_get_closest_point_to_object_volume, "object", "point");
+}
+
+PhysicsDirectSpaceState3DExtension::PhysicsDirectSpaceState3DExtension() {
+}
+
+void PhysicsDirectBodyState3DExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_total_gravity);
+ GDVIRTUAL_BIND(_get_total_linear_damp);
+ GDVIRTUAL_BIND(_get_total_angular_damp);
+
+ GDVIRTUAL_BIND(_get_center_of_mass);
+ GDVIRTUAL_BIND(_get_center_of_mass_local);
+ GDVIRTUAL_BIND(_get_principal_inertia_axes);
+
+ GDVIRTUAL_BIND(_get_inverse_mass);
+ GDVIRTUAL_BIND(_get_inverse_inertia);
+
+ GDVIRTUAL_BIND(_set_linear_velocity, "velocity");
+ GDVIRTUAL_BIND(_get_linear_velocity);
+
+ GDVIRTUAL_BIND(_set_angular_velocity, "velocity");
+ GDVIRTUAL_BIND(_get_angular_velocity);
+
+ GDVIRTUAL_BIND(_set_transform, "transform");
+ GDVIRTUAL_BIND(_get_transform);
+
+ GDVIRTUAL_BIND(_get_velocity_at_local_position, "local_position");
+
+ GDVIRTUAL_BIND(_apply_central_impulse, "impulse");
+ GDVIRTUAL_BIND(_apply_impulse, "impulse", "position");
+ GDVIRTUAL_BIND(_apply_torque_impulse, "impulse");
+
+ GDVIRTUAL_BIND(_apply_central_force, "force");
+ GDVIRTUAL_BIND(_apply_force, "force", "position");
+ GDVIRTUAL_BIND(_apply_torque, "torque");
+
+ GDVIRTUAL_BIND(_add_constant_central_force, "force");
+ GDVIRTUAL_BIND(_add_constant_force, "force", "position");
+ GDVIRTUAL_BIND(_add_constant_torque, "torque");
+
+ GDVIRTUAL_BIND(_set_constant_force, "force");
+ GDVIRTUAL_BIND(_get_constant_force);
+
+ GDVIRTUAL_BIND(_set_constant_torque, "torque");
+ GDVIRTUAL_BIND(_get_constant_torque);
+
+ GDVIRTUAL_BIND(_set_sleep_state, "enabled");
+ GDVIRTUAL_BIND(_is_sleeping);
+
+ GDVIRTUAL_BIND(_get_contact_count);
+
+ GDVIRTUAL_BIND(_get_contact_local_position, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_local_normal, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_impulse, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_local_shape, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_position, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_id, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_object, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_shape, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_velocity_at_position, "contact_idx");
+ GDVIRTUAL_BIND(_get_step);
+ GDVIRTUAL_BIND(_integrate_forces);
+ GDVIRTUAL_BIND(_get_space_state);
+}
+
+PhysicsDirectBodyState3DExtension::PhysicsDirectBodyState3DExtension() {
+}
+
+thread_local const HashSet<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr;
+thread_local const HashSet<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr;
+
+bool PhysicsServer3DExtension::body_test_motion_is_excluding_body(RID p_body) const {
+ return exclude_bodies && exclude_bodies->has(p_body);
+}
+
+bool PhysicsServer3DExtension::body_test_motion_is_excluding_object(ObjectID p_object) const {
+ return exclude_objects && exclude_objects->has(p_object);
+}
+
+void PhysicsServer3DExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_world_boundary_shape_create);
+ GDVIRTUAL_BIND(_separation_ray_shape_create);
+ GDVIRTUAL_BIND(_sphere_shape_create);
+ GDVIRTUAL_BIND(_box_shape_create);
+ GDVIRTUAL_BIND(_capsule_shape_create);
+ GDVIRTUAL_BIND(_cylinder_shape_create);
+ GDVIRTUAL_BIND(_convex_polygon_shape_create);
+ GDVIRTUAL_BIND(_concave_polygon_shape_create);
+ GDVIRTUAL_BIND(_heightmap_shape_create);
+ GDVIRTUAL_BIND(_custom_shape_create);
+
+ GDVIRTUAL_BIND(_shape_set_data, "shape", "data");
+
+ GDVIRTUAL_BIND(_shape_get_type, "shape");
+ GDVIRTUAL_BIND(_shape_get_data, "shape");
+
+ GDVIRTUAL_BIND(_space_create);
+ GDVIRTUAL_BIND(_space_set_active, "space", "active");
+ GDVIRTUAL_BIND(_space_is_active, "space");
+ GDVIRTUAL_BIND(_space_set_param, "space", "param", "value");
+ GDVIRTUAL_BIND(_space_get_param, "space", "param");
+ GDVIRTUAL_BIND(_space_get_direct_state, "space");
+
+ GDVIRTUAL_BIND(_area_create);
+ GDVIRTUAL_BIND(_area_set_space, "area", "space");
+ GDVIRTUAL_BIND(_area_get_space, "area");
+
+ GDVIRTUAL_BIND(_area_add_shape, "area", "shape", "transform", "disabled");
+ GDVIRTUAL_BIND(_area_set_shape, "area", "shape_idx", "shape");
+ GDVIRTUAL_BIND(_area_set_shape_transform, "area", "shape_idx", "transform");
+ GDVIRTUAL_BIND(_area_set_shape_disabled, "area", "shape_idx", "disabled");
+
+ GDVIRTUAL_BIND(_area_get_shape_count, "area");
+ GDVIRTUAL_BIND(_area_get_shape, "area", "shape_idx");
+ GDVIRTUAL_BIND(_area_get_shape_transform, "area", "shape_idx");
+
+ GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx");
+ GDVIRTUAL_BIND(_area_clear_shapes, "area");
+
+ GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer");
+ GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask");
+
+ GDVIRTUAL_BIND(_area_set_param, "area", "param", "value");
+ GDVIRTUAL_BIND(_area_set_transform, "area", "transform");
+
+ GDVIRTUAL_BIND(_area_get_param, "area", "param");
+ GDVIRTUAL_BIND(_area_get_transform, "area");
+
+ GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id");
+ GDVIRTUAL_BIND(_area_get_object_instance_id, "area");
+
+ GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback");
+ GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback");
+ GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable");
+
+ GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable");
+
+ GDVIRTUAL_BIND(_body_create);
+
+ GDVIRTUAL_BIND(_body_set_space, "body", "space");
+ GDVIRTUAL_BIND(_body_get_space, "body");
+
+ GDVIRTUAL_BIND(_body_set_mode, "body", "mode");
+ GDVIRTUAL_BIND(_body_get_mode, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer");
+ GDVIRTUAL_BIND(_body_get_collision_layer, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask");
+ GDVIRTUAL_BIND(_body_get_collision_mask, "body");
+
+ GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled");
+ GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape");
+ GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform");
+ GDVIRTUAL_BIND(_body_set_shape_disabled, "body", "shape_idx", "disabled");
+
+ GDVIRTUAL_BIND(_body_get_shape_count, "body");
+ GDVIRTUAL_BIND(_body_get_shape, "body", "shape_idx");
+ GDVIRTUAL_BIND(_body_get_shape_transform, "body", "shape_idx");
+
+ GDVIRTUAL_BIND(_body_remove_shape, "body", "shape_idx");
+ GDVIRTUAL_BIND(_body_clear_shapes, "body");
+
+ GDVIRTUAL_BIND(_body_attach_object_instance_id, "body", "id");
+ GDVIRTUAL_BIND(_body_get_object_instance_id, "body");
+
+ GDVIRTUAL_BIND(_body_set_enable_continuous_collision_detection, "body", "enable");
+ GDVIRTUAL_BIND(_body_is_continuous_collision_detection_enabled, "body");
+
+ GDVIRTUAL_BIND(_body_set_param, "body", "param", "value");
+ GDVIRTUAL_BIND(_body_get_param, "body", "param");
+
+ GDVIRTUAL_BIND(_body_reset_mass_properties, "body");
+
+ GDVIRTUAL_BIND(_body_set_state, "body", "state", "value");
+ GDVIRTUAL_BIND(_body_get_state, "body", "state");
+
+ GDVIRTUAL_BIND(_body_apply_central_impulse, "body", "impulse");
+ GDVIRTUAL_BIND(_body_apply_impulse, "body", "impulse", "position");
+ GDVIRTUAL_BIND(_body_apply_torque_impulse, "body", "impulse");
+
+ GDVIRTUAL_BIND(_body_apply_central_force, "body", "force");
+ GDVIRTUAL_BIND(_body_apply_force, "body", "force", "position");
+ GDVIRTUAL_BIND(_body_apply_torque, "body", "torque");
+
+ GDVIRTUAL_BIND(_body_add_constant_central_force, "body", "force");
+ GDVIRTUAL_BIND(_body_add_constant_force, "body", "force", "position");
+ GDVIRTUAL_BIND(_body_add_constant_torque, "body", "torque");
+
+ GDVIRTUAL_BIND(_body_set_constant_force, "body", "force");
+ GDVIRTUAL_BIND(_body_get_constant_force, "body");
+
+ GDVIRTUAL_BIND(_body_set_constant_torque, "body", "torque");
+ GDVIRTUAL_BIND(_body_get_constant_torque, "body");
+
+ GDVIRTUAL_BIND(_body_set_axis_velocity, "body", "axis_velocity");
+
+ GDVIRTUAL_BIND(_body_set_axis_lock, "body", "axis", "lock");
+ GDVIRTUAL_BIND(_body_is_axis_locked, "body", "axis");
+
+ GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body");
+ GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body");
+
+ GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount");
+ GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body");
+
+ GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable");
+ GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body");
+
+ GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata");
+
+ GDVIRTUAL_BIND(_body_set_ray_pickable, "body", "enable");
+
+ GDVIRTUAL_BIND(_body_test_motion, "body", "from", "motion", "margin", "max_collisions", "collide_separation_ray", "result");
+
+ GDVIRTUAL_BIND(_body_get_direct_state, "body");
+
+ GDVIRTUAL_BIND(_soft_body_get_bounds, "body");
+
+ GDVIRTUAL_BIND(_joint_create);
+ GDVIRTUAL_BIND(_joint_clear, "joint");
+
+ GDVIRTUAL_BIND(_joint_make_pin, "joint", "body_A", "local_A", "body_B", "local_B");
+ GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_pin_joint_set_local_a, "joint", "local_A");
+ GDVIRTUAL_BIND(_pin_joint_get_local_a, "joint");
+
+ GDVIRTUAL_BIND(_pin_joint_set_local_b, "joint", "local_B");
+ GDVIRTUAL_BIND(_pin_joint_get_local_b, "joint");
+
+ GDVIRTUAL_BIND(_joint_make_hinge, "joint", "body_A", "hinge_A", "body_B", "hinge_B");
+
+ GDVIRTUAL_BIND(_hinge_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_hinge_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_hinge_joint_set_flag, "joint", "flag", "enabled");
+ GDVIRTUAL_BIND(_hinge_joint_get_flag, "joint", "flag");
+
+ GDVIRTUAL_BIND(_joint_make_slider, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B");
+
+ GDVIRTUAL_BIND(_slider_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_slider_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_joint_make_cone_twist, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B");
+
+ GDVIRTUAL_BIND(_cone_twist_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_cone_twist_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_joint_get_type, "joint");
+
+ GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority");
+ GDVIRTUAL_BIND(_joint_get_solver_priority, "joint");
+
+ GDVIRTUAL_BIND(_joint_make_generic_6dof, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B");
+
+ GDVIRTUAL_BIND(_generic_6dof_joint_set_param, "joint", "axis", "param", "value");
+ GDVIRTUAL_BIND(_generic_6dof_joint_get_param, "joint", "axis", "param");
+
+ GDVIRTUAL_BIND(_generic_6dof_joint_set_flag, "joint", "axis", "flag", "enable");
+ GDVIRTUAL_BIND(_generic_6dof_joint_get_flag, "joint", "axis", "flag");
+
+ GDVIRTUAL_BIND(_free_rid, "rid");
+
+ GDVIRTUAL_BIND(_set_active, "active");
+
+ GDVIRTUAL_BIND(_get_process_info, "process_info");
+}
+
+PhysicsServer3DExtension::PhysicsServer3DExtension() {
+}
+
+PhysicsServer3DExtension::~PhysicsServer3DExtension() {
+}
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
new file mode 100644
index 0000000000..663af1ae6c
--- /dev/null
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -0,0 +1,548 @@
+/*************************************************************************/
+/* physics_server_3d_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PHYSICS_SERVER_3D_EXTENSION_H
+#define PHYSICS_SERVER_3D_EXTENSION_H
+
+#include "core/extension/ext_wrappers.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+#include "core/variant/type_info.h"
+#include "core/variant/typed_array.h"
+#include "servers/physics_server_3d.h"
+
+class PhysicsDirectBodyState3DExtension : public PhysicsDirectBodyState3D {
+ GDCLASS(PhysicsDirectBodyState3DExtension, PhysicsDirectBodyState3D);
+
+protected:
+ static void _bind_methods();
+
+public:
+ // The warning is valid, but unavoidable. If the function is not overridden it will error anyway.
+
+ EXBIND0RC(Vector3, get_total_gravity)
+ EXBIND0RC(real_t, get_total_angular_damp)
+ EXBIND0RC(real_t, get_total_linear_damp)
+
+ EXBIND0RC(Vector3, get_center_of_mass)
+ EXBIND0RC(Vector3, get_center_of_mass_local)
+ EXBIND0RC(Basis, get_principal_inertia_axes)
+ EXBIND0RC(real_t, get_inverse_mass)
+ EXBIND0RC(Vector3, get_inverse_inertia)
+ EXBIND0RC(Basis, get_inverse_inertia_tensor)
+
+ EXBIND1(set_linear_velocity, const Vector3 &)
+ EXBIND0RC(Vector3, get_linear_velocity)
+
+ EXBIND1(set_angular_velocity, const Vector3 &)
+ EXBIND0RC(Vector3, get_angular_velocity)
+
+ EXBIND1(set_transform, const Transform3D &)
+ EXBIND0RC(Transform3D, get_transform)
+
+ EXBIND1RC(Vector3, get_velocity_at_local_position, const Vector3 &)
+
+ EXBIND1(apply_central_impulse, const Vector3 &)
+ EXBIND2(apply_impulse, const Vector3 &, const Vector3 &)
+ EXBIND1(apply_torque_impulse, const Vector3 &)
+
+ EXBIND1(apply_central_force, const Vector3 &)
+ EXBIND2(apply_force, const Vector3 &, const Vector3 &)
+ EXBIND1(apply_torque, const Vector3 &)
+
+ EXBIND1(add_constant_central_force, const Vector3 &)
+ EXBIND2(add_constant_force, const Vector3 &, const Vector3 &)
+ EXBIND1(add_constant_torque, const Vector3 &)
+
+ EXBIND1(set_constant_force, const Vector3 &)
+ EXBIND0RC(Vector3, get_constant_force)
+
+ EXBIND1(set_constant_torque, const Vector3 &)
+ EXBIND0RC(Vector3, get_constant_torque)
+
+ EXBIND1(set_sleep_state, bool)
+ EXBIND0RC(bool, is_sleeping)
+
+ EXBIND0RC(int, get_contact_count)
+
+ EXBIND1RC(Vector3, get_contact_local_position, int)
+ EXBIND1RC(Vector3, get_contact_local_normal, int)
+ EXBIND1RC(real_t, get_contact_impulse, int)
+ EXBIND1RC(int, get_contact_local_shape, int)
+ EXBIND1RC(RID, get_contact_collider, int)
+ EXBIND1RC(Vector3, get_contact_collider_position, int)
+ EXBIND1RC(ObjectID, get_contact_collider_id, int)
+ EXBIND1RC(Object *, get_contact_collider_object, int)
+ EXBIND1RC(int, get_contact_collider_shape, int)
+ EXBIND1RC(Vector3, get_contact_collider_velocity_at_position, int)
+
+ EXBIND0RC(real_t, get_step)
+
+ EXBIND0(integrate_forces)
+ EXBIND0R(PhysicsDirectSpaceState3D *, get_space_state)
+
+ PhysicsDirectBodyState3DExtension();
+};
+
+typedef PhysicsDirectSpaceState3D::RayResult PhysicsServer3DExtensionRayResult;
+typedef PhysicsDirectSpaceState3D::ShapeResult PhysicsServer3DExtensionShapeResult;
+typedef PhysicsDirectSpaceState3D::ShapeRestInfo PhysicsServer3DExtensionShapeRestInfo;
+
+GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionRayResult)
+GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeResult)
+GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeRestInfo)
+
+class PhysicsDirectSpaceState3DExtension : public PhysicsDirectSpaceState3D {
+ GDCLASS(PhysicsDirectSpaceState3DExtension, PhysicsDirectSpaceState3D);
+
+ thread_local static const HashSet<RID> *exclude;
+
+protected:
+ static void _bind_methods();
+ bool is_body_excluded_from_query(const RID &p_body) const;
+
+ GDVIRTUAL8R(bool, _intersect_ray, const Vector3 &, const Vector3 &, uint32_t, bool, bool, bool, bool, GDNativePtr<PhysicsServer3DExtensionRayResult>)
+ GDVIRTUAL6R(int, _intersect_point, const Vector3 &, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int)
+ GDVIRTUAL9R(int, _intersect_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int)
+ GDVIRTUAL10R(bool, _cast_motion, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>)
+ GDVIRTUAL10R(bool, _collide_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector3>, int, GDNativePtr<int>)
+ GDVIRTUAL8R(bool, _rest_info, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>)
+ GDVIRTUAL2RC(Vector3, _get_closest_point_to_object_volume, RID, const Vector3 &)
+
+public:
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_intersect_ray, p_parameters.from, p_parameters.to, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, p_parameters.hit_from_inside, p_parameters.hit_back_faces, &r_result, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override {
+ exclude = &p_parameters.exclude;
+ int ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_intersect_point, p_parameters.position, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override {
+ exclude = &p_parameters.exclude;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_intersect_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_cast_motion, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, &p_closest_safe, &p_closest_unsafe, r_info, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_collide_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, &r_result_count, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_rest_info, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_info, ret);
+ exclude = nullptr;
+ return ret;
+ }
+
+ virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override {
+ Vector3 ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_closest_point_to_object_volume, p_object, p_point, ret);
+ return ret;
+ }
+
+ PhysicsDirectSpaceState3DExtension();
+};
+
+typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision;
+typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult;
+
+struct PhysicsServer3DExtensionStateCallback {
+ void *instance = nullptr;
+ void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
+};
+
+GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionCollision)
+GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionResult)
+GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionStateCallback)
+
+class PhysicsServer3DExtension : public PhysicsServer3D {
+ GDCLASS(PhysicsServer3DExtension, PhysicsServer3D);
+
+protected:
+ static void _bind_methods();
+
+public:
+ // The warning is valid, but unavoidable. If the function is not overridden it will error anyway.
+
+ EXBIND0R(RID, world_boundary_shape_create)
+ EXBIND0R(RID, separation_ray_shape_create)
+ EXBIND0R(RID, sphere_shape_create)
+ EXBIND0R(RID, box_shape_create)
+ EXBIND0R(RID, capsule_shape_create)
+ EXBIND0R(RID, cylinder_shape_create)
+ EXBIND0R(RID, convex_polygon_shape_create)
+ EXBIND0R(RID, concave_polygon_shape_create)
+ EXBIND0R(RID, heightmap_shape_create)
+ EXBIND0R(RID, custom_shape_create)
+
+ EXBIND2(shape_set_data, RID, const Variant &)
+ EXBIND2(shape_set_custom_solver_bias, RID, real_t)
+
+ EXBIND2(shape_set_margin, RID, real_t)
+ EXBIND1RC(real_t, shape_get_margin, RID)
+
+ EXBIND1RC(ShapeType, shape_get_type, RID)
+ EXBIND1RC(Variant, shape_get_data, RID)
+ EXBIND1RC(real_t, shape_get_custom_solver_bias, RID)
+
+ /* SPACE API */
+
+ EXBIND0R(RID, space_create)
+ EXBIND2(space_set_active, RID, bool)
+ EXBIND1RC(bool, space_is_active, RID)
+
+ EXBIND3(space_set_param, RID, SpaceParameter, real_t)
+ EXBIND2RC(real_t, space_get_param, RID, SpaceParameter)
+
+ EXBIND1R(PhysicsDirectSpaceState3D *, space_get_direct_state, RID)
+
+ EXBIND2(space_set_debug_contacts, RID, int)
+ EXBIND1RC(Vector<Vector3>, space_get_contacts, RID)
+ EXBIND1RC(int, space_get_contact_count, RID)
+
+ /* AREA API */
+
+ //EXBIND0RID(area);
+ EXBIND0R(RID, area_create)
+
+ EXBIND2(area_set_space, RID, RID)
+ EXBIND1RC(RID, area_get_space, RID)
+
+ EXBIND4(area_add_shape, RID, RID, const Transform3D &, bool)
+ EXBIND3(area_set_shape, RID, int, RID)
+ EXBIND3(area_set_shape_transform, RID, int, const Transform3D &)
+ EXBIND3(area_set_shape_disabled, RID, int, bool)
+
+ EXBIND1RC(int, area_get_shape_count, RID)
+ EXBIND2RC(RID, area_get_shape, RID, int)
+ EXBIND2RC(Transform3D, area_get_shape_transform, RID, int)
+ EXBIND2(area_remove_shape, RID, int)
+ EXBIND1(area_clear_shapes, RID)
+
+ EXBIND2(area_attach_object_instance_id, RID, ObjectID)
+ EXBIND1RC(ObjectID, area_get_object_instance_id, RID)
+
+ EXBIND3(area_set_param, RID, AreaParameter, const Variant &)
+ EXBIND2(area_set_transform, RID, const Transform3D &)
+
+ EXBIND2RC(Variant, area_get_param, RID, AreaParameter)
+ EXBIND1RC(Transform3D, area_get_transform, RID)
+
+ EXBIND2(area_set_collision_mask, RID, uint32_t)
+ EXBIND2(area_set_collision_layer, RID, uint32_t)
+
+ EXBIND2(area_set_monitorable, RID, bool)
+ EXBIND2(area_set_ray_pickable, RID, bool)
+
+ EXBIND2(area_set_monitor_callback, RID, const Callable &)
+ EXBIND2(area_set_area_monitor_callback, RID, const Callable &)
+
+ /* BODY API */
+
+ //EXBIND2RID(body,BodyMode,bool);
+ EXBIND0R(RID, body_create)
+
+ EXBIND2(body_set_space, RID, RID)
+ EXBIND1RC(RID, body_get_space, RID)
+
+ EXBIND2(body_set_mode, RID, BodyMode)
+ EXBIND1RC(BodyMode, body_get_mode, RID)
+
+ EXBIND4(body_add_shape, RID, RID, const Transform3D &, bool)
+ EXBIND3(body_set_shape, RID, int, RID)
+ EXBIND3(body_set_shape_transform, RID, int, const Transform3D &)
+
+ EXBIND1RC(int, body_get_shape_count, RID)
+ EXBIND2RC(Transform3D, body_get_shape_transform, RID, int)
+ EXBIND2RC(RID, body_get_shape, RID, int)
+
+ EXBIND3(body_set_shape_disabled, RID, int, bool)
+
+ EXBIND2(body_remove_shape, RID, int)
+ EXBIND1(body_clear_shapes, RID)
+
+ EXBIND2(body_attach_object_instance_id, RID, ObjectID)
+ EXBIND1RC(ObjectID, body_get_object_instance_id, RID)
+
+ EXBIND2(body_set_enable_continuous_collision_detection, RID, bool)
+ EXBIND1RC(bool, body_is_continuous_collision_detection_enabled, RID)
+
+ EXBIND2(body_set_collision_layer, RID, uint32_t)
+ EXBIND1RC(uint32_t, body_get_collision_layer, RID)
+
+ EXBIND2(body_set_collision_mask, RID, uint32_t)
+ EXBIND1RC(uint32_t, body_get_collision_mask, RID)
+
+ EXBIND2(body_set_user_flags, RID, uint32_t)
+ EXBIND1RC(uint32_t, body_get_user_flags, RID)
+
+ EXBIND3(body_set_param, RID, BodyParameter, const Variant &)
+ EXBIND2RC(Variant, body_get_param, RID, BodyParameter)
+
+ EXBIND1(body_reset_mass_properties, RID)
+
+ EXBIND3(body_set_state, RID, BodyState, const Variant &)
+ EXBIND2RC(Variant, body_get_state, RID, BodyState)
+
+ EXBIND2(body_apply_torque_impulse, RID, const Vector3 &)
+ EXBIND2(body_apply_central_impulse, RID, const Vector3 &)
+ EXBIND3(body_apply_impulse, RID, const Vector3 &, const Vector3 &)
+
+ EXBIND2(body_apply_central_force, RID, const Vector3 &)
+ EXBIND3(body_apply_force, RID, const Vector3 &, const Vector3 &)
+ EXBIND2(body_apply_torque, RID, const Vector3 &)
+
+ EXBIND2(body_add_constant_central_force, RID, const Vector3 &)
+ EXBIND3(body_add_constant_force, RID, const Vector3 &, const Vector3 &)
+ EXBIND2(body_add_constant_torque, RID, const Vector3 &)
+
+ EXBIND2(body_set_constant_force, RID, const Vector3 &)
+ EXBIND1RC(Vector3, body_get_constant_force, RID)
+
+ EXBIND2(body_set_constant_torque, RID, const Vector3 &)
+ EXBIND1RC(Vector3, body_get_constant_torque, RID)
+
+ EXBIND2(body_set_axis_velocity, RID, const Vector3 &)
+
+ EXBIND3(body_set_axis_lock, RID, BodyAxis, bool)
+ EXBIND2RC(bool, body_is_axis_locked, RID, BodyAxis)
+
+ EXBIND2(body_add_collision_exception, RID, RID)
+ EXBIND2(body_remove_collision_exception, RID, RID)
+
+ GDVIRTUAL1RC(TypedArray<RID>, _body_get_collision_exceptions, RID)
+
+ void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override {
+ TypedArray<RID> ret;
+ GDVIRTUAL_REQUIRED_CALL(_body_get_collision_exceptions, p_body, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_exceptions->push_back(ret[i]);
+ }
+ }
+
+ EXBIND2(body_set_max_contacts_reported, RID, int)
+ EXBIND1RC(int, body_get_max_contacts_reported, RID)
+
+ EXBIND2(body_set_contacts_reported_depth_threshold, RID, real_t)
+ EXBIND1RC(real_t, body_get_contacts_reported_depth_threshold, RID)
+
+ EXBIND2(body_set_omit_force_integration, RID, bool)
+ EXBIND1RC(bool, body_is_omitting_force_integration, RID)
+
+ GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer3DExtensionStateCallback>)
+ void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override {
+ PhysicsServer3DExtensionStateCallback callback;
+ callback.callback = p_callback;
+ callback.instance = p_instance;
+ GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback);
+ }
+ EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &)
+
+ EXBIND2(body_set_ray_pickable, RID, bool)
+
+ GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDNativePtr<PhysicsServer3DExtensionMotionResult>)
+
+ thread_local static const HashSet<RID> *exclude_bodies;
+ thread_local static const HashSet<ObjectID> *exclude_objects;
+
+ bool body_test_motion_is_excluding_body(RID p_body) const;
+ bool body_test_motion_is_excluding_object(ObjectID p_object) const;
+
+ bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
+ bool ret = false;
+ exclude_bodies = &p_parameters.exclude_bodies;
+ exclude_objects = &p_parameters.exclude_objects;
+ GDVIRTUAL_REQUIRED_CALL(_body_test_motion, p_body, p_parameters.from, p_parameters.motion, p_parameters.margin, p_parameters.max_collisions, p_parameters.collide_separation_ray, r_result, ret);
+ exclude_bodies = nullptr;
+ exclude_objects = nullptr;
+ return ret;
+ }
+
+ EXBIND1R(PhysicsDirectBodyState3D *, body_get_direct_state, RID)
+
+ /* SOFT BODY API */
+
+ EXBIND0R(RID, soft_body_create)
+
+ EXBIND2(soft_body_update_rendering_server, RID, PhysicsServer3DRenderingServerHandler *)
+
+ EXBIND2(soft_body_set_space, RID, RID)
+ EXBIND1RC(RID, soft_body_get_space, RID)
+
+ EXBIND2(soft_body_set_ray_pickable, RID, bool)
+
+ EXBIND2(soft_body_set_collision_layer, RID, uint32_t)
+ EXBIND1RC(uint32_t, soft_body_get_collision_layer, RID)
+
+ EXBIND2(soft_body_set_collision_mask, RID, uint32_t)
+ EXBIND1RC(uint32_t, soft_body_get_collision_mask, RID)
+
+ EXBIND2(soft_body_add_collision_exception, RID, RID)
+ EXBIND2(soft_body_remove_collision_exception, RID, RID)
+
+ GDVIRTUAL1RC(TypedArray<RID>, _soft_body_get_collision_exceptions, RID)
+
+ void soft_body_get_collision_exceptions(RID p_soft_body, List<RID> *p_exceptions) override {
+ TypedArray<RID> ret;
+ GDVIRTUAL_REQUIRED_CALL(_soft_body_get_collision_exceptions, p_soft_body, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_exceptions->push_back(ret[i]);
+ }
+ }
+
+ EXBIND3(soft_body_set_state, RID, BodyState, const Variant &)
+ EXBIND2RC(Variant, soft_body_get_state, RID, BodyState)
+
+ EXBIND2(soft_body_set_transform, RID, const Transform3D &)
+
+ EXBIND2(soft_body_set_simulation_precision, RID, int)
+ EXBIND1RC(int, soft_body_get_simulation_precision, RID)
+
+ EXBIND2(soft_body_set_total_mass, RID, real_t)
+ EXBIND1RC(real_t, soft_body_get_total_mass, RID)
+
+ EXBIND2(soft_body_set_linear_stiffness, RID, real_t)
+ EXBIND1RC(real_t, soft_body_get_linear_stiffness, RID)
+
+ EXBIND2(soft_body_set_pressure_coefficient, RID, real_t)
+ EXBIND1RC(real_t, soft_body_get_pressure_coefficient, RID)
+
+ EXBIND2(soft_body_set_damping_coefficient, RID, real_t)
+ EXBIND1RC(real_t, soft_body_get_damping_coefficient, RID)
+
+ EXBIND2(soft_body_set_drag_coefficient, RID, real_t)
+ EXBIND1RC(real_t, soft_body_get_drag_coefficient, RID)
+
+ EXBIND2(soft_body_set_mesh, RID, RID)
+
+ EXBIND1RC(AABB, soft_body_get_bounds, RID)
+
+ EXBIND3(soft_body_move_point, RID, int, const Vector3 &)
+ EXBIND2RC(Vector3, soft_body_get_point_global_position, RID, int)
+
+ EXBIND1(soft_body_remove_all_pinned_points, RID)
+ EXBIND3(soft_body_pin_point, RID, int, bool)
+ EXBIND2RC(bool, soft_body_is_point_pinned, RID, int)
+
+ /* JOINT API */
+
+ EXBIND0R(RID, joint_create)
+
+ EXBIND1(joint_clear, RID)
+
+ EXBIND5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &)
+
+ EXBIND3(pin_joint_set_param, RID, PinJointParam, real_t)
+ EXBIND2RC(real_t, pin_joint_get_param, RID, PinJointParam)
+
+ EXBIND2(pin_joint_set_local_a, RID, const Vector3 &)
+ EXBIND1RC(Vector3, pin_joint_get_local_a, RID)
+
+ EXBIND2(pin_joint_set_local_b, RID, const Vector3 &)
+ EXBIND1RC(Vector3, pin_joint_get_local_b, RID)
+
+ EXBIND5(joint_make_hinge, RID, RID, const Transform3D &, RID, const Transform3D &)
+ EXBIND7(joint_make_hinge_simple, RID, RID, const Vector3 &, const Vector3 &, RID, const Vector3 &, const Vector3 &)
+
+ EXBIND3(hinge_joint_set_param, RID, HingeJointParam, real_t)
+ EXBIND2RC(real_t, hinge_joint_get_param, RID, HingeJointParam)
+
+ EXBIND3(hinge_joint_set_flag, RID, HingeJointFlag, bool)
+ EXBIND2RC(bool, hinge_joint_get_flag, RID, HingeJointFlag)
+
+ EXBIND5(joint_make_slider, RID, RID, const Transform3D &, RID, const Transform3D &)
+
+ EXBIND3(slider_joint_set_param, RID, SliderJointParam, real_t)
+ EXBIND2RC(real_t, slider_joint_get_param, RID, SliderJointParam)
+
+ EXBIND5(joint_make_cone_twist, RID, RID, const Transform3D &, RID, const Transform3D &)
+
+ EXBIND3(cone_twist_joint_set_param, RID, ConeTwistJointParam, real_t)
+ EXBIND2RC(real_t, cone_twist_joint_get_param, RID, ConeTwistJointParam)
+
+ EXBIND5(joint_make_generic_6dof, RID, RID, const Transform3D &, RID, const Transform3D &)
+
+ EXBIND4(generic_6dof_joint_set_param, RID, Vector3::Axis, G6DOFJointAxisParam, real_t)
+ EXBIND3RC(real_t, generic_6dof_joint_get_param, RID, Vector3::Axis, G6DOFJointAxisParam)
+
+ EXBIND4(generic_6dof_joint_set_flag, RID, Vector3::Axis, G6DOFJointAxisFlag, bool)
+ EXBIND3RC(bool, generic_6dof_joint_get_flag, RID, Vector3::Axis, G6DOFJointAxisFlag)
+
+ EXBIND1RC(JointType, joint_get_type, RID)
+
+ EXBIND2(joint_set_solver_priority, RID, int)
+ EXBIND1RC(int, joint_get_solver_priority, RID)
+
+ EXBIND2(joint_disable_collisions_between_bodies, RID, bool)
+ EXBIND1RC(bool, joint_is_disabled_collisions_between_bodies, RID)
+
+ /* MISC */
+
+ GDVIRTUAL1(_free_rid, RID)
+ virtual void free(RID p_rid) override {
+ GDVIRTUAL_REQUIRED_CALL(_free_rid, p_rid);
+ }
+
+ EXBIND1(set_active, bool)
+
+ EXBIND0(init)
+ EXBIND1(step, real_t)
+ EXBIND0(sync)
+ EXBIND0(end_sync)
+ EXBIND0(flush_queries)
+ EXBIND0(finish)
+
+ EXBIND0RC(bool, is_flushing_queries)
+ EXBIND1R(int, get_process_info, ProcessInfo)
+
+ PhysicsServer3DExtension();
+ ~PhysicsServer3DExtension();
+};
+
+#endif // PHYSICSSERVER3DEXTENSION_H
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index ee196673a3..0442089503 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -138,11 +138,11 @@ static Object *obj_to_obj(Object *d) {
return d;
}
-static StringName sn_to_sn(StringName &d) {
+static StringName sn_to_sn(const StringName &d) {
return d;
}
-static Variant var_to_var(Variant &d) {
+static Variant var_to_var(const Variant &d) {
return d;
}
@@ -166,14 +166,22 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner);
+ ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions);
+ ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents);
+
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create);
+ ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer2D::region_set_enter_cost);
+ ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer2D::region_get_enter_cost);
+ ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer2D::region_set_travel_cost);
+ ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer2D::region_get_travel_cost);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer2D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer2D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
@@ -182,6 +190,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
+ ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map);
ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist);
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors);
ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon);
@@ -193,7 +202,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed);
ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer2D::free);
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
@@ -208,6 +217,14 @@ NavigationServer2D::~NavigationServer2D() {
singleton = nullptr;
}
+Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid);
+
+Array FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid);
+
+RID FORWARD_1_C(region_get_map, RID, p_region, rid_to_rid);
+
+RID FORWARD_1_C(agent_get_map, RID, p_agent, rid_to_rid);
+
RID FORWARD_0_C(map_create);
void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to_bool);
@@ -226,9 +243,15 @@ Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2
RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3);
RID FORWARD_0_C(region_create);
+
+void FORWARD_2_C(region_set_enter_cost, RID, p_region, real_t, p_enter_cost, rid_to_rid, real_to_real);
+real_t FORWARD_1_C(region_get_enter_cost, RID, p_region, rid_to_rid);
+void FORWARD_2_C(region_set_travel_cost, RID, p_region, real_t, p_travel_cost, rid_to_rid, real_to_real);
+real_t FORWARD_1_C(region_get_travel_cost, RID, p_region, rid_to_rid);
+
void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid);
-void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32);
-uint32_t FORWARD_1_C(region_get_layers, RID, p_region, rid_to_rid);
+void FORWARD_2_C(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
+uint32_t FORWARD_1_C(region_get_navigation_layers, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3);
void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const {
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 7350eeb5b1..30f553d10b 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -75,20 +75,32 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
+ virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const;
virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
+ virtual Array map_get_regions(RID p_map) const;
+ virtual Array map_get_agents(RID p_map) const;
+
/// Creates a new region.
virtual RID region_create() const;
+ /// Set the enter_cost of a region
+ virtual void region_set_enter_cost(RID p_region, real_t p_enter_cost) const;
+ virtual real_t region_get_enter_cost(RID p_region) const;
+
+ /// Set the travel_cost of a region
+ virtual void region_set_travel_cost(RID p_region, real_t p_travel_cost) const;
+ virtual real_t region_get_travel_cost(RID p_region) const;
+
/// Set the map of this region.
virtual void region_set_map(RID p_region, RID p_map) const;
+ virtual RID region_get_map(RID p_region) const;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const;
- virtual uint32_t region_get_layers(RID p_region) const;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
@@ -106,6 +118,7 @@ public:
/// Put the agent in the map.
virtual void agent_set_map(RID p_agent, RID p_map) const;
+ virtual RID agent_get_map(RID p_agent) const;
/// The maximum distance (center point to
/// center point) to other agents this agent
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index d18777869a..60bbcec8d4 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -42,16 +42,24 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner);
+ ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions);
+ ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents);
+
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create);
+ ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer3D::region_set_enter_cost);
+ ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer3D::region_get_enter_cost);
+ ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer3D::region_set_travel_cost);
+ ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer3D::region_get_travel_cost);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer3D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer3D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
@@ -61,6 +69,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
+ ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map);
ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist);
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors);
ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon);
@@ -72,7 +81,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed);
ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer3D::free);
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active);
ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 0a75b07931..9c04d68622 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -84,22 +84,34 @@ public:
virtual real_t map_get_edge_connection_margin(RID p_map) const = 0;
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0;
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0;
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0;
+ virtual Array map_get_regions(RID p_map) const = 0;
+ virtual Array map_get_agents(RID p_map) const = 0;
+
/// Creates a new region.
virtual RID region_create() const = 0;
+ /// Set the enter_cost of a region
+ virtual void region_set_enter_cost(RID p_region, real_t p_enter_cost) const = 0;
+ virtual real_t region_get_enter_cost(RID p_region) const = 0;
+
+ /// Set the travel_cost of a region
+ virtual void region_set_travel_cost(RID p_region, real_t p_travel_cost) const = 0;
+ virtual real_t region_get_travel_cost(RID p_region) const = 0;
+
/// Set the map of this region.
virtual void region_set_map(RID p_region, RID p_map) const = 0;
+ virtual RID region_get_map(RID p_region) const = 0;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0;
- virtual uint32_t region_get_layers(RID p_region) const = 0;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const = 0;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const = 0;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;
@@ -120,6 +132,7 @@ public:
/// Put the agent in the map.
virtual void agent_set_map(RID p_agent, RID p_map) const = 0;
+ virtual RID agent_get_map(RID p_agent) const = 0;
/// The maximum distance (center point to
/// center point) to other agents this agent
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp
index 9937178550..11208f2d5b 100644
--- a/servers/physics_2d/godot_area_2d.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -225,22 +225,24 @@ void GodotArea2D::call_queries() {
resptr[i] = &res[i];
}
- for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_bodies.erase(E);
+ for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_bodies.begin(); E;) {
+ if (E->value.state == 0) { // Nothing happened
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_bodies.remove(E);
E = next;
continue;
}
- res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
+ res[0] = E->value.state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
+ res[1] = E->key.rid;
+ res[2] = E->key.instance_id;
+ res[3] = E->key.body_shape;
+ res[4] = E->key.area_shape;
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_bodies.erase(E);
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_bodies.remove(E);
E = next;
Callable::CallError ce;
@@ -261,22 +263,24 @@ void GodotArea2D::call_queries() {
resptr[i] = &res[i];
}
- for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_areas.erase(E);
+ for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_areas.begin(); E;) {
+ if (E->value.state == 0) { // Nothing happened
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_areas.remove(E);
E = next;
continue;
}
- res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
+ res[0] = E->value.state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
+ res[1] = E->key.rid;
+ res[2] = E->key.instance_id;
+ res[3] = E->key.body_shape;
+ res[4] = E->key.area_shape;
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_areas.erase(E);
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_areas.remove(E);
E = next;
Callable::CallError ce;
diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h
index 6e8078909b..35dad9d2c3 100644
--- a/servers/physics_2d/godot_area_2d.h
+++ b/servers/physics_2d/godot_area_2d.h
@@ -68,16 +68,15 @@ class GodotArea2D : public GodotCollisionObject2D {
uint32_t body_shape = 0;
uint32_t area_shape = 0;
- _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const {
- if (rid == p_key.rid) {
- if (body_shape == p_key.body_shape) {
- return area_shape < p_key.area_shape;
- } else {
- return body_shape < p_key.body_shape;
- }
- } else {
- return rid < p_key.rid;
- }
+ static uint32_t hash(const BodyKey &p_key) {
+ uint32_t h = hash_one_uint64(p_key.rid.get_id());
+ h = hash_djb2_one_64(p_key.instance_id, h);
+ h = hash_djb2_one_32(p_key.area_shape, h);
+ return hash_djb2_one_32(p_key.body_shape, h);
+ }
+
+ _FORCE_INLINE_ bool operator==(const BodyKey &p_key) const {
+ return rid == p_key.rid && instance_id == p_key.instance_id && body_shape == p_key.body_shape && area_shape == p_key.area_shape;
}
_FORCE_INLINE_ BodyKey() {}
@@ -91,12 +90,12 @@ class GodotArea2D : public GodotCollisionObject2D {
_FORCE_INLINE_ void dec() { state--; }
};
- Map<BodyKey, BodyState> monitored_bodies;
- Map<BodyKey, BodyState> monitored_areas;
+ HashMap<BodyKey, BodyState, BodyKey> monitored_bodies;
+ HashMap<BodyKey, BodyState, BodyKey> monitored_areas;
- Set<GodotConstraint2D *> constraints;
+ HashSet<GodotConstraint2D *> constraints;
- virtual void _shapes_changed();
+ virtual void _shapes_changed() override;
void _queue_monitor_update();
void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode);
@@ -143,7 +142,7 @@ public:
_FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint) { constraints.insert(p_constraint); }
_FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint) { constraints.erase(p_constraint); }
- _FORCE_INLINE_ const Set<GodotConstraint2D *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ const HashSet<GodotConstraint2D *> &get_constraints() const { return constraints; }
_FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
void set_monitorable(bool p_monitorable);
@@ -151,7 +150,7 @@ public:
void set_transform(const Transform2D &p_transform);
- void set_space(GodotSpace2D *p_space);
+ void set_space(GodotSpace2D *p_space) override;
void call_queries();
diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h
index 1335a19126..4b87a69d5c 100644
--- a/servers/physics_2d/godot_body_2d.h
+++ b/servers/physics_2d/godot_body_2d.h
@@ -103,7 +103,7 @@ class GodotBody2D : public GodotCollisionObject2D {
bool can_sleep = true;
bool first_time_kinematic = false;
void _mass_properties_changed();
- virtual void _shapes_changed();
+ virtual void _shapes_changed() override;
Transform2D new_transform;
List<Pair<GodotConstraint2D *, int>> constraint_list;
@@ -302,7 +302,7 @@ public:
_FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; }
_FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; }
- void set_space(GodotSpace2D *p_space);
+ void set_space(GodotSpace2D *p_space) override;
void update_mass_properties();
void reset_mass_properties();
diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp
index 2bf1e5a1d4..2f2af15da7 100644
--- a/servers/physics_2d/godot_body_pair_2d.cpp
+++ b/servers/physics_2d/godot_body_pair_2d.cpp
@@ -39,7 +39,7 @@
#define MAX_BIAS_ROTATION (Math_PI / 8)
void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) {
- GodotBodyPair2D *self = (GodotBodyPair2D *)p_self;
+ GodotBodyPair2D *self = static_cast<GodotBodyPair2D *>(p_self);
self->_contact_added_callback(p_point_A, p_point_B);
}
@@ -203,7 +203,7 @@ bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A,
// Check one-way collision based on motion direction.
if (p_A->get_shape(p_shape_A)->allows_one_way_collision() && p_B->is_shape_set_as_one_way_collision(p_shape_B)) {
- Vector2 direction = p_xform_B.get_axis(1).normalized();
+ Vector2 direction = p_xform_B.columns[1].normalized();
if (direction.dot(mnormal) < CMP_EPSILON) {
collided = false;
oneway_disabled = true;
@@ -260,7 +260,7 @@ bool GodotBodyPair2D::setup(real_t p_step) {
Transform2D xform_A = xform_Au * A->get_shape_transform(shape_A);
Transform2D xform_Bu = B->get_transform();
- xform_Bu.elements[2] -= offset_A;
+ xform_Bu.columns[2] -= offset_A;
Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B);
GodotShape2D *shape_A_ptr = A->get_shape(shape_A);
@@ -300,7 +300,7 @@ bool GodotBodyPair2D::setup(real_t p_step) {
if (!prev_collided) {
if (shape_B_ptr->allows_one_way_collision() && A->is_shape_set_as_one_way_collision(shape_A)) {
- Vector2 direction = xform_A.get_axis(1).normalized();
+ Vector2 direction = xform_A.columns[1].normalized();
bool valid = false;
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
@@ -318,7 +318,7 @@ bool GodotBodyPair2D::setup(real_t p_step) {
}
if (shape_A_ptr->allows_one_way_collision() && B->is_shape_set_as_one_way_collision(shape_B)) {
- Vector2 direction = xform_B.get_axis(1).normalized();
+ Vector2 direction = xform_B.columns[1].normalized();
bool valid = false;
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
@@ -351,7 +351,7 @@ bool GodotBodyPair2D::pre_solve(real_t p_step) {
Transform2D xform_A = xform_Au * A->get_shape_transform(shape_A);
Transform2D xform_Bu = B->get_transform();
- xform_Bu.elements[2] -= offset_A;
+ xform_Bu.columns[2] -= offset_A;
Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B);
if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_A) {
diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp
index 5a96dae8ca..c545fec113 100644
--- a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp
+++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp
@@ -32,47 +32,57 @@
#include "godot_collision_object_2d.h"
GodotBroadPhase2D::ID GodotBroadPhase2DBVH::create(GodotCollisionObject2D *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) {
- ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care?
+ uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC;
+ uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC);
+ ID oid = bvh.create(p_object, true, tree_id, tree_collision_mask, p_aabb, p_subindex); // Pair everything, don't care?
return oid + 1;
}
void GodotBroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) {
+ ERR_FAIL_COND(!p_id);
bvh.move(p_id - 1, p_aabb);
}
void GodotBroadPhase2DBVH::set_static(ID p_id, bool p_static) {
- GodotCollisionObject2D *it = bvh.get(p_id - 1);
- bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care?
+ ERR_FAIL_COND(!p_id);
+ uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC;
+ uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC);
+ bvh.set_tree(p_id - 1, tree_id, tree_collision_mask, false);
}
void GodotBroadPhase2DBVH::remove(ID p_id) {
+ ERR_FAIL_COND(!p_id);
bvh.erase(p_id - 1);
}
GodotCollisionObject2D *GodotBroadPhase2DBVH::get_object(ID p_id) const {
+ ERR_FAIL_COND_V(!p_id, nullptr);
GodotCollisionObject2D *it = bvh.get(p_id - 1);
ERR_FAIL_COND_V(!it, nullptr);
return it;
}
bool GodotBroadPhase2DBVH::is_static(ID p_id) const {
- return !bvh.is_pairable(p_id - 1);
+ ERR_FAIL_COND_V(!p_id, false);
+ uint32_t tree_id = bvh.get_tree_id(p_id - 1);
+ return tree_id == 0;
}
int GodotBroadPhase2DBVH::get_subindex(ID p_id) const {
+ ERR_FAIL_COND_V(!p_id, 0);
return bvh.get_subindex(p_id - 1);
}
int GodotBroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) {
- return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices);
+ return bvh.cull_segment(p_from, p_to, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices);
}
int GodotBroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) {
- return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices);
+ return bvh.cull_aabb(p_aabb, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices);
}
void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B) {
- GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self);
+ GodotBroadPhase2DBVH *bpo = static_cast<GodotBroadPhase2DBVH *>(self);
if (!bpo->pair_callback) {
return nullptr;
}
@@ -81,7 +91,7 @@ void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollis
}
void GodotBroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B, void *pairdata) {
- GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self);
+ GodotBroadPhase2DBVH *bpo = static_cast<GodotBroadPhase2DBVH *>(self);
if (!bpo->unpair_callback) {
return;
}
diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h
index d77e0574eb..512111f948 100644
--- a/servers/physics_2d/godot_broad_phase_2d_bvh.h
+++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h
@@ -38,7 +38,34 @@
#include "core/math/vector2.h"
class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
- BVH_Manager<GodotCollisionObject2D, true, 128, Rect2, Vector2> bvh;
+ template <class T>
+ class UserPairTestFunction {
+ public:
+ static bool user_pair_check(const T *p_a, const T *p_b) {
+ // return false if no collision, decided by masks etc
+ return p_a->interacts_with(p_b);
+ }
+ };
+
+ template <class T>
+ class UserCullTestFunction {
+ public:
+ static bool user_cull_check(const T *p_a, const T *p_b) {
+ return true;
+ }
+ };
+
+ enum Tree {
+ TREE_STATIC = 0,
+ TREE_DYNAMIC = 1,
+ };
+
+ enum TreeFlag {
+ TREE_FLAG_STATIC = 1 << TREE_STATIC,
+ TREE_FLAG_DYNAMIC = 1 << TREE_DYNAMIC,
+ };
+
+ BVH_Manager<GodotCollisionObject2D, 2, true, 128, UserPairTestFunction<GodotCollisionObject2D>, UserCullTestFunction<GodotCollisionObject2D>, Rect2, Vector2> bvh;
static void *_pair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int);
static void _unpair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int, void *);
@@ -50,22 +77,22 @@ class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
public:
// 0 is an invalid ID
- virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false);
- virtual void move(ID p_id, const Rect2 &p_aabb);
- virtual void set_static(ID p_id, bool p_static);
- virtual void remove(ID p_id);
+ virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) override;
+ virtual void move(ID p_id, const Rect2 &p_aabb) override;
+ virtual void set_static(ID p_id, bool p_static) override;
+ virtual void remove(ID p_id) override;
- virtual GodotCollisionObject2D *get_object(ID p_id) const;
- virtual bool is_static(ID p_id) const;
- virtual int get_subindex(ID p_id) const;
+ virtual GodotCollisionObject2D *get_object(ID p_id) const override;
+ virtual bool is_static(ID p_id) const override;
+ virtual int get_subindex(ID p_id) const override;
- virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr);
- virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) override;
+ virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) override;
- virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
- virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
+ virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) override;
+ virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) override;
- virtual void update();
+ virtual void update() override;
static GodotBroadPhase2D *_create();
GodotBroadPhase2DBVH();
diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h
index 1e9baad8d9..1a683a7b0f 100644
--- a/servers/physics_2d/godot_collision_object_2d.h
+++ b/servers/physics_2d/godot_collision_object_2d.h
@@ -104,7 +104,7 @@ public:
_FORCE_INLINE_ void set_canvas_instance_id(const ObjectID &p_canvas_instance_id) { canvas_instance_id = p_canvas_instance_id; }
_FORCE_INLINE_ ObjectID get_canvas_instance_id() const { return canvas_instance_id; }
- void _shape_changed();
+ void _shape_changed() override;
_FORCE_INLINE_ Type get_type() const { return type; }
void add_shape(GodotShape2D *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
@@ -166,7 +166,7 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; }
- void remove_shape(GodotShape2D *p_shape);
+ void remove_shape(GodotShape2D *p_shape) override;
void remove_shape(int p_index);
virtual void set_space(GodotSpace2D *p_space) = 0;
@@ -180,7 +180,7 @@ public:
return p_other->collision_layer & collision_mask;
}
- _FORCE_INLINE_ bool interacts_with(GodotCollisionObject2D *p_other) const {
+ _FORCE_INLINE_ bool interacts_with(const GodotCollisionObject2D *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}
diff --git a/servers/physics_2d/godot_collision_solver_2d.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp
index 263d6d939f..0d7b42b80d 100644
--- a/servers/physics_2d/godot_collision_solver_2d.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d.cpp
@@ -140,7 +140,7 @@ struct _ConcaveCollisionInfo2D {
Vector2 motion_B;
real_t margin_A = 0.0;
real_t margin_B = 0.0;
- GodotCollisionSolver2D::CallbackResult result_callback;
+ GodotCollisionSolver2D::CallbackResult result_callback = nullptr;
void *userdata = nullptr;
bool swap_result = false;
bool collided = false;
@@ -150,7 +150,7 @@ struct _ConcaveCollisionInfo2D {
};
bool GodotCollisionSolver2D::concave_callback(void *p_userdata, GodotShape2D *p_convex) {
- _ConcaveCollisionInfo2D &cinfo = *(_ConcaveCollisionInfo2D *)(p_userdata);
+ _ConcaveCollisionInfo2D &cinfo = *(static_cast<_ConcaveCollisionInfo2D *>(p_userdata));
cinfo.aabb_tests++;
bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, cinfo.motion_A, p_convex, *cinfo.transform_B, cinfo.motion_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, cinfo.sep_axis, cinfo.margin_A, cinfo.margin_B);
@@ -185,13 +185,13 @@ bool GodotCollisionSolver2D::solve_concave(const GodotShape2D *p_shape_A, const
cinfo.aabb_tests = 0;
Transform2D rel_transform = p_transform_A;
- rel_transform.elements[2] -= p_transform_B.get_origin();
+ rel_transform.columns[2] -= p_transform_B.get_origin();
//quickly compute a local Rect2
Rect2 local_aabb;
for (int i = 0; i < 2; i++) {
- Vector2 axis(p_transform_B.elements[i]);
+ Vector2 axis(p_transform_B.columns[i]);
real_t axis_scale = 1.0 / axis.length();
axis *= axis_scale;
diff --git a/servers/physics_2d/godot_collision_solver_2d_sat.cpp b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
index ded3ff356b..77186d3810 100644
--- a/servers/physics_2d/godot_collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
@@ -33,7 +33,7 @@
#include "core/math/geometry_2d.h"
struct _CollectorCallback2D {
- GodotCollisionSolver2D::CallbackResult callback;
+ GodotCollisionSolver2D::CallbackResult callback = nullptr;
void *userdata = nullptr;
bool swap = false;
bool collided = false;
@@ -477,11 +477,11 @@ static void _collision_segment_rectangle(const GodotShape2D *p_a, const Transfor
return;
}
- if (!separator.test_axis(p_transform_b.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[0].normalized())) {
return;
}
- if (!separator.test_axis(p_transform_b.elements[1].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[1].normalized())) {
return;
}
@@ -548,22 +548,22 @@ static void _collision_segment_capsule(const GodotShape2D *p_a, const Transform2
return;
}
- if (!separator.test_axis(p_transform_b.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[0].normalized())) {
return;
}
real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
- if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() - p_transform_b.columns[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() - p_transform_b.columns[1] * capsule_dir))) {
return;
}
@@ -646,8 +646,8 @@ static void _collision_circle_rectangle(const GodotShape2D *p_a, const Transform
return;
}
- const Vector2 &sphere = p_transform_a.elements[2];
- const Vector2 *axis = &p_transform_b.elements[0];
+ const Vector2 &sphere = p_transform_a.columns[2];
+ const Vector2 *axis = &p_transform_b.columns[0];
//const Vector2& half_extents = rectangle_B->get_half_extents();
if (!separator.test_axis(axis[0].normalized())) {
@@ -705,17 +705,17 @@ static void _collision_circle_capsule(const GodotShape2D *p_a, const Transform2D
}
//capsule axis
- if (!separator.test_axis(p_transform_b.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[0].normalized())) {
return;
}
real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
//capsule endpoints
- if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
+ if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
+ if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() - p_transform_b.columns[1] * capsule_dir))) {
return;
}
@@ -769,20 +769,20 @@ static void _collision_rectangle_rectangle(const GodotShape2D *p_a, const Transf
}
//box faces A
- if (!separator.test_axis(p_transform_a.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[0].normalized())) {
return;
}
- if (!separator.test_axis(p_transform_a.elements[1].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[1].normalized())) {
return;
}
//box faces B
- if (!separator.test_axis(p_transform_b.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[0].normalized())) {
return;
}
- if (!separator.test_axis(p_transform_b.elements[1].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[1].normalized())) {
return;
}
@@ -796,10 +796,10 @@ static void _collision_rectangle_rectangle(const GodotShape2D *p_a, const Transf
if (castA || castB) {
Transform2D aofs = p_transform_a;
- aofs.elements[2] += p_motion_a;
+ aofs.columns[2] += p_motion_a;
Transform2D bofs = p_transform_b;
- bofs.elements[2] += p_motion_b;
+ bofs.columns[2] += p_motion_b;
Transform2D aofsinv = aofs.affine_inverse();
Transform2D bofsinv = bofs.affine_inverse();
@@ -843,16 +843,16 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
//box faces
- if (!separator.test_axis(p_transform_a.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[0].normalized())) {
return;
}
- if (!separator.test_axis(p_transform_a.elements[1].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[1].normalized())) {
return;
}
//capsule axis
- if (!separator.test_axis(p_transform_b.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[0].normalized())) {
return;
}
@@ -864,7 +864,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
for (int i = 0; i < 2; i++) {
{
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
return;
@@ -872,7 +872,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
if (castA) {
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
capsule_endpoint -= p_motion_a;
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
@@ -881,7 +881,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
if (castB) {
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
capsule_endpoint += p_motion_b;
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
@@ -890,7 +890,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
if (castA && castB) {
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
capsule_endpoint -= p_motion_a;
capsule_endpoint += p_motion_b;
@@ -921,11 +921,11 @@ static void _collision_rectangle_convex_polygon(const GodotShape2D *p_a, const T
}
//box faces
- if (!separator.test_axis(p_transform_a.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[0].normalized())) {
return;
}
- if (!separator.test_axis(p_transform_a.elements[1].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[1].normalized())) {
return;
}
@@ -984,11 +984,11 @@ static void _collision_capsule_capsule(const GodotShape2D *p_a, const Transform2
//capsule axis
- if (!separator.test_axis(p_transform_b.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_b.columns[0].normalized())) {
return;
}
- if (!separator.test_axis(p_transform_a.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[0].normalized())) {
return;
}
@@ -996,11 +996,11 @@ static void _collision_capsule_capsule(const GodotShape2D *p_a, const Transform2
real_t capsule_dir_A = capsule_A->get_height() * 0.5 - capsule_A->get_radius();
for (int i = 0; i < 2; i++) {
- Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_dir_A;
+ Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.columns[1] * capsule_dir_A;
real_t capsule_dir_B = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
for (int j = 0; j < 2; j++) {
- Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir_B;
+ Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir_B;
if (TEST_POINT(capsule_endpoint_A, capsule_endpoint_B)) {
return;
@@ -1032,7 +1032,7 @@ static void _collision_capsule_convex_polygon(const GodotShape2D *p_a, const Tra
//capsule axis
- if (!separator.test_axis(p_transform_a.elements[0].normalized())) {
+ if (!separator.test_axis(p_transform_a.columns[0].normalized())) {
return;
}
@@ -1042,7 +1042,7 @@ static void _collision_capsule_convex_polygon(const GodotShape2D *p_a, const Tra
real_t capsule_dir = capsule_A->get_height() * 0.5 - capsule_A->get_radius();
for (int j = 0; j < 2; j++) {
- Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_dir;
+ Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.columns[1] * capsule_dir;
if (TEST_POINT(capsule_endpoint_A, cpoint)) {
return;
diff --git a/servers/physics_2d/godot_joints_2d.cpp b/servers/physics_2d/godot_joints_2d.cpp
index 0876184d8c..0c21b08ea9 100644
--- a/servers/physics_2d/godot_joints_2d.cpp
+++ b/servers/physics_2d/godot_joints_2d.cpp
@@ -118,22 +118,26 @@ bool GodotPinJoint2D::setup(real_t p_step) {
K1[0].y = 0.0f;
K1[1].y = A->get_inv_mass() + B_inv_mass;
+ Vector2 r1 = rA - A->get_center_of_mass();
+
Transform2D K2;
- K2[0].x = A->get_inv_inertia() * rA.y * rA.y;
- K2[1].x = -A->get_inv_inertia() * rA.x * rA.y;
- K2[0].y = -A->get_inv_inertia() * rA.x * rA.y;
- K2[1].y = A->get_inv_inertia() * rA.x * rA.x;
+ K2[0].x = A->get_inv_inertia() * r1.y * r1.y;
+ K2[1].x = -A->get_inv_inertia() * r1.x * r1.y;
+ K2[0].y = -A->get_inv_inertia() * r1.x * r1.y;
+ K2[1].y = A->get_inv_inertia() * r1.x * r1.x;
Transform2D K;
K[0] = K1[0] + K2[0];
K[1] = K1[1] + K2[1];
if (B) {
+ Vector2 r2 = rB - B->get_center_of_mass();
+
Transform2D K3;
- K3[0].x = B->get_inv_inertia() * rB.y * rB.y;
- K3[1].x = -B->get_inv_inertia() * rB.x * rB.y;
- K3[0].y = -B->get_inv_inertia() * rB.x * rB.y;
- K3[1].y = B->get_inv_inertia() * rB.x * rB.x;
+ K3[0].x = B->get_inv_inertia() * r2.y * r2.y;
+ K3[1].x = -B->get_inv_inertia() * r2.x * r2.y;
+ K3[0].y = -B->get_inv_inertia() * r2.x * r2.y;
+ K3[1].y = B->get_inv_inertia() * r2.x * r2.x;
K[0] += K3[0];
K[1] += K3[1];
diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp
index a9b499c6b5..99e68de07c 100644
--- a/servers/physics_2d/godot_physics_server_2d.cpp
+++ b/servers/physics_2d/godot_physics_server_2d.cpp
@@ -144,7 +144,7 @@ real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const {
}
void GodotPhysicsServer2D::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
- CollCbkData *cbk = (CollCbkData *)p_userdata;
+ CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata);
if (cbk->max == 0) {
return;
@@ -1179,7 +1179,7 @@ void GodotPhysicsServer2D::free(RID p_rid) {
GodotShape2D *shape = shape_owner.get_or_null(p_rid);
while (shape->get_owners().size()) {
- GodotShapeOwner2D *so = shape->get_owners().front()->key();
+ GodotShapeOwner2D *so = shape->get_owners().begin()->key;
so->remove_shape(shape);
}
@@ -1212,7 +1212,7 @@ void GodotPhysicsServer2D::free(RID p_rid) {
GodotSpace2D *space = space_owner.get_or_null(p_rid);
while (space->get_objects().size()) {
- GodotCollisionObject2D *co = (GodotCollisionObject2D *)space->get_objects().front()->get();
+ GodotCollisionObject2D *co = static_cast<GodotCollisionObject2D *>(*space->get_objects().begin());
co->set_space(nullptr);
}
@@ -1250,11 +1250,11 @@ void GodotPhysicsServer2D::step(real_t p_step) {
island_count = 0;
active_objects = 0;
collision_pairs = 0;
- for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) {
- stepper->step((GodotSpace2D *)E->get(), p_step);
- island_count += E->get()->get_island_count();
- active_objects += E->get()->get_active_objects();
- collision_pairs += E->get()->get_collision_pairs();
+ for (const GodotSpace2D *E : active_spaces) {
+ stepper->step(const_cast<GodotSpace2D *>(E), p_step);
+ island_count += E->get_island_count();
+ active_objects += E->get_active_objects();
+ collision_pairs += E->get_collision_pairs();
}
}
@@ -1271,8 +1271,8 @@ void GodotPhysicsServer2D::flush_queries() {
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
- for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) {
- GodotSpace2D *space = (GodotSpace2D *)E->get();
+ for (const GodotSpace2D *E : active_spaces) {
+ GodotSpace2D *space = const_cast<GodotSpace2D *>(E);
space->call_queries();
}
@@ -1292,9 +1292,9 @@ void GodotPhysicsServer2D::flush_queries() {
total_time[i] = 0;
}
- for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ for (const GodotSpace2D *E : active_spaces) {
for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
- total_time[i] += E->get()->get_elapsed_time(GodotSpace2D::ElapsedTime(i));
+ total_time[i] += E->get_elapsed_time(GodotSpace2D::ElapsedTime(i));
}
}
diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h
index 0a84caadc5..2af6e5c97c 100644
--- a/servers/physics_2d/godot_physics_server_2d.h
+++ b/servers/physics_2d/godot_physics_server_2d.h
@@ -56,7 +56,7 @@ class GodotPhysicsServer2D : public PhysicsServer2D {
bool flushing_queries = false;
GodotStep2D *stepper = nullptr;
- Set<const GodotSpace2D *> active_spaces;
+ HashSet<const GodotSpace2D *> active_spaces;
mutable RID_PtrOwner<GodotShape2D, true> shape_owner;
mutable RID_PtrOwner<GodotSpace2D, true> space_owner;
diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp
index b5dbb8a2dd..72ade3757b 100644
--- a/servers/physics_2d/godot_shape_2d.cpp
+++ b/servers/physics_2d/godot_shape_2d.cpp
@@ -37,7 +37,7 @@ void GodotShape2D::configure(const Rect2 &p_aabb) {
aabb = p_aabb;
configured = true;
for (const KeyValue<GodotShapeOwner2D *, int> &E : owners) {
- GodotShapeOwner2D *co = (GodotShapeOwner2D *)E.key;
+ GodotShapeOwner2D *co = const_cast<GodotShapeOwner2D *>(E.key);
co->_shape_changed();
}
}
@@ -50,20 +50,20 @@ Vector2 GodotShape2D::get_support(const Vector2 &p_normal) const {
}
void GodotShape2D::add_owner(GodotShapeOwner2D *p_owner) {
- Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner);
+ HashMap<GodotShapeOwner2D *, int>::Iterator E = owners.find(p_owner);
if (E) {
- E->get()++;
+ E->value++;
} else {
owners[p_owner] = 1;
}
}
void GodotShape2D::remove_owner(GodotShapeOwner2D *p_owner) {
- Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner);
+ HashMap<GodotShapeOwner2D *, int>::Iterator E = owners.find(p_owner);
ERR_FAIL_COND(!E);
- E->get()--;
- if (E->get() == 0) {
- owners.erase(E);
+ E->value--;
+ if (E->value == 0) {
+ owners.remove(E);
}
}
@@ -71,7 +71,7 @@ bool GodotShape2D::is_owner(GodotShapeOwner2D *p_owner) const {
return owners.has(p_owner);
}
-const Map<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const {
+const HashMap<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const {
return owners;
}
@@ -841,7 +841,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
const Vector2 *arr = p2arr.ptr();
- Map<Point2, int> pointmap;
+ HashMap<Point2, int> pointmap;
for (int i = 0; i < len; i += 2) {
Point2 p1 = arr[i];
Point2 p2 = arr[i + 1];
@@ -868,7 +868,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
}
points.resize(pointmap.size());
- aabb.position = pointmap.front()->key();
+ aabb.position = pointmap.begin()->key;
for (const KeyValue<Point2, int> &E : pointmap) {
aabb.expand_to(E.key);
points.write[E.value] = E.key;
diff --git a/servers/physics_2d/godot_shape_2d.h b/servers/physics_2d/godot_shape_2d.h
index fb52cbce20..cede01e18d 100644
--- a/servers/physics_2d/godot_shape_2d.h
+++ b/servers/physics_2d/godot_shape_2d.h
@@ -50,7 +50,7 @@ class GodotShape2D {
bool configured = false;
real_t custom_bias = 0.0;
- Map<GodotShapeOwner2D *, int> owners;
+ HashMap<GodotShapeOwner2D *, int> owners;
protected:
void configure(const Rect2 &p_aabb);
@@ -86,7 +86,7 @@ public:
void add_owner(GodotShapeOwner2D *p_owner);
void remove_owner(GodotShapeOwner2D *p_owner);
bool is_owner(GodotShapeOwner2D *p_owner) const;
- const Map<GodotShapeOwner2D *, int> &get_owners() const;
+ const HashMap<GodotShapeOwner2D *, int> &get_owners() const;
_FORCE_INLINE_ void get_supports_transformed_cast(const Vector2 &p_cast, const Vector2 &p_normal, const Transform2D &p_xform, Vector2 *r_supports, int &r_amount) const {
get_supports(p_xform.basis_xform_inv(p_normal).normalized(), r_supports, r_amount);
@@ -134,7 +134,7 @@ public:
real_t mina, maxa; \
real_t minb, maxb; \
Transform2D ofsb = p_transform; \
- ofsb.elements[2] += p_cast; \
+ ofsb.columns[2] += p_cast; \
project_range(p_normal, p_transform, mina, maxa); \
project_range(p_normal, ofsb, minb, maxb); \
r_min = MIN(mina, minb); \
diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp
index 68dac67d21..166ec3049e 100644
--- a/servers/physics_2d/godot_space_2d.cpp
+++ b/servers/physics_2d/godot_space_2d.cpp
@@ -158,7 +158,7 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame
if (p_parameters.hit_from_inside) {
// Hit shape at starting point.
min_d = 0;
- res_point = local_from;
+ res_point = begin;
res_normal = Vector2();
res_shape = shape_idx;
res_obj = col_obj;
@@ -403,7 +403,7 @@ struct _RestCallbackData2D {
};
static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
- _RestCallbackData2D *rd = (_RestCallbackData2D *)p_userdata;
+ _RestCallbackData2D *rd = static_cast<_RestCallbackData2D *>(p_userdata);
Vector2 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
@@ -633,7 +633,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.columns[1].normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
cbk.valid_depth = MAX(owc_margin, margin); //user specified, but never less than actual margin or it won't work
@@ -710,7 +710,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
break;
}
- body_transform.elements[2] += recover_motion;
+ body_transform.columns[2] += recover_motion;
body_aabb.position += recover_motion;
recover_attempts--;
@@ -788,7 +788,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
//test initial overlap
if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
- Vector2 direction = col_obj_shape_xform.get_axis(1).normalized();
+ Vector2 direction = col_obj_shape_xform.columns[1].normalized();
if (motion_normal.dot(direction) < 0) {
continue;
}
@@ -838,7 +838,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
cbk.amount = 0;
cbk.passed = 0;
cbk.ptr = cd;
- cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.columns[1].normalized();
cbk.valid_depth = 10e20;
@@ -874,14 +874,14 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
bool collided = false;
- if (recovered || (safe < 1)) {
+ if ((p_parameters.recovery_as_collision && recovered) || (safe < 1)) {
if (safe >= 1) {
best_shape = -1; //no best shape with cast, reset to -1
}
//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
- ugt.elements[2] += p_parameters.motion * unsafe;
+ ugt.columns[2] += p_parameters.motion * unsafe;
_RestCallbackData2D rcd;
@@ -929,7 +929,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+ rcd.valid_dir = col_obj_shape_xform.columns[1].normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
rcd.valid_depth = MAX(owc_margin, margin); //user specified, but never less than actual margin or it won't work
@@ -995,11 +995,8 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
return collided;
}
+// Assumes a valid collision pair, this should have been checked beforehand in the BVH or octree.
void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self) {
- if (!A->interacts_with(B)) {
- return nullptr;
- }
-
GodotCollisionObject2D::Type type_A = A->get_type();
GodotCollisionObject2D::Type type_B = B->get_type();
if (type_A > type_B) {
@@ -1008,7 +1005,7 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A
SWAP(type_A, type_B);
}
- GodotSpace2D *self = (GodotSpace2D *)p_self;
+ GodotSpace2D *self = static_cast<GodotSpace2D *>(p_self);
self->collision_pairs++;
if (type_A == GodotCollisionObject2D::TYPE_AREA) {
@@ -1024,7 +1021,7 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A
}
} else {
- GodotBodyPair2D *b = memnew(GodotBodyPair2D((GodotBody2D *)A, p_subindex_A, (GodotBody2D *)B, p_subindex_B));
+ GodotBodyPair2D *b = memnew(GodotBodyPair2D(static_cast<GodotBody2D *>(A), p_subindex_A, static_cast<GodotBody2D *>(B), p_subindex_B));
return b;
}
@@ -1036,9 +1033,9 @@ void GodotSpace2D::_broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_
return;
}
- GodotSpace2D *self = (GodotSpace2D *)p_self;
+ GodotSpace2D *self = static_cast<GodotSpace2D *>(p_self);
self->collision_pairs--;
- GodotConstraint2D *c = (GodotConstraint2D *)p_data;
+ GodotConstraint2D *c = static_cast<GodotConstraint2D *>(p_data);
memdelete(c);
}
@@ -1076,7 +1073,7 @@ void GodotSpace2D::remove_object(GodotCollisionObject2D *p_object) {
objects.erase(p_object);
}
-const Set<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const {
+const HashSet<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const {
return objects;
}
diff --git a/servers/physics_2d/godot_space_2d.h b/servers/physics_2d/godot_space_2d.h
index 5d97721176..b6fc48bd70 100644
--- a/servers/physics_2d/godot_space_2d.h
+++ b/servers/physics_2d/godot_space_2d.h
@@ -92,7 +92,7 @@ private:
static void *_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self);
static void _broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self);
- Set<GodotCollisionObject2D *> objects;
+ HashSet<GodotCollisionObject2D *> objects;
GodotArea2D *area = nullptr;
@@ -156,7 +156,7 @@ public:
void add_object(GodotCollisionObject2D *p_object);
void remove_object(GodotCollisionObject2D *p_object);
- const Set<GodotCollisionObject2D *> &get_objects() const;
+ const HashSet<GodotCollisionObject2D *> &get_objects() const;
_FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; }
_FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp
index 866c415440..551fd9329f 100644
--- a/servers/physics_2d/godot_step_2d.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -47,7 +47,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D
}
for (const Pair<GodotConstraint2D *, int> &E : p_body->get_constraint_list()) {
- GodotConstraint2D *constraint = (GodotConstraint2D *)E.first;
+ GodotConstraint2D *constraint = const_cast<GodotConstraint2D *>(E.first);
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -168,8 +168,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
const SelfList<GodotArea2D>::List &aml = p_space->get_moved_area_list();
while (aml.first()) {
- for (const Set<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) {
- GodotConstraint2D *constraint = E->get();
+ for (GodotConstraint2D *E : aml.first()->self()->get_constraints()) {
+ GodotConstraint2D *constraint = E;
if (constraint->get_island_step() == _step) {
continue;
}
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index 23c8079538..ba362740b2 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -113,7 +113,7 @@ struct MinkowskiDiff {
real_t margin_A = 0.0;
real_t margin_B = 0.0;
- Vector3 (*get_support)(const GodotShape3D*, const Vector3&, real_t);
+ Vector3 (*get_support)(const GodotShape3D*, const Vector3&, real_t) = nullptr;
void Initialize(const GodotShape3D* shape0, const Transform3D& wtrs0, const real_t margin0,
const GodotShape3D* shape1, const Transform3D& wtrs1, const real_t margin1) {
@@ -191,13 +191,13 @@ struct GJK
/* Fields */
tShape m_shape;
Vector3 m_ray;
- real_t m_distance;
+ real_t m_distance = 0.0f;
sSimplex m_simplices[2];
sSV m_store[4];
sSV* m_free[4];
- U m_nfree;
- U m_current;
- sSimplex* m_simplex;
+ U m_nfree = 0;
+ U m_current = 0;
+ sSimplex* m_simplex = nullptr;
eStatus::_ m_status;
/* Methods */
GJK()
@@ -548,12 +548,12 @@ struct GJK
struct sFace
{
Vector3 n;
- real_t d;
+ real_t d = 0.0f;
sSV* c[3];
sFace* f[3];
sFace* l[2];
U1 e[3];
- U1 pass;
+ U1 pass = 0;
};
struct sList
{
@@ -583,10 +583,10 @@ struct GJK
eStatus::_ m_status;
GJK::sSimplex m_result;
Vector3 m_normal;
- real_t m_depth;
+ real_t m_depth = 0.0f;
sSV m_sv_store[EPA_MAX_VERTICES];
sFace m_fc_store[EPA_MAX_FACES];
- U m_nextsv;
+ U m_nextsv = 0;
sList m_hull;
sList m_stock;
/* Methods */
diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp
index e7df23d0d8..e2ad765d62 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -254,22 +254,24 @@ void GodotArea3D::call_queries() {
resptr[i] = &res[i];
}
- for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_bodies.erase(E);
+ for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_bodies.begin(); E;) {
+ if (E->value.state == 0) { // Nothing happened
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_bodies.remove(E);
E = next;
continue;
}
- res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
+ res[0] = E->value.state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
+ res[1] = E->key.rid;
+ res[2] = E->key.instance_id;
+ res[3] = E->key.body_shape;
+ res[4] = E->key.area_shape;
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_bodies.erase(E);
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_bodies.remove(E);
E = next;
Callable::CallError ce;
@@ -290,22 +292,24 @@ void GodotArea3D::call_queries() {
resptr[i] = &res[i];
}
- for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_areas.erase(E);
+ for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_areas.begin(); E;) {
+ if (E->value.state == 0) { // Nothing happened
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_areas.remove(E);
E = next;
continue;
}
- res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
+ res[0] = E->value.state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
+ res[1] = E->key.rid;
+ res[2] = E->key.instance_id;
+ res[3] = E->key.body_shape;
+ res[4] = E->key.area_shape;
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_areas.erase(E);
+ HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E;
+ ++next;
+ monitored_areas.remove(E);
E = next;
Callable::CallError ce;
diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h
index ce64fc802a..a00451f602 100644
--- a/servers/physics_3d/godot_area_3d.h
+++ b/servers/physics_3d/godot_area_3d.h
@@ -72,16 +72,15 @@ class GodotArea3D : public GodotCollisionObject3D {
uint32_t body_shape = 0;
uint32_t area_shape = 0;
- _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const {
- if (rid == p_key.rid) {
- if (body_shape == p_key.body_shape) {
- return area_shape < p_key.area_shape;
- } else {
- return body_shape < p_key.body_shape;
- }
- } else {
- return rid < p_key.rid;
- }
+ static uint32_t hash(const BodyKey &p_key) {
+ uint32_t h = hash_one_uint64(p_key.rid.get_id());
+ h = hash_djb2_one_64(p_key.instance_id, h);
+ h = hash_djb2_one_32(p_key.area_shape, h);
+ return hash_djb2_one_32(p_key.body_shape, h);
+ }
+
+ _FORCE_INLINE_ bool operator==(const BodyKey &p_key) const {
+ return rid == p_key.rid && instance_id == p_key.instance_id && body_shape == p_key.body_shape && area_shape == p_key.area_shape;
}
_FORCE_INLINE_ BodyKey() {}
@@ -96,13 +95,13 @@ class GodotArea3D : public GodotCollisionObject3D {
_FORCE_INLINE_ void dec() { state--; }
};
- Map<BodyKey, BodyState> monitored_soft_bodies;
- Map<BodyKey, BodyState> monitored_bodies;
- Map<BodyKey, BodyState> monitored_areas;
+ HashMap<BodyKey, BodyState, BodyKey> monitored_soft_bodies;
+ HashMap<BodyKey, BodyState, BodyKey> monitored_bodies;
+ HashMap<BodyKey, BodyState, BodyKey> monitored_areas;
- Set<GodotConstraint3D *> constraints;
+ HashSet<GodotConstraint3D *> constraints;
- virtual void _shapes_changed();
+ virtual void _shapes_changed() override;
void _queue_monitor_update();
void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode);
@@ -164,7 +163,7 @@ public:
_FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); }
_FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); }
- _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ const HashSet<GodotConstraint3D *> &get_constraints() const { return constraints; }
_FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
void set_monitorable(bool p_monitorable);
@@ -172,7 +171,7 @@ public:
void set_transform(const Transform3D &p_transform);
- void set_space(GodotSpace3D *p_space);
+ void set_space(GodotSpace3D *p_space) override;
void call_queries();
diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h
index c416477204..64b43a3b51 100644
--- a/servers/physics_3d/godot_area_pair_3d.h
+++ b/servers/physics_3d/godot_area_pair_3d.h
@@ -37,8 +37,8 @@
#include "godot_soft_body_3d.h"
class GodotAreaPair3D : public GodotConstraint3D {
- GodotBody3D *body;
- GodotArea3D *area;
+ GodotBody3D *body = nullptr;
+ GodotArea3D *area = nullptr;
int body_shape;
int area_shape;
bool colliding = false;
@@ -55,8 +55,8 @@ public:
};
class GodotArea2Pair3D : public GodotConstraint3D {
- GodotArea3D *area_a;
- GodotArea3D *area_b;
+ GodotArea3D *area_a = nullptr;
+ GodotArea3D *area_b = nullptr;
int shape_a;
int shape_b;
bool colliding_a = false;
@@ -76,8 +76,8 @@ public:
};
class GodotAreaSoftBodyPair3D : public GodotConstraint3D {
- GodotSoftBody3D *soft_body;
- GodotArea3D *area;
+ GodotSoftBody3D *soft_body = nullptr;
+ GodotArea3D *area = nullptr;
int soft_body_shape;
int area_shape;
bool colliding = false;
diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h
index 1906e8aab1..93bd5a0071 100644
--- a/servers/physics_3d/godot_body_3d.h
+++ b/servers/physics_3d/godot_body_3d.h
@@ -109,10 +109,10 @@ class GodotBody3D : public GodotCollisionObject3D {
bool first_time_kinematic = false;
void _mass_properties_changed();
- virtual void _shapes_changed();
+ virtual void _shapes_changed() override;
Transform3D new_transform;
- Map<GodotConstraint3D *, int> constraint_map;
+ HashMap<GodotConstraint3D *, int> constraint_map;
Vector<AreaCMP> areas;
@@ -196,7 +196,7 @@ public:
_FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }
_FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraint_map.erase(p_constraint); }
- const Map<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; }
+ const HashMap<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; }
_FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); }
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }
@@ -301,7 +301,7 @@ public:
_FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; }
_FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; }
- void set_space(GodotSpace3D *p_space);
+ void set_space(GodotSpace3D *p_space) override;
void update_mass_properties();
void reset_mass_properties();
diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp
index 89d5d59161..eebbe0196d 100644
--- a/servers/physics_3d/godot_body_pair_3d.cpp
+++ b/servers/physics_3d/godot_body_pair_3d.cpp
@@ -39,7 +39,7 @@
#define MAX_BIAS_ROTATION (Math_PI / 8)
void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- GodotBodyPair3D *pair = (GodotBodyPair3D *)p_userdata;
+ GodotBodyPair3D *pair = static_cast<GodotBodyPair3D *>(p_userdata);
pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
}
@@ -562,7 +562,7 @@ GodotBodyPair3D::~GodotBodyPair3D() {
}
void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- GodotBodySoftBodyPair3D *pair = (GodotBodySoftBodyPair3D *)p_userdata;
+ GodotBodySoftBodyPair3D *pair = static_cast<GodotBodySoftBodyPair3D *>(p_userdata);
pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
}
diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp
index 9a6b96c411..435c1e8aec 100644
--- a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp
+++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp
@@ -33,51 +33,61 @@
#include "godot_collision_object_3d.h"
GodotBroadPhase3DBVH::ID GodotBroadPhase3DBVH::create(GodotCollisionObject3D *p_object, int p_subindex, const AABB &p_aabb, bool p_static) {
- ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care?
+ uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC;
+ uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC);
+ ID oid = bvh.create(p_object, true, tree_id, tree_collision_mask, p_aabb, p_subindex); // Pair everything, don't care?
return oid + 1;
}
void GodotBroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) {
+ ERR_FAIL_COND(!p_id);
bvh.move(p_id - 1, p_aabb);
}
void GodotBroadPhase3DBVH::set_static(ID p_id, bool p_static) {
- GodotCollisionObject3D *it = bvh.get(p_id - 1);
- bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care?
+ ERR_FAIL_COND(!p_id);
+ uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC;
+ uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC);
+ bvh.set_tree(p_id - 1, tree_id, tree_collision_mask, false);
}
void GodotBroadPhase3DBVH::remove(ID p_id) {
+ ERR_FAIL_COND(!p_id);
bvh.erase(p_id - 1);
}
GodotCollisionObject3D *GodotBroadPhase3DBVH::get_object(ID p_id) const {
+ ERR_FAIL_COND_V(!p_id, nullptr);
GodotCollisionObject3D *it = bvh.get(p_id - 1);
ERR_FAIL_COND_V(!it, nullptr);
return it;
}
bool GodotBroadPhase3DBVH::is_static(ID p_id) const {
- return !bvh.is_pairable(p_id - 1);
+ ERR_FAIL_COND_V(!p_id, false);
+ uint32_t tree_id = bvh.get_tree_id(p_id - 1);
+ return tree_id == 0;
}
int GodotBroadPhase3DBVH::get_subindex(ID p_id) const {
+ ERR_FAIL_COND_V(!p_id, 0);
return bvh.get_subindex(p_id - 1);
}
int GodotBroadPhase3DBVH::cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) {
- return bvh.cull_point(p_point, p_results, p_max_results, p_result_indices);
+ return bvh.cull_point(p_point, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices);
}
int GodotBroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) {
- return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices);
+ return bvh.cull_segment(p_from, p_to, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices);
}
int GodotBroadPhase3DBVH::cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) {
- return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices);
+ return bvh.cull_aabb(p_aabb, p_results, p_max_results, nullptr, 0xFFFFFFFF, p_result_indices);
}
void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B) {
- GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self);
+ GodotBroadPhase3DBVH *bpo = static_cast<GodotBroadPhase3DBVH *>(self);
if (!bpo->pair_callback) {
return nullptr;
}
@@ -86,7 +96,7 @@ void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollis
}
void GodotBroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B, void *pairdata) {
- GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self);
+ GodotBroadPhase3DBVH *bpo = static_cast<GodotBroadPhase3DBVH *>(self);
if (!bpo->unpair_callback) {
return;
}
diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h
index 7138019a9c..ae5a18d955 100644
--- a/servers/physics_3d/godot_broad_phase_3d_bvh.h
+++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h
@@ -36,7 +36,34 @@
#include "core/math/bvh.h"
class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
- BVH_Manager<GodotCollisionObject3D, true, 128> bvh;
+ template <class T>
+ class UserPairTestFunction {
+ public:
+ static bool user_pair_check(const T *p_a, const T *p_b) {
+ // return false if no collision, decided by masks etc
+ return p_a->interacts_with(p_b);
+ }
+ };
+
+ template <class T>
+ class UserCullTestFunction {
+ public:
+ static bool user_cull_check(const T *p_a, const T *p_b) {
+ return true;
+ }
+ };
+
+ enum Tree {
+ TREE_STATIC = 0,
+ TREE_DYNAMIC = 1,
+ };
+
+ enum TreeFlag {
+ TREE_FLAG_STATIC = 1 << TREE_STATIC,
+ TREE_FLAG_DYNAMIC = 1 << TREE_DYNAMIC,
+ };
+
+ BVH_Manager<GodotCollisionObject3D, 2, true, 128, UserPairTestFunction<GodotCollisionObject3D>, UserCullTestFunction<GodotCollisionObject3D>> bvh;
static void *_pair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int);
static void _unpair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int, void *);
@@ -48,23 +75,23 @@ class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
public:
// 0 is an invalid ID
- virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false);
- virtual void move(ID p_id, const AABB &p_aabb);
- virtual void set_static(ID p_id, bool p_static);
- virtual void remove(ID p_id);
+ virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) override;
+ virtual void move(ID p_id, const AABB &p_aabb) override;
+ virtual void set_static(ID p_id, bool p_static) override;
+ virtual void remove(ID p_id) override;
- virtual GodotCollisionObject3D *get_object(ID p_id) const;
- virtual bool is_static(ID p_id) const;
- virtual int get_subindex(ID p_id) const;
+ virtual GodotCollisionObject3D *get_object(ID p_id) const override;
+ virtual bool is_static(ID p_id) const override;
+ virtual int get_subindex(ID p_id) const override;
- virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr);
- virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr);
- virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override;
+ virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override;
+ virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) override;
- virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
- virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
+ virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) override;
+ virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) override;
- virtual void update();
+ virtual void update() override;
static GodotBroadPhase3D *_create();
GodotBroadPhase3DBVH();
diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h
index 0178838a25..0f09f21962 100644
--- a/servers/physics_3d/godot_collision_object_3d.h
+++ b/servers/physics_3d/godot_collision_object_3d.h
@@ -112,7 +112,7 @@ public:
_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
- void _shape_changed();
+ void _shape_changed() override;
_FORCE_INLINE_ Type get_type() const { return type; }
void add_shape(GodotShape3D *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false);
@@ -169,11 +169,11 @@ public:
return p_other->collision_layer & collision_mask;
}
- _FORCE_INLINE_ bool interacts_with(GodotCollisionObject3D *p_other) const {
+ _FORCE_INLINE_ bool interacts_with(const GodotCollisionObject3D *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}
- void remove_shape(GodotShape3D *p_shape);
+ void remove_shape(GodotShape3D *p_shape) override;
void remove_shape(int p_index);
virtual void set_space(GodotSpace3D *p_space) = 0;
diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp
index 81e1a88366..b2d3e4d876 100644
--- a/servers/physics_3d/godot_collision_solver_3d.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "godot_collision_solver_3d.h"
+
#include "godot_collision_solver_3d_sat.h"
#include "godot_soft_body_3d.h"
@@ -93,7 +94,7 @@ bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A,
const GodotSeparationRayShape3D *ray = static_cast<const GodotSeparationRayShape3D *>(p_shape_A);
Vector3 from = p_transform_A.origin;
- Vector3 to = from + p_transform_A.basis.get_axis(2) * (ray->get_length() + p_margin);
+ Vector3 to = from + p_transform_A.basis.get_column(2) * (ray->get_length() + p_margin);
Vector3 support_A = to;
Transform3D ai = p_transform_B.affine_inverse();
@@ -141,7 +142,7 @@ struct _SoftBodyContactCollisionInfo {
};
void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- _SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata);
+ _SoftBodyContactCollisionInfo &cinfo = *(static_cast<_SoftBodyContactCollisionInfo *>(p_userdata));
++cinfo.contact_count;
@@ -170,7 +171,7 @@ struct _SoftBodyQueryInfo {
};
bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) {
- _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
+ _SoftBodyQueryInfo &query_cinfo = *(static_cast<_SoftBodyQueryInfo *>(p_userdata));
Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index);
@@ -189,7 +190,7 @@ bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, voi
}
bool GodotCollisionSolver3D::soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex) {
- _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
+ _SoftBodyQueryInfo &query_cinfo = *(static_cast<_SoftBodyQueryInfo *>(p_userdata));
query_cinfo.shape_A = p_convex;
@@ -251,7 +252,7 @@ bool GodotCollisionSolver3D::solve_soft_body(const GodotShape3D *p_shape_A, cons
// Calculate AABB for internal concave shape query (in local space).
AABB local_aabb;
for (int i = 0; i < 3; i++) {
- Vector3 axis(p_transform_A.basis.get_axis(i));
+ Vector3 axis(p_transform_A.basis.get_column(i));
real_t axis_scale = 1.0 / axis.length();
real_t smin = soft_body_aabb.position[i];
@@ -276,23 +277,24 @@ bool GodotCollisionSolver3D::solve_soft_body(const GodotShape3D *p_shape_A, cons
}
struct _ConcaveCollisionInfo {
- const Transform3D *transform_A;
- const GodotShape3D *shape_A;
- const Transform3D *transform_B;
- GodotCollisionSolver3D::CallbackResult result_callback;
- void *userdata;
- bool swap_result;
- bool collided;
- int aabb_tests;
- int collisions;
- bool tested;
- real_t margin_A;
- real_t margin_B;
- Vector3 close_A, close_B;
+ const Transform3D *transform_A = nullptr;
+ const GodotShape3D *shape_A = nullptr;
+ const Transform3D *transform_B = nullptr;
+ GodotCollisionSolver3D::CallbackResult result_callback = nullptr;
+ void *userdata = nullptr;
+ bool swap_result = false;
+ bool collided = false;
+ int aabb_tests = 0;
+ int collisions = 0;
+ bool tested = false;
+ real_t margin_A = 0.0f;
+ real_t margin_B = 0.0f;
+ Vector3 close_A;
+ Vector3 close_B;
};
bool GodotCollisionSolver3D::concave_callback(void *p_userdata, GodotShape3D *p_convex) {
- _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata);
+ _ConcaveCollisionInfo &cinfo = *(static_cast<_ConcaveCollisionInfo *>(p_userdata));
cinfo.aabb_tests++;
bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, nullptr, cinfo.margin_A, cinfo.margin_B);
@@ -331,7 +333,7 @@ bool GodotCollisionSolver3D::solve_concave(const GodotShape3D *p_shape_A, const
AABB local_aabb;
for (int i = 0; i < 3; i++) {
- Vector3 axis(p_transform_B.basis.get_axis(i));
+ Vector3 axis(p_transform_B.basis.get_column(i));
real_t axis_scale = 1.0 / axis.length();
axis *= axis_scale;
@@ -422,7 +424,7 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T
}
bool GodotCollisionSolver3D::concave_distance_callback(void *p_userdata, GodotShape3D *p_convex) {
- _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata);
+ _ConcaveCollisionInfo &cinfo = *(static_cast<_ConcaveCollisionInfo *>(p_userdata));
cinfo.aabb_tests++;
Vector3 close_A, close_B;
@@ -540,7 +542,7 @@ bool GodotCollisionSolver3D::solve_distance(const GodotShape3D *p_shape_A, const
AABB local_aabb;
for (int i = 0; i < 3; i++) {
- Vector3 axis(p_transform_B.basis.get_axis(i));
+ Vector3 axis(p_transform_B.basis.get_column(i));
real_t axis_scale = ((real_t)1.0) / axis.length();
axis *= axis_scale;
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index ca429040f5..20e9300778 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -68,7 +68,7 @@
*************************************************************************/
struct _CollectorCallback {
- GodotCollisionSolver3D::CallbackResult callback;
+ GodotCollisionSolver3D::CallbackResult callback = nullptr;
void *userdata = nullptr;
bool swap = false;
bool collided = false;
@@ -792,7 +792,7 @@ static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_
// test faces
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_b.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_b.basis.get_column(i).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -819,7 +819,7 @@ static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_
// test edges
for (int i = 0; i < 3; i++) {
- Vector3 axis = point_axis.cross(p_transform_b.basis.get_axis(i)).cross(p_transform_b.basis.get_axis(i)).normalized();
+ Vector3 axis = point_axis.cross(p_transform_b.basis.get_column(i)).cross(p_transform_b.basis.get_column(i)).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -842,7 +842,7 @@ static void _collision_sphere_capsule(const GodotShape3D *p_a, const Transform3D
//capsule sphere 1, sphere
- Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
+ Vector3 capsule_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Vector3 capsule_ball_1 = p_transform_b.origin + capsule_axis;
@@ -883,7 +883,7 @@ static void _collision_sphere_cylinder(const GodotShape3D *p_a, const Transform3
}
// Cylinder B end caps.
- Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1).normalized();
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_column(1).normalized();
if (!separator.test_axis(cylinder_B_axis)) {
return;
}
@@ -897,8 +897,8 @@ static void _collision_sphere_cylinder(const GodotShape3D *p_a, const Transform3
// Closest point to cylinder caps.
const Vector3 &sphere_center = p_transform_a.origin;
- Vector3 cyl_axis = p_transform_b.basis.get_axis(1);
- Vector3 cap_axis = p_transform_b.basis.get_axis(0);
+ Vector3 cyl_axis = p_transform_b.basis.get_column(1);
+ Vector3 cap_axis = p_transform_b.basis.get_column(0);
real_t height_scale = cyl_axis.length();
real_t cap_dist = cylinder_B->get_height() * 0.5 * height_scale;
cyl_axis /= height_scale;
@@ -1063,7 +1063,7 @@ static void _collision_box_box(const GodotShape3D *p_a, const Transform3D &p_tra
// test faces of A
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_a.basis.get_column(i).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1073,7 +1073,7 @@ static void _collision_box_box(const GodotShape3D *p_a, const Transform3D &p_tra
// test faces of B
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_b.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_b.basis.get_column(i).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1083,7 +1083,7 @@ static void _collision_box_box(const GodotShape3D *p_a, const Transform3D &p_tra
// test combined edges
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- Vector3 axis = p_transform_a.basis.get_axis(i).cross(p_transform_b.basis.get_axis(j));
+ Vector3 axis = p_transform_a.basis.get_column(i).cross(p_transform_b.basis.get_column(j));
if (Math::is_zero_approx(axis.length_squared())) {
continue;
@@ -1129,14 +1129,14 @@ static void _collision_box_box(const GodotShape3D *p_a, const Transform3D &p_tra
for (int i = 0; i < 3; i++) {
//a ->b
- Vector3 axis_a = p_transform_a.basis.get_axis(i);
+ Vector3 axis_a = p_transform_a.basis.get_column(i);
if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) {
return;
}
//b ->a
- Vector3 axis_b = p_transform_b.basis.get_axis(i);
+ Vector3 axis_b = p_transform_b.basis.get_column(i);
if (!separator.test_axis(axis_ab.cross(axis_b).cross(axis_b).normalized())) {
return;
@@ -1160,20 +1160,20 @@ static void _collision_box_capsule(const GodotShape3D *p_a, const Transform3D &p
// faces of A
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_a.basis.get_column(i).normalized();
if (!separator.test_axis(axis)) {
return;
}
}
- Vector3 cyl_axis = p_transform_b.basis.get_axis(1).normalized();
+ Vector3 cyl_axis = p_transform_b.basis.get_column(1).normalized();
// edges of A, capsule cylinder
for (int i = 0; i < 3; i++) {
// cylinder
- Vector3 box_axis = p_transform_a.basis.get_axis(i);
+ Vector3 box_axis = p_transform_a.basis.get_column(i);
Vector3 axis = box_axis.cross(cyl_axis);
if (Math::is_zero_approx(axis.length_squared())) {
continue;
@@ -1196,7 +1196,7 @@ static void _collision_box_capsule(const GodotShape3D *p_a, const Transform3D &p
he.z *= (k * 2 - 1);
Vector3 point = p_transform_a.origin;
for (int l = 0; l < 3; l++) {
- point += p_transform_a.basis.get_axis(l) * he[l];
+ point += p_transform_a.basis.get_column(l) * he[l];
}
//Vector3 axis = (point - cyl_axis * cyl_axis.dot(point)).normalized();
@@ -1212,7 +1212,7 @@ static void _collision_box_capsule(const GodotShape3D *p_a, const Transform3D &p
// capsule balls, edges of A
for (int i = 0; i < 2; i++) {
- Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
+ Vector3 capsule_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Vector3 sphere_pos = p_transform_b.origin + ((i == 0) ? capsule_axis : -capsule_axis);
@@ -1234,7 +1234,7 @@ static void _collision_box_capsule(const GodotShape3D *p_a, const Transform3D &p
// test edges of A
for (int j = 0; j < 3; j++) {
- Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(j)).cross(p_transform_a.basis.get_axis(j)).normalized();
+ Vector3 axis = point_axis.cross(p_transform_a.basis.get_column(j)).cross(p_transform_a.basis.get_column(j)).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1258,14 +1258,14 @@ static void _collision_box_cylinder(const GodotShape3D *p_a, const Transform3D &
// Faces of A.
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_a.basis.get_column(i).normalized();
if (!separator.test_axis(axis)) {
return;
}
}
- Vector3 cyl_axis = p_transform_b.basis.get_axis(1).normalized();
+ Vector3 cyl_axis = p_transform_b.basis.get_column(1).normalized();
// Cylinder end caps.
{
@@ -1276,7 +1276,7 @@ static void _collision_box_cylinder(const GodotShape3D *p_a, const Transform3D &
// Edges of A, cylinder lateral surface.
for (int i = 0; i < 3; i++) {
- Vector3 box_axis = p_transform_a.basis.get_axis(i);
+ Vector3 box_axis = p_transform_a.basis.get_column(i);
Vector3 axis = box_axis.cross(cyl_axis);
if (Math::is_zero_approx(axis.length_squared())) {
continue;
@@ -1300,7 +1300,7 @@ static void _collision_box_cylinder(const GodotShape3D *p_a, const Transform3D &
Vector3 &point = vertices_A[i * 2 * 2 + j * 2 + k];
point = p_transform_a.origin;
for (int l = 0; l < 3; l++) {
- point += p_transform_a.basis.get_axis(l) * extent[l];
+ point += p_transform_a.basis.get_column(l) * extent[l];
}
}
}
@@ -1380,7 +1380,7 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
// faces of A
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_a.basis.get_column(i).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1401,7 +1401,7 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
// A<->B edges
for (int i = 0; i < 3; i++) {
- Vector3 e1 = p_transform_a.basis.get_axis(i);
+ Vector3 e1 = p_transform_a.basis.get_column(i);
for (int j = 0; j < edge_count; j++) {
Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]);
@@ -1438,7 +1438,7 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
for (int i = 0; i < 3; i++) {
//a ->b
- Vector3 axis_a = p_transform_a.basis.get_axis(i);
+ Vector3 axis_a = p_transform_a.basis.get_column(i);
if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) {
return;
@@ -1456,7 +1456,7 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
he.z *= (k * 2 - 1);
Vector3 point = p_transform_a.origin;
for (int l = 0; l < 3; l++) {
- point += p_transform_a.basis.get_axis(l) * he[l];
+ point += p_transform_a.basis.get_column(l) * he[l];
}
for (int e = 0; e < edge_count; e++) {
@@ -1497,7 +1497,7 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr
// faces of A
for (int i = 0; i < 3; i++) {
- Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
+ Vector3 axis = p_transform_a.basis.get_column(i).normalized();
if (axis.dot(normal) < 0.0) {
axis *= -1.0;
}
@@ -1513,7 +1513,7 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr
Vector3 e = vertex[i] - vertex[(i + 1) % 3];
for (int j = 0; j < 3; j++) {
- Vector3 axis = e.cross(p_transform_a.basis.get_axis(j)).normalized();
+ Vector3 axis = e.cross(p_transform_a.basis.get_column(j)).normalized();
if (axis.dot(normal) < 0.0) {
axis *= -1.0;
}
@@ -1550,7 +1550,7 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr
for (int i = 0; i < 3; i++) {
//a ->b
- Vector3 axis_a = p_transform_a.basis.get_axis(i);
+ Vector3 axis_a = p_transform_a.basis.get_column(i);
Vector3 axis = axis_ab.cross(axis_a).cross(axis_a).normalized();
if (axis.dot(normal) < 0.0) {
@@ -1573,7 +1573,7 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr
he.z *= (k * 2 - 1);
Vector3 point = p_transform_a.origin;
for (int l = 0; l < 3; l++) {
- point += p_transform_a.basis.get_axis(l) * he[l];
+ point += p_transform_a.basis.get_column(l) * he[l];
}
for (int e = 0; e < 3; e++) {
@@ -1623,8 +1623,8 @@ static void _collision_capsule_capsule(const GodotShape3D *p_a, const Transform3
// some values
- Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
- Vector3 capsule_B_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
+ Vector3 capsule_A_axis = p_transform_a.basis.get_column(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
+ Vector3 capsule_B_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis;
Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis;
@@ -1686,14 +1686,14 @@ static void _collision_capsule_cylinder(const GodotShape3D *p_a, const Transform
}
// Cylinder B end caps.
- Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1).normalized();
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_column(1).normalized();
if (!separator.test_axis(cylinder_B_axis)) {
return;
}
// Cylinder edge against capsule balls.
- Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1);
+ Vector3 capsule_A_axis = p_transform_a.basis.get_column(1);
Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
@@ -1772,7 +1772,7 @@ static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Tra
for (int i = 0; i < edge_count; i++) {
// cylinder
Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].a]) - p_transform_b.basis.xform(vertices[edges[i].b]);
- Vector3 axis = edge_axis.cross(p_transform_a.basis.get_axis(1)).normalized();
+ Vector3 axis = edge_axis.cross(p_transform_a.basis.get_column(1)).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1784,7 +1784,7 @@ static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Tra
for (int i = 0; i < 2; i++) {
// edges of B, capsule cylinder
- Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
+ Vector3 capsule_axis = p_transform_a.basis.get_column(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis);
@@ -1824,7 +1824,7 @@ static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D &
// edges of B, capsule cylinder
- Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
+ Vector3 capsule_axis = p_transform_a.basis.get_column(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
for (int i = 0; i < 3; i++) {
// edge-cylinder
@@ -1895,8 +1895,8 @@ static void _collision_cylinder_cylinder(const GodotShape3D *p_a, const Transfor
SeparatorAxisTest<GodotCylinderShape3D, GodotCylinderShape3D, withMargin> separator(cylinder_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
- Vector3 cylinder_A_axis = p_transform_a.basis.get_axis(1);
- Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1);
+ Vector3 cylinder_A_axis = p_transform_a.basis.get_column(1);
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_column(1);
if (!separator.test_previous_axis()) {
return;
@@ -1983,7 +1983,7 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D
return;
}
- Vector3 cyl_axis = p_transform_a.basis.get_axis(1).normalized();
+ Vector3 cyl_axis = p_transform_a.basis.get_column(1).normalized();
if (cyl_axis.dot(normal) < 0.0) {
cyl_axis *= -1.0;
}
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index a1912dc660..b735283ebe 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -920,7 +920,7 @@ RID GodotPhysicsServer3D::soft_body_create() {
return rid;
}
-void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) {
+void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) {
GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
ERR_FAIL_COND(!soft_body);
@@ -1355,7 +1355,7 @@ int GodotPhysicsServer3D::joint_get_solver_priority(RID p_joint) const {
return joint->get_priority();
}
-void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
+void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) {
GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
ERR_FAIL_COND(!joint);
@@ -1531,7 +1531,7 @@ void GodotPhysicsServer3D::free(RID p_rid) {
GodotShape3D *shape = shape_owner.get_or_null(p_rid);
while (shape->get_owners().size()) {
- GodotShapeOwner3D *so = shape->get_owners().front()->key();
+ GodotShapeOwner3D *so = shape->get_owners().begin()->key;
so->remove_shape(shape);
}
@@ -1570,7 +1570,7 @@ void GodotPhysicsServer3D::free(RID p_rid) {
GodotSpace3D *space = space_owner.get_or_null(p_rid);
while (space->get_objects().size()) {
- GodotCollisionObject3D *co = (GodotCollisionObject3D *)space->get_objects().front()->get();
+ GodotCollisionObject3D *co = static_cast<GodotCollisionObject3D *>(*space->get_objects().begin());
co->set_space(nullptr);
}
@@ -1611,11 +1611,11 @@ void GodotPhysicsServer3D::step(real_t p_step) {
island_count = 0;
active_objects = 0;
collision_pairs = 0;
- for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) {
- stepper->step((GodotSpace3D *)E->get(), p_step);
- island_count += E->get()->get_island_count();
- active_objects += E->get()->get_active_objects();
- collision_pairs += E->get()->get_collision_pairs();
+ for (const GodotSpace3D *E : active_spaces) {
+ stepper->step(const_cast<GodotSpace3D *>(E), p_step);
+ island_count += E->get_island_count();
+ active_objects += E->get_active_objects();
+ collision_pairs += E->get_collision_pairs();
}
#endif
}
@@ -1635,8 +1635,8 @@ void GodotPhysicsServer3D::flush_queries() {
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
- for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) {
- GodotSpace3D *space = (GodotSpace3D *)E->get();
+ for (const GodotSpace3D *E : active_spaces) {
+ GodotSpace3D *space = const_cast<GodotSpace3D *>(E);
space->call_queries();
}
@@ -1656,9 +1656,9 @@ void GodotPhysicsServer3D::flush_queries() {
total_time[i] = 0;
}
- for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ for (const GodotSpace3D *E : active_spaces) {
for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) {
- total_time[i] += E->get()->get_elapsed_time(GodotSpace3D::ElapsedTime(i));
+ total_time[i] += E->get_elapsed_time(GodotSpace3D::ElapsedTime(i));
}
}
@@ -1671,7 +1671,7 @@ void GodotPhysicsServer3D::flush_queries() {
values.push_back("flush_queries");
values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
- values.push_front("physics");
+ values.push_front("physics_3d");
EngineDebugger::profiler_add_frame_data("servers", values);
}
#endif
@@ -1709,7 +1709,7 @@ void GodotPhysicsServer3D::_update_shapes() {
}
void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- CollCbkData *cbk = (CollCbkData *)p_userdata;
+ CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata);
if (cbk->max == 0) {
return;
diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h
index b903f4808c..1d57451925 100644
--- a/servers/physics_3d/godot_physics_server_3d.h
+++ b/servers/physics_3d/godot_physics_server_3d.h
@@ -54,7 +54,7 @@ class GodotPhysicsServer3D : public PhysicsServer3D {
bool flushing_queries = false;
GodotStep3D *stepper = nullptr;
- Set<const GodotSpace3D *> active_spaces;
+ HashSet<const GodotSpace3D *> active_spaces;
mutable RID_PtrOwner<GodotShape3D, true> shape_owner;
mutable RID_PtrOwner<GodotSpace3D, true> space_owner;
@@ -74,7 +74,7 @@ public:
struct CollCbkData {
int max;
int amount;
- Vector3 *ptr;
+ Vector3 *ptr = nullptr;
};
static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
@@ -253,7 +253,7 @@ public:
virtual RID soft_body_create() override;
- virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override;
+ virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) override;
virtual void soft_body_set_space(RID p_body, RID p_space) override;
virtual RID soft_body_get_space(RID p_body) const override;
@@ -353,7 +353,7 @@ public:
virtual void joint_set_solver_priority(RID p_joint, int p_priority) override;
virtual int joint_get_solver_priority(RID p_joint) const override;
- virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) override;
+ virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) override;
virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const override;
/* MISC */
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 7762c4829e..5e310670a5 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -62,7 +62,7 @@ void GodotShape3D::configure(const AABB &p_aabb) {
aabb = p_aabb;
configured = true;
for (const KeyValue<GodotShapeOwner3D *, int> &E : owners) {
- GodotShapeOwner3D *co = (GodotShapeOwner3D *)E.key;
+ GodotShapeOwner3D *co = const_cast<GodotShapeOwner3D *>(E.key);
co->_shape_changed();
}
}
@@ -76,20 +76,20 @@ Vector3 GodotShape3D::get_support(const Vector3 &p_normal) const {
}
void GodotShape3D::add_owner(GodotShapeOwner3D *p_owner) {
- Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner);
+ HashMap<GodotShapeOwner3D *, int>::Iterator E = owners.find(p_owner);
if (E) {
- E->get()++;
+ E->value++;
} else {
owners[p_owner] = 1;
}
}
void GodotShape3D::remove_owner(GodotShapeOwner3D *p_owner) {
- Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner);
+ HashMap<GodotShapeOwner3D *, int>::Iterator E = owners.find(p_owner);
ERR_FAIL_COND(!E);
- E->get()--;
- if (E->get() == 0) {
- owners.erase(E);
+ E->value--;
+ if (E->value == 0) {
+ owners.remove(E);
}
}
@@ -97,7 +97,7 @@ bool GodotShape3D::is_owner(GodotShapeOwner3D *p_owner) const {
return owners.has(p_owner);
}
-const Map<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const {
+const HashMap<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const {
return owners;
}
@@ -662,7 +662,7 @@ GodotCapsuleShape3D::GodotCapsuleShape3D() {}
/********** CYLINDER *************/
void GodotCylinderShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
- Vector3 cylinder_axis = p_transform.basis.get_axis(1).normalized();
+ Vector3 cylinder_axis = p_transform.basis.get_column(1).normalized();
real_t axis_dot = cylinder_axis.dot(p_normal);
Vector3 local_normal = p_transform.basis.xform_inv(p_normal);
@@ -1438,7 +1438,7 @@ Vector3 GodotConcavePolygonShape3D::get_moment_of_inertia(real_t p_mass) const {
struct _Volume_BVH_Element {
AABB aabb;
Vector3 center;
- int face_index;
+ int face_index = 0;
};
struct _Volume_BVH_CompareX {
@@ -1461,10 +1461,10 @@ struct _Volume_BVH_CompareZ {
struct _Volume_BVH {
AABB aabb;
- _Volume_BVH *left;
- _Volume_BVH *right;
+ _Volume_BVH *left = nullptr;
+ _Volume_BVH *right = nullptr;
- int face_index;
+ int face_index = 0;
};
_Volume_BVH *_volume_build_bvh(_Volume_BVH_Element *p_elements, int p_size, int &count) {
diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h
index 9d171c3928..1fc8f7c711 100644
--- a/servers/physics_3d/godot_shape_3d.h
+++ b/servers/physics_3d/godot_shape_3d.h
@@ -51,7 +51,7 @@ class GodotShape3D {
bool configured = false;
real_t custom_bias = 0.0;
- Map<GodotShapeOwner3D *, int> owners;
+ HashMap<GodotShapeOwner3D *, int> owners;
protected:
void configure(const AABB &p_aabb);
@@ -93,7 +93,7 @@ public:
void add_owner(GodotShapeOwner3D *p_owner);
void remove_owner(GodotShapeOwner3D *p_owner);
bool is_owner(GodotShapeOwner3D *p_owner) const;
- const Map<GodotShapeOwner3D *, int> &get_owners() const;
+ const HashMap<GodotShapeOwner3D *, int> &get_owners() const;
GodotShape3D() {}
virtual ~GodotShape3D();
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 095050b7f3..173843072a 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -33,7 +33,7 @@
#include "godot_space_3d.h"
#include "core/math/geometry_3d.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "servers/rendering_server.h"
// Based on Bullet soft body.
@@ -147,7 +147,7 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) {
}
}
-void GodotSoftBody3D::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) {
+void GodotSoftBody3D::update_rendering_server(PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) {
if (soft_mesh.is_null()) {
return;
}
@@ -429,33 +429,33 @@ uint32_t GodotSoftBody3D::get_node_count() const {
}
real_t GodotSoftBody3D::get_node_inv_mass(uint32_t p_node_index) const {
- ERR_FAIL_COND_V(p_node_index >= nodes.size(), 0.0);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_node_index, nodes.size(), 0.0);
return nodes[p_node_index].im;
}
Vector3 GodotSoftBody3D::get_node_position(uint32_t p_node_index) const {
- ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
+ ERR_FAIL_UNSIGNED_INDEX_V(p_node_index, nodes.size(), Vector3());
return nodes[p_node_index].x;
}
Vector3 GodotSoftBody3D::get_node_velocity(uint32_t p_node_index) const {
- ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
+ ERR_FAIL_UNSIGNED_INDEX_V(p_node_index, nodes.size(), Vector3());
return nodes[p_node_index].v;
}
Vector3 GodotSoftBody3D::get_node_biased_velocity(uint32_t p_node_index) const {
- ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
+ ERR_FAIL_UNSIGNED_INDEX_V(p_node_index, nodes.size(), Vector3());
return nodes[p_node_index].bv;
}
void GodotSoftBody3D::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
- ERR_FAIL_COND(p_node_index >= nodes.size());
+ ERR_FAIL_UNSIGNED_INDEX(p_node_index, nodes.size());
Node &node = nodes[p_node_index];
node.v += p_impulse * node.im;
}
void GodotSoftBody3D::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
- ERR_FAIL_COND(p_node_index >= nodes.size());
+ ERR_FAIL_UNSIGNED_INDEX(p_node_index, nodes.size());
Node &node = nodes[p_node_index];
node.bv += p_impulse * node.im;
}
@@ -465,7 +465,7 @@ uint32_t GodotSoftBody3D::get_face_count() const {
}
void GodotSoftBody3D::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const {
- ERR_FAIL_COND(p_face_index >= faces.size());
+ ERR_FAIL_UNSIGNED_INDEX(p_face_index, faces.size());
const Face &face = faces[p_face_index];
r_point_1 = face.n[0]->x;
r_point_2 = face.n[1]->x;
@@ -473,7 +473,7 @@ void GodotSoftBody3D::get_face_points(uint32_t p_face_index, Vector3 &r_point_1,
}
Vector3 GodotSoftBody3D::get_face_normal(uint32_t p_face_index) const {
- ERR_FAIL_COND_V(p_face_index >= faces.size(), Vector3());
+ ERR_FAIL_UNSIGNED_INDEX_V(p_face_index, faces.size(), Vector3());
return faces[p_face_index].normal;
}
@@ -494,7 +494,7 @@ bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Ve
// Process vertices.
{
uint32_t vertex_count = 0;
- Map<Vector3, uint32_t> unique_vertices;
+ HashMap<Vector3, uint32_t> unique_vertices;
vertices.resize(visual_vertex_count);
map_visual_to_physics.resize(visual_vertex_count);
@@ -502,11 +502,11 @@ bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Ve
for (int visual_vertex_index = 0; visual_vertex_index < visual_vertex_count; ++visual_vertex_index) {
const Vector3 &vertex = p_vertices[visual_vertex_index];
- Map<Vector3, uint32_t>::Element *e = unique_vertices.find(vertex);
+ HashMap<Vector3, uint32_t>::Iterator e = unique_vertices.find(vertex);
uint32_t vertex_id;
if (e) {
// Already existing.
- vertex_id = e->value();
+ vertex_id = e->value;
} else {
// Create new one.
vertex_id = vertex_count++;
@@ -1272,7 +1272,7 @@ struct _SoftBodyIntersectSegmentInfo {
real_t hit_dist_sq = INFINITY;
static bool process_hit(uint32_t p_face_index, void *p_userdata) {
- _SoftBodyIntersectSegmentInfo &query_info = *(_SoftBodyIntersectSegmentInfo *)(p_userdata);
+ _SoftBodyIntersectSegmentInfo &query_info = *(static_cast<_SoftBodyIntersectSegmentInfo *>(p_userdata));
Vector3 points[3];
query_info.soft_body->get_face_points(p_face_index, points[0], points[1], points[2]);
diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h
index 5028e81dd8..86f73c366b 100644
--- a/servers/physics_3d/godot_soft_body_3d.h
+++ b/servers/physics_3d/godot_soft_body_3d.h
@@ -37,8 +37,8 @@
#include "core/math/aabb.h"
#include "core/math/dynamic_bvh.h"
#include "core/math/vector3.h"
+#include "core/templates/hash_set.h"
#include "core/templates/local_vector.h"
-#include "core/templates/set.h"
#include "core/templates/vset.h"
class GodotConstraint3D;
@@ -103,7 +103,7 @@ class GodotSoftBody3D : public GodotCollisionObject3D {
SelfList<GodotSoftBody3D> active_list;
- Set<GodotConstraint3D *> constraints;
+ HashSet<GodotConstraint3D *> constraints;
Vector<AreaCMP> areas;
@@ -123,7 +123,7 @@ public:
_FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); }
_FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); }
- _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ const HashSet<GodotConstraint3D *> &get_constraints() const { return constraints; }
_FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
_FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); }
@@ -153,11 +153,11 @@ public:
}
}
- virtual void set_space(GodotSpace3D *p_space);
+ virtual void set_space(GodotSpace3D *p_space) override;
void set_mesh(RID p_mesh);
- void update_rendering_server(RenderingServerHandler *p_rendering_server_handler);
+ void update_rendering_server(PhysicsServer3DRenderingServerHandler *p_rendering_server_handler);
Vector3 get_vertex_position(int p_index) const;
void set_vertex_position(int p_index, const Vector3 &p_position);
@@ -204,8 +204,8 @@ public:
void predict_motion(real_t p_delta);
void solve_constraints(real_t p_delta);
- _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return ((Node *)p_node)->index; }
- _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return ((Face *)p_face)->index; }
+ _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return static_cast<Node *>(p_node)->index; }
+ _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return static_cast<Face *>(p_face)->index; }
// Return true to stop the query.
// p_index is the node index for AABB query, face index for Ray query.
@@ -215,7 +215,7 @@ public:
void query_ray(const Vector3 &p_from, const Vector3 &p_to, QueryResultCallback p_result_callback, void *p_userdata);
protected:
- virtual void _shapes_changed();
+ virtual void _shapes_changed() override;
private:
void update_normals_and_centroids();
diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp
index 2490a2f506..533d7605ce 100644
--- a/servers/physics_3d/godot_space_3d.cpp
+++ b/servers/physics_3d/godot_space_3d.cpp
@@ -153,7 +153,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
if (p_parameters.hit_from_inside) {
// Hit shape at starting point.
min_d = 0;
- res_point = local_from;
+ res_point = begin;
res_normal = Vector3();
res_shape = shape_idx;
res_obj = col_obj;
@@ -445,7 +445,7 @@ struct _RestCallbackData {
};
static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- _RestCallbackData *rd = (_RestCallbackData *)p_userdata;
+ _RestCallbackData *rd = static_cast<_RestCallbackData *>(p_userdata);
Vector3 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
@@ -906,7 +906,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
}
bool collided = false;
- if (recovered || (safe < 1)) {
+ if ((p_parameters.recovery_as_collision && recovered) || (safe < 1)) {
if (safe >= 1) {
best_shape = -1; //no best shape with cast, reset to -1
}
@@ -1007,11 +1007,8 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
return collided;
}
+// Assumes a valid collision pair, this should have been checked beforehand in the BVH or octree.
void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self) {
- if (!A->interacts_with(B)) {
- return nullptr;
- }
-
GodotCollisionObject3D::Type type_A = A->get_type();
GodotCollisionObject3D::Type type_B = B->get_type();
if (type_A > type_B) {
@@ -1020,7 +1017,7 @@ void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A
SWAP(type_A, type_B);
}
- GodotSpace3D *self = (GodotSpace3D *)p_self;
+ GodotSpace3D *self = static_cast<GodotSpace3D *>(p_self);
self->collision_pairs++;
@@ -1041,10 +1038,10 @@ void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A
}
} else if (type_A == GodotCollisionObject3D::TYPE_BODY) {
if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) {
- GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotSoftBody3D *)B));
+ GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D(static_cast<GodotBody3D *>(A), p_subindex_A, static_cast<GodotSoftBody3D *>(B)));
return soft_pair;
} else {
- GodotBodyPair3D *b = memnew(GodotBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotBody3D *)B, p_subindex_B));
+ GodotBodyPair3D *b = memnew(GodotBodyPair3D(static_cast<GodotBody3D *>(A), p_subindex_A, static_cast<GodotBody3D *>(B), p_subindex_B));
return b;
}
} else {
@@ -1059,9 +1056,9 @@ void GodotSpace3D::_broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_
return;
}
- GodotSpace3D *self = (GodotSpace3D *)p_self;
+ GodotSpace3D *self = static_cast<GodotSpace3D *>(p_self);
self->collision_pairs--;
- GodotConstraint3D *c = (GodotConstraint3D *)p_data;
+ GodotConstraint3D *c = static_cast<GodotConstraint3D *>(p_data);
memdelete(c);
}
@@ -1099,7 +1096,7 @@ void GodotSpace3D::remove_object(GodotCollisionObject3D *p_object) {
objects.erase(p_object);
}
-const Set<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const {
+const HashSet<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const {
return objects;
}
diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h
index ac54c8bf69..df7315e96d 100644
--- a/servers/physics_3d/godot_space_3d.h
+++ b/servers/physics_3d/godot_space_3d.h
@@ -47,7 +47,7 @@ class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D {
GDCLASS(GodotPhysicsDirectSpaceState3D, PhysicsDirectSpaceState3D);
public:
- GodotSpace3D *space;
+ GodotSpace3D *space = nullptr;
virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override;
virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override;
@@ -89,7 +89,7 @@ private:
static void *_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self);
static void _broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self);
- Set<GodotCollisionObject3D *> objects;
+ HashSet<GodotCollisionObject3D *> objects;
GodotArea3D *area = nullptr;
@@ -158,7 +158,7 @@ public:
void add_object(GodotCollisionObject3D *p_object);
void remove_object(GodotCollisionObject3D *p_object);
- const Set<GodotCollisionObject3D *> &get_objects() const;
+ const HashSet<GodotCollisionObject3D *> &get_objects() const;
_FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; }
_FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp
index 63635b224b..99656d01a0 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -49,7 +49,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D
}
for (const KeyValue<GodotConstraint3D *, int> &E : p_body->get_constraint_map()) {
- GodotConstraint3D *constraint = (GodotConstraint3D *)E.key;
+ GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E.key);
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -87,8 +87,8 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D
void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) {
p_soft_body->set_island_step(_step);
- for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) {
- GodotConstraint3D *constraint = (GodotConstraint3D *)E->get();
+ for (const GodotConstraint3D *E : p_soft_body->get_constraints()) {
+ GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E);
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -236,8 +236,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
const SelfList<GodotArea3D>::List &aml = p_space->get_moved_area_list();
while (aml.first()) {
- for (const Set<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) {
- GodotConstraint3D *constraint = E->get();
+ for (GodotConstraint3D *E : aml.first()->self()->get_constraints()) {
+ GodotConstraint3D *constraint = E;
if (constraint->get_island_step() == _step) {
continue;
}
diff --git a/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp
index dc4858ff9a..28cc064a1e 100644
--- a/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp
+++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp
@@ -147,8 +147,8 @@ bool GodotConeTwistJoint3D::setup(real_t p_timestep) {
Vector3 b1Axis1, b1Axis2, b1Axis3;
Vector3 b2Axis1, b2Axis2;
- b1Axis1 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(0));
- b2Axis1 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(0));
+ b1Axis1 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_column(0));
+ b2Axis1 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_column(0));
real_t swing1 = real_t(0.), swing2 = real_t(0.);
@@ -158,7 +158,7 @@ bool GodotConeTwistJoint3D::setup(real_t p_timestep) {
// Get Frame into world space
if (m_swingSpan1 >= real_t(0.05f)) {
- b1Axis2 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(1));
+ b1Axis2 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_column(1));
//swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) );
swx = b2Axis1.dot(b1Axis1);
swy = b2Axis1.dot(b1Axis2);
@@ -169,7 +169,7 @@ bool GodotConeTwistJoint3D::setup(real_t p_timestep) {
}
if (m_swingSpan2 >= real_t(0.05f)) {
- b1Axis3 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(2));
+ b1Axis3 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_column(2));
//swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) );
swx = b2Axis1.dot(b1Axis1);
swy = b2Axis1.dot(b1Axis3);
@@ -199,7 +199,7 @@ bool GodotConeTwistJoint3D::setup(real_t p_timestep) {
// Twist limits
if (m_twistSpan >= real_t(0.)) {
- Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1));
+ Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_column(1));
Quaternion rotationArc = Quaternion(b2Axis1, b1Axis1);
Vector3 TwistRef = rotationArc.xform(b2Axis22);
real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
diff --git a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
index 41e9bf06bb..e0fa940104 100644
--- a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
+++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
@@ -249,8 +249,8 @@ void GodotGeneric6DOFJoint3D::calculateAngleInfo() {
// easier to take the euler rate expression for d(angle[2])/dt with respect
// to the components of w and set that to 0.
- Vector3 axis0 = m_calculatedTransformB.basis.get_axis(0);
- Vector3 axis2 = m_calculatedTransformA.basis.get_axis(2);
+ Vector3 axis0 = m_calculatedTransformB.basis.get_column(0);
+ Vector3 axis2 = m_calculatedTransformA.basis.get_column(2);
m_calculatedAxis[1] = axis2.cross(axis0);
m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
@@ -345,9 +345,9 @@ bool GodotGeneric6DOFJoint3D::setup(real_t p_timestep) {
for (i = 0; i < 3; i++) {
if (m_linearLimits.enable_limit[i] && m_linearLimits.isLimited(i)) {
if (m_useLinearReferenceFrameA) {
- normalWorld = m_calculatedTransformA.basis.get_axis(i);
+ normalWorld = m_calculatedTransformA.basis.get_column(i);
} else {
- normalWorld = m_calculatedTransformB.basis.get_axis(i);
+ normalWorld = m_calculatedTransformB.basis.get_column(i);
}
buildLinearJacobian(
@@ -388,9 +388,9 @@ void GodotGeneric6DOFJoint3D::solve(real_t p_timestep) {
jacDiagABInv = real_t(1.) / m_jacLinear[i].getDiagonal();
if (m_useLinearReferenceFrameA) {
- linear_axis = m_calculatedTransformA.basis.get_axis(i);
+ linear_axis = m_calculatedTransformA.basis.get_column(i);
} else {
- linear_axis = m_calculatedTransformB.basis.get_axis(i);
+ linear_axis = m_calculatedTransformB.basis.get_column(i);
}
m_linearLimits.solveLinearAxis(
diff --git a/servers/physics_3d/joints/godot_hinge_joint_3d.cpp b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp
index 1c4d5dec23..01c59395c8 100644
--- a/servers/physics_3d/joints/godot_hinge_joint_3d.cpp
+++ b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp
@@ -92,16 +92,16 @@ GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const V
m_rbAFrame.origin = pivotInA;
// since no frame is given, assume this to be zero angle and just pick rb transform axis
- Vector3 rbAxisA1 = rbA->get_transform().basis.get_axis(0);
+ Vector3 rbAxisA1 = rbA->get_transform().basis.get_column(0);
Vector3 rbAxisA2;
real_t projection = axisInA.dot(rbAxisA1);
if (projection >= 1.0f - CMP_EPSILON) {
- rbAxisA1 = -rbA->get_transform().basis.get_axis(2);
- rbAxisA2 = rbA->get_transform().basis.get_axis(1);
+ rbAxisA1 = -rbA->get_transform().basis.get_column(2);
+ rbAxisA2 = rbA->get_transform().basis.get_column(1);
} else if (projection <= -1.0f + CMP_EPSILON) {
- rbAxisA1 = rbA->get_transform().basis.get_axis(2);
- rbAxisA2 = rbA->get_transform().basis.get_axis(1);
+ rbAxisA1 = rbA->get_transform().basis.get_column(2);
+ rbAxisA2 = rbA->get_transform().basis.get_column(1);
} else {
rbAxisA2 = axisInA.cross(rbAxisA1);
rbAxisA1 = rbAxisA2.cross(axisInA);
@@ -171,11 +171,11 @@ bool GodotHingeJoint3D::setup(real_t p_step) {
Vector3 jointAxis0local;
Vector3 jointAxis1local;
- plane_space(m_rbAFrame.basis.get_axis(2), jointAxis0local, jointAxis1local);
+ plane_space(m_rbAFrame.basis.get_column(2), jointAxis0local, jointAxis1local);
Vector3 jointAxis0 = A->get_transform().basis.xform(jointAxis0local);
Vector3 jointAxis1 = A->get_transform().basis.xform(jointAxis1local);
- Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
+ Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(2));
memnew_placement(
&m_jacAng[0],
@@ -226,7 +226,7 @@ bool GodotHingeJoint3D::setup(real_t p_step) {
}
//Compute K = J*W*J' for hinge axis
- Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
+ Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(2));
m_kHinge = 1.0f / (A->compute_angular_impulse_denominator(axisA) + B->compute_angular_impulse_denominator(axisA));
return true;
@@ -271,8 +271,8 @@ void GodotHingeJoint3D::solve(real_t p_step) {
///solve angular part
// get axes in world space
- Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
- Vector3 axisB = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(2));
+ Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(2));
+ Vector3 axisB = B->get_transform().basis.xform(m_rbBFrame.basis.get_column(2));
const Vector3 &angVelA = A->get_angular_velocity();
const Vector3 &angVelB = B->get_angular_velocity();
@@ -384,9 +384,9 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) {
}
real_t GodotHingeJoint3D::get_hinge_angle() {
- const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(0));
- const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(1));
- const Vector3 swingAxis = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(1));
+ const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(0));
+ const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(1));
+ const Vector3 swingAxis = B->get_transform().basis.xform(m_rbBFrame.basis.get_column(1));
return atan2fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
}
diff --git a/servers/physics_3d/joints/godot_slider_joint_3d.cpp b/servers/physics_3d/joints/godot_slider_joint_3d.cpp
index f175421304..4539be21e3 100644
--- a/servers/physics_3d/joints/godot_slider_joint_3d.cpp
+++ b/servers/physics_3d/joints/godot_slider_joint_3d.cpp
@@ -102,7 +102,7 @@ bool GodotSliderJoint3D::setup(real_t p_step) {
m_calculatedTransformB = B->get_transform() * m_frameInB;
m_realPivotAInW = m_calculatedTransformA.origin;
m_realPivotBInW = m_calculatedTransformB.origin;
- m_sliderAxis = m_calculatedTransformA.basis.get_axis(0); // along X
+ m_sliderAxis = m_calculatedTransformA.basis.get_column(0); // along X
m_delta = m_realPivotBInW - m_realPivotAInW;
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
m_relPosA = m_projPivotInW - A->get_transform().origin;
@@ -111,7 +111,7 @@ bool GodotSliderJoint3D::setup(real_t p_step) {
int i;
//linear part
for (i = 0; i < 3; i++) {
- normalWorld = m_calculatedTransformA.basis.get_axis(i);
+ normalWorld = m_calculatedTransformA.basis.get_column(i);
memnew_placement(
&m_jacLin[i],
GodotJacobianEntry3D(
@@ -130,7 +130,7 @@ bool GodotSliderJoint3D::setup(real_t p_step) {
testLinLimits();
// angular part
for (i = 0; i < 3; i++) {
- normalWorld = m_calculatedTransformA.basis.get_axis(i);
+ normalWorld = m_calculatedTransformA.basis.get_column(i);
memnew_placement(
&m_jacAng[i],
GodotJacobianEntry3D(
@@ -141,7 +141,7 @@ bool GodotSliderJoint3D::setup(real_t p_step) {
B->get_inv_inertia()));
}
testAngLimits();
- Vector3 axisA = m_calculatedTransformA.basis.get_axis(0);
+ Vector3 axisA = m_calculatedTransformA.basis.get_column(0);
m_kAngle = real_t(1.0) / (A->compute_angular_impulse_denominator(axisA) + B->compute_angular_impulse_denominator(axisA));
// clear accumulator for motors
m_accumulatedLinMotorImpulse = real_t(0.0);
@@ -206,8 +206,8 @@ void GodotSliderJoint3D::solve(real_t p_step) {
}
// angular
// get axes in world space
- Vector3 axisA = m_calculatedTransformA.basis.get_axis(0);
- Vector3 axisB = m_calculatedTransformB.basis.get_axis(0);
+ Vector3 axisA = m_calculatedTransformA.basis.get_column(0);
+ Vector3 axisB = m_calculatedTransformB.basis.get_column(0);
const Vector3 &angVelA = A->get_angular_velocity();
const Vector3 &angVelB = B->get_angular_velocity();
@@ -297,14 +297,14 @@ void GodotSliderJoint3D::calculateTransforms() {
m_calculatedTransformB = B->get_transform() * m_frameInB;
m_realPivotAInW = m_calculatedTransformA.origin;
m_realPivotBInW = m_calculatedTransformB.origin;
- m_sliderAxis = m_calculatedTransformA.basis.get_axis(0); // along X
+ m_sliderAxis = m_calculatedTransformA.basis.get_column(0); // along X
m_delta = m_realPivotBInW - m_realPivotAInW;
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
Vector3 normalWorld;
int i;
//linear part
for (i = 0; i < 3; i++) {
- normalWorld = m_calculatedTransformA.basis.get_axis(i);
+ normalWorld = m_calculatedTransformA.basis.get_column(i);
m_depth[i] = m_delta.dot(normalWorld);
}
}
@@ -335,9 +335,9 @@ void GodotSliderJoint3D::testAngLimits() {
m_angDepth = real_t(0.);
m_solveAngLim = false;
if (m_lowerAngLimit <= m_upperAngLimit) {
- const Vector3 axisA0 = m_calculatedTransformA.basis.get_axis(1);
- const Vector3 axisA1 = m_calculatedTransformA.basis.get_axis(2);
- const Vector3 axisB0 = m_calculatedTransformB.basis.get_axis(1);
+ const Vector3 axisA0 = m_calculatedTransformA.basis.get_column(1);
+ const Vector3 axisA1 = m_calculatedTransformA.basis.get_column(2);
+ const Vector3 axisB0 = m_calculatedTransformB.basis.get_column(1);
real_t rot = atan2fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
if (rot < m_lowerAngLimit) {
m_angDepth = rot - m_lowerAngLimit;
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 45816e3244..41aae36785 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -158,8 +158,8 @@ Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const {
Vector<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
- ret.write[idx++] = E->get();
+ for (const RID &E : parameters.exclude) {
+ ret.write[idx++] = E;
}
return ret;
}
@@ -208,8 +208,8 @@ Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const {
Vector<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
- ret.write[idx++] = E->get();
+ for (const RID &E : parameters.exclude) {
+ ret.write[idx++] = E;
}
return ret;
}
@@ -243,7 +243,7 @@ void PhysicsPointQueryParameters2D::_bind_methods() {
///////////////////////////////////////////////////////
-void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) {
+void PhysicsShapeQueryParameters2D::set_shape(const Ref<Resource> &p_shape_ref) {
ERR_FAIL_COND(p_shape_ref.is_null());
shape_ref = p_shape_ref;
parameters.shape_rid = p_shape_ref->get_rid();
@@ -251,7 +251,7 @@ void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) {
void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) {
if (parameters.shape_rid != p_shape) {
- shape_ref = RES();
+ shape_ref = Ref<Resource>();
parameters.shape_rid = p_shape;
}
}
@@ -267,8 +267,8 @@ Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const {
Vector<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
- ret.write[idx++] = E->get();
+ for (const RID &E : parameters.exclude) {
+ ret.write[idx++] = E;
}
return ret;
}
@@ -505,12 +505,16 @@ void PhysicsTestMotionParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters2D::get_exclude_objects);
ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_objects);
+ ClassDB::bind_method(D_METHOD("is_recovery_as_collision_enabled"), &PhysicsTestMotionParameters2D::is_recovery_as_collision_enabled);
+ ClassDB::bind_method(D_METHOD("set_recovery_as_collision_enabled", "enabled"), &PhysicsTestMotionParameters2D::set_recovery_as_collision_enabled);
+
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "recovery_as_collision"), "set_recovery_as_collision_enabled", "is_recovery_as_collision_enabled");
}
///////////////////////////////
@@ -857,7 +861,7 @@ PhysicsServer2D::~PhysicsServer2D() {
Vector<PhysicsServer2DManager::ClassInfo> PhysicsServer2DManager::physics_2d_servers;
int PhysicsServer2DManager::default_server_id = -1;
int PhysicsServer2DManager::default_server_priority = -1;
-const String PhysicsServer2DManager::setting_property_name("physics/2d/physics_engine");
+const String PhysicsServer2DManager::setting_property_name(PNAME("physics/2d/physics_engine"));
void PhysicsServer2DManager::on_servers_changed() {
String physics_servers("DEFAULT");
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index e9faf0a3bf..7a821c64e6 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -127,7 +127,7 @@ public:
struct RayParameters {
Vector2 from;
Vector2 to;
- Set<RID> exclude;
+ HashSet<RID> exclude;
uint32_t collision_mask = UINT32_MAX;
bool collide_with_bodies = true;
@@ -157,7 +157,7 @@ public:
struct PointParameters {
Vector2 position;
ObjectID canvas_instance_id;
- Set<RID> exclude;
+ HashSet<RID> exclude;
uint32_t collision_mask = UINT32_MAX;
bool collide_with_bodies = true;
@@ -173,7 +173,7 @@ public:
Transform2D transform;
Vector2 motion;
real_t margin = 0.0;
- Set<RID> exclude;
+ HashSet<RID> exclude;
uint32_t collision_mask = UINT32_MAX;
bool collide_with_bodies = true;
@@ -483,8 +483,9 @@ public:
Vector2 motion;
real_t margin = 0.08;
bool collide_separation_ray = false;
- Set<RID> exclude_bodies;
- Set<ObjectID> exclude_objects;
+ HashSet<RID> exclude_bodies;
+ HashSet<ObjectID> exclude_objects;
+ bool recovery_as_collision = false;
MotionParameters() {}
@@ -663,7 +664,7 @@ class PhysicsShapeQueryParameters2D : public RefCounted {
PhysicsDirectSpaceState2D::ShapeParameters parameters;
- RES shape_ref;
+ Ref<Resource> shape_ref;
protected:
static void _bind_methods();
@@ -671,8 +672,8 @@ protected:
public:
const PhysicsDirectSpaceState2D::ShapeParameters &get_parameters() const { return parameters; }
- void set_shape(const RES &p_shape_ref);
- RES get_shape() const { return shape_ref; }
+ void set_shape(const Ref<Resource> &p_shape_ref);
+ Ref<Resource> get_shape() const { return shape_ref; }
void set_shape_rid(const RID &p_shape);
RID get_shape_rid() const { return parameters.shape_rid; }
@@ -727,6 +728,9 @@ public:
Array get_exclude_objects() const;
void set_exclude_objects(const Array &p_exclude);
+
+ bool is_recovery_as_collision_enabled() const { return parameters.recovery_as_collision; }
+ void set_recovery_as_collision_enabled(bool p_enabled) { parameters.recovery_as_collision = p_enabled; }
};
class PhysicsTestMotionResult2D : public RefCounted {
diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp
index 02223b83f0..699f515270 100644
--- a/servers/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_server_2d_wrap_mt.cpp
@@ -37,7 +37,7 @@ void PhysicsServer2DWrapMT::thread_exit() {
}
void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
- physics_2d_server->step(p_delta);
+ physics_server_2d->step(p_delta);
step_sem.post();
}
@@ -50,7 +50,7 @@ void PhysicsServer2DWrapMT::_thread_callback(void *_instance) {
void PhysicsServer2DWrapMT::thread_loop() {
server_thread = Thread::get_caller_id();
- physics_2d_server->init();
+ physics_server_2d->init();
exit.clear();
step_thread_up.set();
@@ -61,7 +61,7 @@ void PhysicsServer2DWrapMT::thread_loop() {
command_queue.flush_all(); // flush all
- physics_2d_server->finish();
+ physics_server_2d->finish();
}
/* EVENT QUEUING */
@@ -71,7 +71,7 @@ void PhysicsServer2DWrapMT::step(real_t p_step) {
command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step);
} else {
command_queue.flush_all(); //flush all pending from other threads
- physics_2d_server->step(p_step);
+ physics_server_2d->step(p_step);
}
}
@@ -83,15 +83,15 @@ void PhysicsServer2DWrapMT::sync() {
step_sem.wait(); //must not wait if a step was not issued
}
}
- physics_2d_server->sync();
+ physics_server_2d->sync();
}
void PhysicsServer2DWrapMT::flush_queries() {
- physics_2d_server->flush_queries();
+ physics_server_2d->flush_queries();
}
void PhysicsServer2DWrapMT::end_sync() {
- physics_2d_server->end_sync();
+ physics_server_2d->end_sync();
}
void PhysicsServer2DWrapMT::init() {
@@ -102,7 +102,7 @@ void PhysicsServer2DWrapMT::init() {
OS::get_singleton()->delay_usec(1000);
}
} else {
- physics_2d_server->init();
+ physics_server_2d->init();
}
}
@@ -111,13 +111,13 @@ void PhysicsServer2DWrapMT::finish() {
command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
thread.wait_to_finish();
} else {
- physics_2d_server->finish();
+ physics_server_2d->finish();
}
}
PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) :
command_queue(p_create_thread) {
- physics_2d_server = p_contained;
+ physics_server_2d = p_contained;
create_thread = p_create_thread;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
@@ -132,6 +132,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
}
PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {
- memdelete(physics_2d_server);
+ memdelete(physics_server_2d);
//finish();
}
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index aa3a8bc04a..ddb071f603 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -44,7 +44,7 @@
#endif
class PhysicsServer2DWrapMT : public PhysicsServer2D {
- mutable PhysicsServer2D *physics_2d_server;
+ mutable PhysicsServer2D *physics_server_2d;
mutable CommandQueueMT command_queue;
@@ -71,7 +71,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
public:
#define ServerName PhysicsServer2D
#define ServerNameWrapMT PhysicsServer2DWrapMT
-#define server_name physics_2d_server
+#define server_name physics_server_2d
#define WRITE_ACTION
#include "servers/server_wrap_mt_common.h"
@@ -96,7 +96,7 @@ public:
//these work well, but should be used from the main thread only
bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
+ return physics_server_2d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
}
/* SPACE API */
@@ -111,18 +111,18 @@ public:
// this function only works on physics process, errors and returns null otherwise
PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
- return physics_2d_server->space_get_direct_state(p_space);
+ return physics_server_2d->space_get_direct_state(p_space);
}
FUNC2(space_set_debug_contacts, RID, int);
virtual Vector<Vector2> space_get_contacts(RID p_space) const override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>());
- return physics_2d_server->space_get_contacts(p_space);
+ return physics_server_2d->space_get_contacts(p_space);
}
virtual int space_get_contact_count(RID p_space) const override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
- return physics_2d_server->space_get_contact_count(p_space);
+ return physics_server_2d->space_get_contact_count(p_space);
}
/* AREA API */
@@ -250,20 +250,20 @@ public:
FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
- return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
+ return physics_server_2d->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
}
FUNC2(body_set_pickable, RID, bool);
bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_parameters, r_result);
+ return physics_server_2d->body_test_motion(p_body, p_parameters, r_result);
}
// this function only works on physics process, errors and returns null otherwise
PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
- return physics_2d_server->body_get_direct_state(p_body);
+ return physics_server_2d->body_get_direct_state(p_body);
}
/* JOINT API */
@@ -309,11 +309,11 @@ public:
virtual void finish() override;
virtual bool is_flushing_queries() const override {
- return physics_2d_server->is_flushing_queries();
+ return physics_server_2d->is_flushing_queries();
}
int get_process_info(ProcessInfo p_info) override {
- return physics_2d_server->get_process_info(p_info);
+ return physics_server_2d->get_process_info(p_info);
}
PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread);
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index fc119e49e9..a606d055f7 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -33,6 +33,22 @@
#include "core/config/project_settings.h"
#include "core/string/print_string.h"
+void PhysicsServer3DRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) {
+ GDVIRTUAL_REQUIRED_CALL(_set_vertex, p_vertex_id, p_vector3);
+}
+void PhysicsServer3DRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) {
+ GDVIRTUAL_REQUIRED_CALL(_set_normal, p_vertex_id, p_vector3);
+}
+void PhysicsServer3DRenderingServerHandler::set_aabb(const AABB &p_aabb) {
+ GDVIRTUAL_REQUIRED_CALL(_set_aabb, p_aabb);
+}
+
+void PhysicsServer3DRenderingServerHandler::_bind_methods() {
+ GDVIRTUAL_BIND(_set_vertex, "vertex_id", "vertices");
+ GDVIRTUAL_BIND(_set_normal, "vertex_id", "normals");
+ GDVIRTUAL_BIND(_set_aabb, "aabb");
+}
+
PhysicsServer3D *PhysicsServer3D::singleton = nullptr;
void PhysicsDirectBodyState3D::integrate_forces() {
@@ -161,8 +177,8 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const {
Vector<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
- ret.write[idx++] = E->get();
+ for (const RID &E : parameters.exclude) {
+ ret.write[idx++] = E;
}
return ret;
}
@@ -215,8 +231,8 @@ Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const {
Vector<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
- ret.write[idx++] = E->get();
+ for (const RID &E : parameters.exclude) {
+ ret.write[idx++] = E;
}
return ret;
}
@@ -246,7 +262,7 @@ void PhysicsPointQueryParameters3D::_bind_methods() {
///////////////////////////////////////////////////////
-void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) {
+void PhysicsShapeQueryParameters3D::set_shape(const Ref<Resource> &p_shape_ref) {
ERR_FAIL_COND(p_shape_ref.is_null());
shape_ref = p_shape_ref;
parameters.shape_rid = p_shape_ref->get_rid();
@@ -254,7 +270,7 @@ void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) {
void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) {
if (parameters.shape_rid != p_shape) {
- shape_ref = RES();
+ shape_ref = Ref<Resource>();
parameters.shape_rid = p_shape;
}
}
@@ -270,8 +286,8 @@ Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const {
Vector<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
- ret.write[idx++] = E->get();
+ for (const RID &E : parameters.exclude) {
+ ret.write[idx++] = E;
}
return ret;
}
@@ -511,6 +527,9 @@ void PhysicsTestMotionParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters3D::get_exclude_objects);
ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_objects);
+ ClassDB::bind_method(D_METHOD("is_recovery_as_collision_enabled"), &PhysicsTestMotionParameters3D::is_recovery_as_collision_enabled);
+ ClassDB::bind_method(D_METHOD("set_recovery_as_collision_enabled", "enabled"), &PhysicsTestMotionParameters3D::set_recovery_as_collision_enabled);
+
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
@@ -518,6 +537,7 @@ void PhysicsTestMotionParameters3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "recovery_as_collision"), "set_recovery_as_collision_enabled", "is_recovery_as_collision_enabled");
}
///////////////////////////////
@@ -1013,7 +1033,7 @@ PhysicsServer3D::~PhysicsServer3D() {
Vector<PhysicsServer3DManager::ClassInfo> PhysicsServer3DManager::physics_servers;
int PhysicsServer3DManager::default_server_id = -1;
int PhysicsServer3DManager::default_server_priority = -1;
-const String PhysicsServer3DManager::setting_property_name("physics/3d/physics_engine");
+const String PhysicsServer3DManager::setting_property_name(PNAME("physics/3d/physics_engine"));
void PhysicsServer3DManager::on_servers_changed() {
String physics_servers2("DEFAULT");
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index f830c95b58..86a41d96ef 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -33,6 +33,9 @@
#include "core/io/resource.h"
#include "core/object/class_db.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
class PhysicsDirectSpaceState3D;
@@ -130,7 +133,7 @@ public:
struct RayParameters {
Vector3 from;
Vector3 to;
- Set<RID> exclude;
+ HashSet<RID> exclude;
uint32_t collision_mask = UINT32_MAX;
bool collide_with_bodies = true;
@@ -162,7 +165,7 @@ public:
struct PointParameters {
Vector3 position;
- Set<RID> exclude;
+ HashSet<RID> exclude;
uint32_t collision_mask = UINT32_MAX;
bool collide_with_bodies = true;
@@ -176,7 +179,7 @@ public:
Transform3D transform;
Vector3 motion;
real_t margin = 0.0;
- Set<RID> exclude;
+ HashSet<RID> exclude;
uint32_t collision_mask = UINT32_MAX;
bool collide_with_bodies = true;
@@ -202,13 +205,21 @@ public:
PhysicsDirectSpaceState3D();
};
-class RenderingServerHandler {
+class PhysicsServer3DRenderingServerHandler : public Object {
+ GDCLASS(PhysicsServer3DRenderingServerHandler, Object)
+protected:
+ GDVIRTUAL2(_set_vertex, int, GDNativeConstPtr<void>)
+ GDVIRTUAL2(_set_normal, int, GDNativeConstPtr<void>)
+ GDVIRTUAL1(_set_aabb, const AABB &)
+
+ static void _bind_methods();
+
public:
- virtual void set_vertex(int p_vertex_id, const void *p_vector3) = 0;
- virtual void set_normal(int p_vertex_id, const void *p_vector3) = 0;
- virtual void set_aabb(const AABB &p_aabb) = 0;
+ virtual void set_vertex(int p_vertex_id, const void *p_vector3);
+ virtual void set_normal(int p_vertex_id, const void *p_vector3);
+ virtual void set_aabb(const AABB &p_aabb);
- virtual ~RenderingServerHandler() {}
+ virtual ~PhysicsServer3DRenderingServerHandler() {}
};
class PhysicsTestMotionParameters3D;
@@ -509,8 +520,9 @@ public:
real_t margin = 0.001;
int max_collisions = 1;
bool collide_separation_ray = false;
- Set<RID> exclude_bodies;
- Set<ObjectID> exclude_objects;
+ HashSet<RID> exclude_bodies;
+ HashSet<ObjectID> exclude_objects;
+ bool recovery_as_collision = false;
MotionParameters() {}
@@ -552,7 +564,7 @@ public:
virtual RID soft_body_create() = 0;
- virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) = 0;
+ virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) = 0;
virtual void soft_body_set_space(RID p_body, RID p_space) = 0;
virtual RID soft_body_get_space(RID p_body) const = 0;
@@ -624,7 +636,7 @@ public:
virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0;
virtual int joint_get_solver_priority(RID p_joint) const = 0;
- virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0;
+ virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) = 0;
virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0;
virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0;
@@ -863,7 +875,7 @@ class PhysicsShapeQueryParameters3D : public RefCounted {
PhysicsDirectSpaceState3D::ShapeParameters parameters;
- RES shape_ref;
+ Ref<Resource> shape_ref;
protected:
static void _bind_methods();
@@ -871,8 +883,8 @@ protected:
public:
const PhysicsDirectSpaceState3D::ShapeParameters &get_parameters() const { return parameters; }
- void set_shape(const RES &p_shape_ref);
- RES get_shape() const { return shape_ref; }
+ void set_shape(const Ref<Resource> &p_shape_ref);
+ Ref<Resource> get_shape() const { return shape_ref; }
void set_shape_rid(const RID &p_shape);
RID get_shape_rid() const { return parameters.shape_rid; }
@@ -930,6 +942,9 @@ public:
Array get_exclude_objects() const;
void set_exclude_objects(const Array &p_exclude);
+
+ bool is_recovery_as_collision_enabled() const { return parameters.recovery_as_collision; }
+ void set_recovery_as_collision_enabled(bool p_enabled) { parameters.recovery_as_collision = p_enabled; }
};
class PhysicsTestMotionResult3D : public RefCounted {
diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp
index 822ca44b72..7faa193ec2 100644
--- a/servers/physics_server_3d_wrap_mt.cpp
+++ b/servers/physics_server_3d_wrap_mt.cpp
@@ -37,7 +37,7 @@ void PhysicsServer3DWrapMT::thread_exit() {
}
void PhysicsServer3DWrapMT::thread_step(real_t p_delta) {
- physics_3d_server->step(p_delta);
+ physics_server_3d->step(p_delta);
step_sem.post();
}
@@ -50,7 +50,7 @@ void PhysicsServer3DWrapMT::_thread_callback(void *_instance) {
void PhysicsServer3DWrapMT::thread_loop() {
server_thread = Thread::get_caller_id();
- physics_3d_server->init();
+ physics_server_3d->init();
exit = false;
step_thread_up = true;
@@ -61,7 +61,7 @@ void PhysicsServer3DWrapMT::thread_loop() {
command_queue.flush_all(); // flush all
- physics_3d_server->finish();
+ physics_server_3d->finish();
}
/* EVENT QUEUING */
@@ -71,7 +71,7 @@ void PhysicsServer3DWrapMT::step(real_t p_step) {
command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
} else {
command_queue.flush_all(); //flush all pending from other threads
- physics_3d_server->step(p_step);
+ physics_server_3d->step(p_step);
}
}
@@ -83,15 +83,15 @@ void PhysicsServer3DWrapMT::sync() {
step_sem.wait(); //must not wait if a step was not issued
}
}
- physics_3d_server->sync();
+ physics_server_3d->sync();
}
void PhysicsServer3DWrapMT::flush_queries() {
- physics_3d_server->flush_queries();
+ physics_server_3d->flush_queries();
}
void PhysicsServer3DWrapMT::end_sync() {
- physics_3d_server->end_sync();
+ physics_server_3d->end_sync();
}
void PhysicsServer3DWrapMT::init() {
@@ -102,7 +102,7 @@ void PhysicsServer3DWrapMT::init() {
OS::get_singleton()->delay_usec(1000);
}
} else {
- physics_3d_server->init();
+ physics_server_3d->init();
}
}
@@ -111,13 +111,13 @@ void PhysicsServer3DWrapMT::finish() {
command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
thread.wait_to_finish();
} else {
- physics_3d_server->finish();
+ physics_server_3d->finish();
}
}
PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) :
command_queue(p_create_thread) {
- physics_3d_server = p_contained;
+ physics_server_3d = p_contained;
create_thread = p_create_thread;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
@@ -132,6 +132,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool
}
PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
- memdelete(physics_3d_server);
+ memdelete(physics_server_3d);
//finish();
}
diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index ecaef886e1..d4a4ad3132 100644
--- a/servers/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -43,7 +43,7 @@
#endif
class PhysicsServer3DWrapMT : public PhysicsServer3D {
- mutable PhysicsServer3D *physics_3d_server;
+ mutable PhysicsServer3D *physics_server_3d;
mutable CommandQueueMT command_queue;
@@ -70,7 +70,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D {
public:
#define ServerName PhysicsServer3D
#define ServerNameWrapMT PhysicsServer3DWrapMT
-#define server_name physics_3d_server
+#define server_name physics_server_3d
#define WRITE_ACTION
#include "servers/server_wrap_mt_common.h"
@@ -100,7 +100,7 @@ public:
//these work well, but should be used from the main thread only
bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
+ return physics_server_3d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
}
#endif
/* SPACE API */
@@ -115,18 +115,18 @@ public:
// this function only works on physics process, errors and returns null otherwise
PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
- return physics_3d_server->space_get_direct_state(p_space);
+ return physics_server_3d->space_get_direct_state(p_space);
}
FUNC2(space_set_debug_contacts, RID, int);
virtual Vector<Vector3> space_get_contacts(RID p_space) const override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>());
- return physics_3d_server->space_get_contacts(p_space);
+ return physics_server_3d->space_get_contacts(p_space);
}
virtual int space_get_contact_count(RID p_space) const override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
- return physics_3d_server->space_get_contact_count(p_space);
+ return physics_server_3d->space_get_contact_count(p_space);
}
/* AREA API */
@@ -256,20 +256,20 @@ public:
bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_motion(p_body, p_parameters, r_result);
+ return physics_server_3d->body_test_motion(p_body, p_parameters, r_result);
}
// this function only works on physics process, errors and returns null otherwise
PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
- return physics_3d_server->body_get_direct_state(p_body);
+ return physics_server_3d->body_get_direct_state(p_body);
}
/* SOFT BODY API */
FUNCRID(soft_body)
- FUNC2(soft_body_update_rendering_server, RID, class RenderingServerHandler *)
+ FUNC2(soft_body_update_rendering_server, RID, PhysicsServer3DRenderingServerHandler *)
FUNC2(soft_body_set_space, RID, RID)
FUNC1RC(RID, soft_body_get_space, RID)
@@ -369,7 +369,7 @@ public:
FUNC2(joint_set_solver_priority, RID, int);
FUNC1RC(int, joint_get_solver_priority, RID);
- FUNC2(joint_disable_collisions_between_bodies, RID, const bool);
+ FUNC2(joint_disable_collisions_between_bodies, RID, bool);
FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID);
/* MISC */
@@ -385,11 +385,11 @@ public:
virtual void finish() override;
virtual bool is_flushing_queries() const override {
- return physics_3d_server->is_flushing_queries();
+ return physics_server_3d->is_flushing_queries();
}
int get_process_info(ProcessInfo p_info) override {
- return physics_3d_server->get_process_info(p_info);
+ return physics_server_3d->get_process_info(p_info);
}
PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread);
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index f405dea770..8bbe987cb7 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -55,7 +55,6 @@
#include "audio_server.h"
#include "camera/camera_feed.h"
#include "camera_server.h"
-#include "core/extension/native_extension_manager.h"
#include "debugger/servers_debugger.h"
#include "display_server.h"
#include "navigation_server_2d.h"
@@ -70,7 +69,9 @@
#include "rendering/rendering_device.h"
#include "rendering/rendering_device_binds.h"
#include "rendering_server.h"
+#include "servers/extensions/physics_server_3d_extension.h"
#include "servers/rendering/shader_types.h"
+#include "text/text_server_dummy.h"
#include "text/text_server_extension.h"
#include "text_server.h"
#include "xr/xr_interface.h"
@@ -83,17 +84,17 @@ ShaderTypes *shader_types = nullptr;
PhysicsServer3D *_createGodotPhysics3DCallback() {
bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread");
- PhysicsServer3D *physics_server = memnew(GodotPhysicsServer3D(using_threads));
+ PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads));
- return memnew(PhysicsServer3DWrapMT(physics_server, using_threads));
+ return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads));
}
PhysicsServer2D *_createGodotPhysics2DCallback() {
bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread");
- PhysicsServer2D *physics_server = memnew(GodotPhysicsServer2D(using_threads));
+ PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads));
- return memnew(PhysicsServer2DWrapMT(physics_server, using_threads));
+ return memnew(PhysicsServer2DWrapMT(physics_server_2d, using_threads));
}
static bool has_server_feature_callback(const String &p_feature) {
@@ -106,33 +107,47 @@ static bool has_server_feature_callback(const String &p_feature) {
return false;
}
-void preregister_server_types() {
+void register_server_types() {
shader_types = memnew(ShaderTypes);
GDREGISTER_CLASS(TextServerManager);
- GDREGISTER_VIRTUAL_CLASS(TextServer);
+ GDREGISTER_ABSTRACT_CLASS(TextServer);
GDREGISTER_CLASS(TextServerExtension);
+ GDREGISTER_CLASS(TextServerDummy);
+
+ GDREGISTER_NATIVE_STRUCT(Glyph, "int start = -1;int end = -1;uint8_t count = 0;uint8_t repeat = 1;uint16_t flags = 0;float x_off = 0.f;float y_off = 0.f;float advance = 0.f;RID font_rid;int font_size = 0;int32_t index = 0");
+ GDREGISTER_NATIVE_STRUCT(CaretInfo, "Rect2 leading_caret;Rect2 trailing_caret;TextServer::Direction leading_direction;TextServer::Direction trailing_direction");
Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
-}
-void register_server_types() {
OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback);
- GDREGISTER_VIRTUAL_CLASS(DisplayServer);
- GDREGISTER_VIRTUAL_CLASS(RenderingServer);
+ GDREGISTER_ABSTRACT_CLASS(DisplayServer);
+ GDREGISTER_ABSTRACT_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer3D);
- GDREGISTER_VIRTUAL_CLASS(NavigationServer2D);
- GDREGISTER_VIRTUAL_CLASS(NavigationServer3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3DExtension)
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DRenderingServerHandler)
+
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionRayResult, "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state)");
+
+ GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
+ GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);
GDREGISTER_CLASS(XRServer);
GDREGISTER_CLASS(CameraServer);
- GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
+ GDREGISTER_ABSTRACT_CLASS(RenderingDevice);
- GDREGISTER_VIRTUAL_CLASS(XRInterface);
+ GDREGISTER_ABSTRACT_CLASS(XRInterface);
GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
GDREGISTER_CLASS(XRPose);
GDREGISTER_CLASS(XRPositionalTracker);
@@ -149,7 +164,7 @@ void register_server_types() {
GDREGISTER_CLASS(AudioBusLayout);
GDREGISTER_CLASS(AudioStreamGenerator);
- GDREGISTER_VIRTUAL_CLASS(AudioStreamGeneratorPlayback);
+ GDREGISTER_ABSTRACT_CLASS(AudioStreamGeneratorPlayback);
{
//audio effects
@@ -183,12 +198,12 @@ void register_server_types() {
GDREGISTER_CLASS(AudioEffectRecord);
GDREGISTER_CLASS(AudioEffectSpectrumAnalyzer);
- GDREGISTER_VIRTUAL_CLASS(AudioEffectSpectrumAnalyzerInstance);
+ GDREGISTER_ABSTRACT_CLASS(AudioEffectSpectrumAnalyzerInstance);
GDREGISTER_CLASS(AudioEffectCapture);
}
- GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
+ GDREGISTER_ABSTRACT_CLASS(RenderingDevice);
GDREGISTER_CLASS(RDTextureFormat);
GDREGISTER_CLASS(RDTextureView);
GDREGISTER_CLASS(RDAttachmentFormat);
@@ -208,16 +223,16 @@ void register_server_types() {
GDREGISTER_CLASS(CameraFeed);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectBodyState2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectSpaceState2D);
GDREGISTER_CLASS(PhysicsRayQueryParameters2D);
GDREGISTER_CLASS(PhysicsPointQueryParameters2D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionResult2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectBodyState3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectSpaceState3D);
GDREGISTER_CLASS(PhysicsRayQueryParameters3D);
GDREGISTER_CLASS(PhysicsPointQueryParameters3D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
@@ -239,15 +254,10 @@ void register_server_types() {
PhysicsServer3DManager::register_server("GodotPhysics3D", &_createGodotPhysics3DCallback);
PhysicsServer3DManager::set_default_server("GodotPhysics3D");
-
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
}
void unregister_server_types() {
ServersDebugger::deinitialize();
-
- NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
-
memdelete(shader_types);
}
diff --git a/servers/register_server_types.h b/servers/register_server_types.h
index cf6364eee3..32fd944bea 100644
--- a/servers/register_server_types.h
+++ b/servers/register_server_types.h
@@ -31,7 +31,6 @@
#ifndef REGISTER_SERVER_TYPES_H
#define REGISTER_SERVER_TYPES_H
-void preregister_server_types();
void register_server_types();
void unregister_server_types();
diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub
index 0939b68482..06d1d28b08 100644
--- a/servers/rendering/SCsub
+++ b/servers/rendering/SCsub
@@ -5,3 +5,4 @@ Import("env")
env.add_source_files(env.servers_sources, "*.cpp")
SConscript("renderer_rd/SCsub")
+SConscript("storage/SCsub")
diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h
new file mode 100644
index 0000000000..194b5b5cfe
--- /dev/null
+++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h
@@ -0,0 +1,63 @@
+/*************************************************************************/
+/* rasterizer_canvas_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RASTERIZER_CANVAS_DUMMY_H
+#define RASTERIZER_CANVAS_DUMMY_H
+
+#include "servers/rendering/renderer_canvas_render.h"
+
+class RasterizerCanvasDummy : public RendererCanvasRender {
+public:
+ 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>()) override { return 0; }
+ void free_polygon(PolygonID p_polygon) override {}
+
+ 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) override {}
+ void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
+
+ RID light_create() override { return RID(); }
+ void light_set_texture(RID p_rid, RID p_texture) override {}
+ void light_set_use_shadow(RID p_rid, bool p_enable) override {}
+ 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) override {}
+ 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) override {}
+
+ void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
+ RID occluder_polygon_create() override { return RID(); }
+ void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {}
+ void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
+ void set_shadow_texture_size(int p_size) override {}
+
+ bool free(RID p_rid) override { return true; }
+ void update() override {}
+
+ RasterizerCanvasDummy() {}
+ ~RasterizerCanvasDummy() {}
+};
+
+#endif // !RASTERIZER_CANVAS_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
new file mode 100644
index 0000000000..5c6fcc8386
--- /dev/null
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* rasterizer_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RASTERIZER_DUMMY_H
+#define RASTERIZER_DUMMY_H
+
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "scene/resources/mesh.h"
+#include "servers/rendering/dummy/rasterizer_canvas_dummy.h"
+#include "servers/rendering/dummy/rasterizer_scene_dummy.h"
+#include "servers/rendering/dummy/rasterizer_storage_dummy.h"
+#include "servers/rendering/dummy/storage/light_storage.h"
+#include "servers/rendering/dummy/storage/material_storage.h"
+#include "servers/rendering/dummy/storage/mesh_storage.h"
+#include "servers/rendering/dummy/storage/particles_storage.h"
+#include "servers/rendering/dummy/storage/texture_storage.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering_server.h"
+
+class RasterizerDummy : public RendererCompositor {
+private:
+ uint64_t frame = 1;
+ double delta = 0;
+
+protected:
+ RasterizerCanvasDummy canvas;
+ RendererDummy::LightStorage light_storage;
+ RendererDummy::MaterialStorage material_storage;
+ RendererDummy::MeshStorage mesh_storage;
+ RendererDummy::ParticlesStorage particles_storage;
+ RendererDummy::TextureStorage texture_storage;
+ RasterizerStorageDummy storage;
+ RasterizerSceneDummy scene;
+
+public:
+ RendererLightStorage *get_light_storage() override { return &light_storage; };
+ RendererMaterialStorage *get_material_storage() override { return &material_storage; };
+ RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
+ RendererParticlesStorage *get_particles_storage() override { return &particles_storage; };
+ RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
+ RendererStorage *get_storage() override { return &storage; }
+ RendererCanvasRender *get_canvas() override { return &canvas; }
+ RendererSceneRender *get_scene() override { return &scene; }
+
+ void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {}
+
+ void initialize() override {}
+ void begin_frame(double frame_step) override {
+ frame++;
+ delta = frame_step;
+ }
+
+ void prepare_for_blitting_render_targets() override {}
+ void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
+
+ void end_frame(bool p_swap_buffers) override {
+ if (p_swap_buffers) {
+ DisplayServer::get_singleton()->swap_buffers();
+ }
+ }
+
+ void finalize() override {}
+
+ static RendererCompositor *_create_current() {
+ return memnew(RasterizerDummy);
+ }
+
+ static void make_current() {
+ _create_func = _create_current;
+ low_end = true;
+ }
+
+ uint64_t get_frame_number() const override { return frame; }
+ double get_frame_delta_time() const override { return delta; }
+
+ RasterizerDummy() {}
+ ~RasterizerDummy() {}
+};
+
+#endif // RASTERIZER_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
new file mode 100644
index 0000000000..e6d2b93f99
--- /dev/null
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -0,0 +1,217 @@
+/*************************************************************************/
+/* rasterizer_scene_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RASTERIZER_SCENE_DUMMY_H
+#define RASTERIZER_SCENE_DUMMY_H
+
+#include "servers/rendering/renderer_scene_render.h"
+
+class RasterizerSceneDummy : public RendererSceneRender {
+public:
+ GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
+ void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
+ void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
+ void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
+ void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
+ void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
+ void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
+ void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
+ void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
+ void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ 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) override {}
+ void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
+ void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
+ void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
+ void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
+ void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
+
+ uint32_t geometry_instance_get_pair_mask() override { return 0; }
+ void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+ void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
+ void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
+
+ void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
+
+ /* SHADOW ATLAS API */
+
+ RID shadow_atlas_create() override { return RID(); }
+ void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
+ void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
+ bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
+
+ void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {}
+ int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
+ void set_directional_shadow_count(int p_count) override {}
+
+ /* SDFGI UPDATE */
+
+ void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+ int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
+ AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
+ uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
+
+ /* SKY API */
+
+ RID sky_allocate() override { return RID(); }
+ void sky_initialize(RID p_rid) override {}
+ void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
+ void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
+ void sky_set_material(RID p_sky, RID p_material) override {}
+ Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
+
+ /* ENVIRONMENT API */
+
+ RID environment_allocate() override { return RID(); }
+ void environment_initialize(RID p_rid) override {}
+ void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
+ void environment_set_sky(RID p_env, RID p_sky) override {}
+ void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
+ void environment_set_bg_color(RID p_env, const Color &p_color) override {}
+ void environment_set_bg_energy(RID p_env, float p_energy) override {}
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
+ 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) override {}
+
+ 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, float p_glow_map_strength, RID p_glow_map) override {}
+ void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
+ void environment_glow_set_use_high_quality(bool p_enable) override {}
+
+ 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) override {}
+ void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
+ 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) override {}
+ void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
+ void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
+ void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
+
+ void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+
+ void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
+ void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
+ void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
+
+ 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) override {}
+
+ 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) override {}
+
+ 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) override {}
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
+ void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
+ void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
+
+ Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
+
+ bool is_environment(RID p_env) const override { return false; }
+ RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
+ int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
+
+ RID camera_effects_allocate() override { return RID(); }
+ void camera_effects_initialize(RID p_rid) override {}
+ void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
+ void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
+
+ 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) override {}
+ void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
+
+ void shadows_quality_set(RS::ShadowQuality p_quality) override {}
+ void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
+
+ RID light_instance_create(RID p_light) override { return RID(); }
+ void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
+ void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
+ void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &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()) override {}
+ void light_instance_mark_visible(RID p_light_instance) override {}
+
+ RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
+ void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
+ void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {}
+ RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
+ Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
+
+ RID reflection_atlas_create() override { return RID(); }
+ int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
+ void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
+
+ RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
+ void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
+ void reflection_probe_release_atlas_index(RID p_instance) override {}
+ bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
+ bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
+ bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
+ bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
+
+ RID decal_instance_create(RID p_decal) override { return RID(); }
+ void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
+
+ RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
+ void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
+
+ RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
+ void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
+ bool voxel_gi_needs_update(RID p_probe) const override { return false; }
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
+
+ void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
+
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+ void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
+
+ void set_scene_pass(uint64_t p_pass) override {}
+ void set_time(double p_time, double p_step) override {}
+ void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
+
+ RID render_buffers_create() override { return RID(); }
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void gi_set_use_half_resolution(bool p_enable) override {}
+
+ void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
+ bool screen_space_roughness_limiter_is_active() const override { return false; }
+
+ void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
+ void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
+
+ TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
+
+ bool free(RID p_rid) override { return false; }
+ void update() override {}
+ void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
+
+ virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
+
+ RasterizerSceneDummy() {}
+ ~RasterizerSceneDummy() {}
+};
+
+#endif // !RASTERIZER_SCENE_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h
new file mode 100644
index 0000000000..596960786a
--- /dev/null
+++ b/servers/rendering/dummy/rasterizer_storage_dummy.h
@@ -0,0 +1,147 @@
+/*************************************************************************/
+/* rasterizer_storage_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RASTERIZER_STORAGE_DUMMY_H
+#define RASTERIZER_STORAGE_DUMMY_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "storage/texture_storage.h"
+
+class RasterizerStorageDummy : public RendererStorage {
+public:
+ void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
+
+ /* VOXEL GI API */
+
+ RID voxel_gi_allocate() override { return RID(); }
+ void voxel_gi_initialize(RID p_rid) override {}
+ void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &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) override {}
+
+ AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); }
+ Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); }
+ Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+ Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+ Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+
+ Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); }
+ Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); }
+
+ void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; }
+
+ void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; }
+
+ void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
+
+ void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
+
+ void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {}
+ float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; }
+
+ void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {}
+ bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; }
+
+ void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {}
+ bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
+
+ void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {}
+ float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; }
+
+ uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; }
+
+ /* OCCLUDER */
+
+ void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
+
+ /* FOG VOLUMES */
+
+ RID fog_volume_allocate() override { return RID(); }
+ void fog_volume_initialize(RID p_rid) override {}
+
+ void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
+ void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
+ void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
+ AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
+ RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
+
+ /* VISIBILITY NOTIFIER */
+ virtual RID visibility_notifier_allocate() override { return RID(); }
+ virtual void visibility_notifier_initialize(RID p_notifier) override {}
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
+
+ /* STORAGE */
+
+ RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
+ bool free(RID p_rid) override {
+ if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+ RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid);
+ return true;
+ }
+ return false;
+ }
+
+ virtual void update_memory_info() override {}
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
+
+ bool has_os_feature(const String &p_feature) const override {
+ return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
+ }
+
+ void update_dirty_resources() override {}
+
+ void set_debug_generate_wireframes(bool p_generate) override {}
+
+ String get_video_adapter_name() const override { return String(); }
+ String get_video_adapter_vendor() const override { return String(); }
+ RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
+ String get_video_adapter_api_version() const override { return String(); }
+
+ static RendererStorage *base_singleton;
+
+ void capture_timestamps_begin() override {}
+ void capture_timestamp(const String &p_name) override {}
+ uint32_t get_captured_timestamps_count() const override { return 0; }
+ uint64_t get_captured_timestamps_frame() const override { return 0; }
+ uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
+ uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
+ String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
+
+ RasterizerStorageDummy() {}
+ ~RasterizerStorageDummy() {}
+};
+
+#endif // !RASTERIZER_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
new file mode 100644
index 0000000000..b0100a5fe7
--- /dev/null
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -0,0 +1,135 @@
+/*************************************************************************/
+/* light_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIGHT_STORAGE_DUMMY_H
+#define LIGHT_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/light_storage.h"
+
+namespace RendererDummy {
+
+class LightStorage : public RendererLightStorage {
+public:
+ /* Light API */
+
+ virtual RID directional_light_allocate() override { return RID(); }
+ virtual void directional_light_initialize(RID p_rid) override {}
+ virtual RID omni_light_allocate() override { return RID(); }
+ virtual void omni_light_initialize(RID p_rid) override {}
+ virtual RID spot_light_allocate() override { return RID(); }
+ virtual void spot_light_initialize(RID p_rid) override {}
+
+ virtual void light_free(RID p_rid) override {}
+
+ virtual void light_set_color(RID p_light, const Color &p_color) override {}
+ virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
+ virtual void light_set_shadow(RID p_light, bool p_enabled) override {}
+ virtual void light_set_projector(RID p_light, RID p_texture) override {}
+ virtual void light_set_negative(RID p_light, bool p_enable) override {}
+ virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
+ virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
+ virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
+ virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
+ virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
+
+ virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
+
+ virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
+ virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
+ virtual bool light_directional_get_blend_splits(RID p_light) const override { return false; }
+ virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override {}
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; }
+
+ virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
+ virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
+
+ virtual bool light_has_shadow(RID p_light) const override { return false; }
+ virtual bool light_has_projector(RID p_light) const override { return false; }
+
+ virtual RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
+ virtual AABB light_get_aabb(RID p_light) const override { return AABB(); }
+ virtual float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
+ virtual Color light_get_color(RID p_light) override { return Color(); }
+ virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
+ virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
+ virtual uint64_t light_get_version(RID p_light) const override { return 0; }
+
+ /* PROBE API */
+ virtual RID reflection_probe_allocate() override { return RID(); }
+ virtual void reflection_probe_initialize(RID p_rid) override {}
+ virtual void reflection_probe_free(RID p_rid) override {}
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
+ virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
+ virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
+ virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
+
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
+ virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
+
+ /* LIGHTMAP CAPTURE */
+ virtual RID lightmap_allocate() override { return RID(); }
+ virtual void lightmap_initialize(RID p_rid) override {}
+ virtual void lightmap_free(RID p_rid) override {}
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
+ 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) override {}
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
+ virtual bool lightmap_is_interior(RID p_lightmap) const override { return false; }
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) override {}
+ virtual float lightmap_get_probe_capture_update_speed() const override { return 0; }
+};
+
+} // namespace RendererDummy
+
+#endif // !LIGHT_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
new file mode 100644
index 0000000000..8890be8ea9
--- /dev/null
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -0,0 +1,95 @@
+/*************************************************************************/
+/* material_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MATERIAL_STORAGE_DUMMY_H
+#define MATERIAL_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererDummy {
+
+class MaterialStorage : public RendererMaterialStorage {
+public:
+ /* GLOBAL VARIABLE API */
+
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
+ virtual void global_variable_remove(const StringName &p_name) override {}
+ virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
+ virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+
+ virtual void global_variables_load_settings(bool p_load_textures = true) override {}
+ virtual void global_variables_clear() override {}
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
+ virtual void global_variables_instance_free(RID p_instance) override {}
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
+
+ /* SHADER API */
+
+ virtual RID shader_allocate() override { return RID(); }
+ virtual void shader_initialize(RID p_rid) override {}
+ virtual void shader_free(RID p_rid) override{};
+
+ virtual void shader_set_code(RID p_shader, const String &p_code) override {}
+ virtual String shader_get_code(RID p_shader) const override { return ""; }
+ virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
+
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
+ virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+
+ /* MATERIAL API */
+ virtual RID material_allocate() override { return RID(); }
+ virtual void material_initialize(RID p_rid) override {}
+ virtual void material_free(RID p_rid) override{};
+
+ virtual void material_set_render_priority(RID p_material, int priority) override {}
+ virtual void material_set_shader(RID p_shader_material, RID p_shader) override {}
+
+ virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {}
+ virtual Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+ virtual void material_set_next_pass(RID p_material, RID p_next_material) override {}
+
+ virtual bool material_is_animated(RID p_material) override { return false; }
+ virtual bool material_casts_shadows(RID p_material) override { return false; }
+ virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
+ virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {}
+};
+
+} // namespace RendererDummy
+
+#endif // !MATERIAL_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
new file mode 100644
index 0000000000..dfbd265bba
--- /dev/null
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_DUMMY_H
+#define MESH_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace RendererDummy {
+
+class MeshStorage : public RendererMeshStorage {
+public:
+ /* MESH API */
+
+ virtual RID mesh_allocate() override { return RID(); }
+ virtual void mesh_initialize(RID p_rid) override {}
+ virtual void mesh_free(RID p_rid) override {}
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
+
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
+ virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; }
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
+ virtual void mesh_clear(RID p_mesh) override {}
+
+ /* MESH INSTANCE */
+
+ virtual RID mesh_instance_create(RID p_base) override { return RID(); }
+ virtual void mesh_instance_free(RID p_rid) override {}
+
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {}
+ virtual void update_mesh_instances() override {}
+
+ /* MULTIMESH API */
+
+ virtual RID multimesh_allocate() override { return RID(); }
+ virtual void multimesh_initialize(RID p_rid) override {}
+ virtual void multimesh_free(RID p_rid) override {}
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() override { return RID(); }
+ virtual void skeleton_initialize(RID p_rid) override {}
+ virtual void skeleton_free(RID p_rid) override {}
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {}
+};
+
+} // namespace RendererDummy
+
+#endif // !MESH_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
new file mode 100644
index 0000000000..f614b41c4c
--- /dev/null
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* particles_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PARTICLES_STORAGE_DUMMY_H
+#define PARTICLES_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace RendererDummy {
+
+class ParticlesStorage : public RendererParticlesStorage {
+public:
+ /* PARTICLES */
+
+ virtual RID particles_allocate() override { return RID(); }
+ virtual void particles_initialize(RID p_rid) override {}
+ virtual void particles_free(RID p_rid) override {}
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
+ virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {}
+ virtual void particles_set_amount(RID p_particles, int p_amount) override {}
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
+ virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {}
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) override {}
+ virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
+ virtual void particles_set_process_material(RID p_particles, RID p_material) override {}
+ virtual RID particles_get_process_material(RID p_particles) const override { return RID(); }
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) override {}
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
+ virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
+ virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
+
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
+
+ virtual void particles_restart(RID p_particles) override {}
+
+ virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
+
+ virtual void particles_set_draw_passes(RID p_particles, int p_count) override {}
+ virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
+
+ virtual void particles_request_process(RID p_particles) override {}
+ virtual AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
+ virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
+
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
+
+ virtual bool particles_get_emitting(RID p_particles) override { return false; }
+ virtual int particles_get_draw_passes(RID p_particles) const override { return 0; }
+ virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
+
+ virtual void particles_add_collision(RID p_particles, RID p_instance) override {}
+ virtual void particles_remove_collision(RID p_particles, RID p_instance) override {}
+
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
+
+ virtual void update_particles() override {}
+
+ /* PARTICLES COLLISION */
+
+ virtual RID particles_collision_allocate() override { return RID(); }
+ virtual void particles_collision_initialize(RID p_rid) override {}
+ virtual void particles_collision_free(RID p_rid) override {}
+
+ virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
+ virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
+ virtual void particles_collision_height_field_update(RID p_particles_collision) override {}
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
+ virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
+ virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
+ virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
+
+ virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); }
+ virtual void particles_collision_instance_free(RID p_rid) override {}
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+
+ virtual bool particles_is_inactive(RID p_particles) const override { return false; }
+};
+
+} // namespace RendererDummy
+
+#endif // !PARTICLES_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
new file mode 100644
index 0000000000..11d827a6e3
--- /dev/null
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -0,0 +1,173 @@
+/*************************************************************************/
+/* texture_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEXTURE_STORAGE_DUMMY_H
+#define TEXTURE_STORAGE_DUMMY_H
+
+#include "servers/rendering/rendering_server_globals.h"
+#include "servers/rendering/storage/texture_storage.h"
+
+namespace RendererDummy {
+
+class TextureStorage : public RendererTextureStorage {
+private:
+ struct DummyTexture {
+ Ref<Image> image;
+ };
+ mutable RID_PtrOwner<DummyTexture> texture_owner;
+
+public:
+ static TextureStorage *get_singleton() {
+ // Here we cheat until we can retire RasterizerStorageDummy::free()
+
+ return (TextureStorage *)RSG::texture_storage;
+ };
+
+ virtual bool can_create_resources_async() const override { return false; }
+
+ /* Canvas Texture API */
+
+ virtual RID canvas_texture_allocate() override { return RID(); };
+ virtual void canvas_texture_initialize(RID p_rid) override{};
+ virtual void canvas_texture_free(RID p_rid) override{};
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{};
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{};
+
+ virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{};
+ virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{};
+
+ /* Texture API */
+
+ DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
+ bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
+
+ virtual RID texture_allocate() override {
+ DummyTexture *texture = memnew(DummyTexture);
+ ERR_FAIL_COND_V(!texture, RID());
+ return texture_owner.make_rid(texture);
+ };
+
+ virtual void texture_free(RID p_rid) override {
+ // delete the texture
+ DummyTexture *texture = texture_owner.get_or_null(p_rid);
+ texture_owner.free(p_rid);
+ memdelete(texture);
+ };
+
+ virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
+ DummyTexture *t = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!t);
+ t->image = p_image->duplicate();
+ };
+ virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override{};
+ virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{};
+ virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent
+
+ virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{};
+ virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
+ virtual void texture_proxy_update(RID p_proxy, RID p_base) override{};
+
+ //these two APIs can be used together or in combination with the others.
+ virtual void texture_2d_placeholder_initialize(RID p_texture) override{};
+ virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override{};
+ virtual void texture_3d_placeholder_initialize(RID p_texture) override{};
+
+ virtual Ref<Image> texture_2d_get(RID p_texture) const override {
+ DummyTexture *t = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!t, Ref<Image>());
+ return t->image;
+ };
+ virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); };
+ virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); };
+
+ virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); };
+ virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override{};
+
+ virtual void texture_set_path(RID p_texture, const String &p_path) override{};
+ virtual String texture_get_path(RID p_texture) const override { return String(); };
+
+ virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{};
+ virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{};
+ virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{};
+
+ virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override{};
+
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override{};
+
+ virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); };
+
+ /* DECAL API */
+ virtual RID decal_allocate() override { return RID(); }
+ virtual void decal_initialize(RID p_rid) override {}
+ virtual void decal_free(RID p_rid) override{};
+
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {}
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {}
+
+ virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
+
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
+ /* RENDER TARGET */
+
+ virtual RID render_target_create() override { return RID(); }
+ virtual void render_target_free(RID p_rid) override {}
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
+ virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
+ virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override {}
+ virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override {}
+ virtual bool render_target_was_used(RID p_render_target) override { return false; }
+ virtual void render_target_set_as_unused(RID p_render_target) override {}
+
+ virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
+ virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; }
+ virtual Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
+ virtual void render_target_disable_clear_request(RID p_render_target) override {}
+ virtual void render_target_do_clear_request(RID p_render_target) override {}
+
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
+ virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
+};
+
+} // namespace RendererDummy
+
+#endif // !TEXTURE_STORAGE_DUMMY_H
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
deleted file mode 100644
index 74c080660d..0000000000
--- a/servers/rendering/rasterizer_dummy.h
+++ /dev/null
@@ -1,801 +0,0 @@
-/*************************************************************************/
-/* rasterizer_dummy.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef RASTERIZER_DUMMY_H
-#define RASTERIZER_DUMMY_H
-
-#include "core/templates/rid_owner.h"
-#include "core/templates/self_list.h"
-#include "scene/resources/mesh.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering_server.h"
-
-class RasterizerSceneDummy : public RendererSceneRender {
-public:
- GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
- void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
- void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
- void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
- void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
- void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
- void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
- void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- 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) override {}
- void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
- void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
- void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
- void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
- void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
-
- uint32_t geometry_instance_get_pair_mask() override { return 0; }
- void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
- void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
- void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
- void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
-
- void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
-
- /* SHADOW ATLAS API */
-
- RID shadow_atlas_create() override { return RID(); }
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
-
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {}
- int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
- void set_directional_shadow_count(int p_count) override {}
-
- /* SDFGI UPDATE */
-
- void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
- int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
- AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
- uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
-
- /* SKY API */
-
- RID sky_allocate() override { return RID(); }
- void sky_initialize(RID p_rid) override {}
- void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
- void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
- void sky_set_material(RID p_sky, RID p_material) override {}
- Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
-
- /* ENVIRONMENT API */
-
- RID environment_allocate() override { return RID(); }
- void environment_initialize(RID p_rid) override {}
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
- void environment_set_sky(RID p_env, RID p_sky) override {}
- void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
- void environment_set_bg_color(RID p_env, const Color &p_color) override {}
- void environment_set_bg_energy(RID p_env, float p_energy) override {}
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
- 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) override {}
-
- 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, float p_glow_map_strength, RID p_glow_map) override {}
- void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
- void environment_glow_set_use_high_quality(bool p_enable) override {}
-
- 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) override {}
- void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
- 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) override {}
- void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
- void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
-
- void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
-
- void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
- void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
- void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
-
- 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) override {}
-
- 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) override {}
-
- 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) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
- void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
- void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
-
- Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
-
- bool is_environment(RID p_env) const override { return false; }
- RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
- int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
-
- RID camera_effects_allocate() override { return RID(); }
- void camera_effects_initialize(RID p_rid) override {}
- void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
- void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
-
- 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) override {}
- void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
-
- void shadows_quality_set(RS::ShadowQuality p_quality) override {}
- void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
-
- RID light_instance_create(RID p_light) override { return RID(); }
- void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
- void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &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()) override {}
- void light_instance_mark_visible(RID p_light_instance) override {}
-
- RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
- void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
- void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {}
- RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
- Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
-
- RID reflection_atlas_create() override { return RID(); }
- int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
- void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
-
- RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
- void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
- void reflection_probe_release_atlas_index(RID p_instance) override {}
- bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
- bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
- bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
-
- RID decal_instance_create(RID p_decal) override { return RID(); }
- void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
-
- RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
- void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
-
- RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
- void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
- bool voxel_gi_needs_update(RID p_probe) const override { return false; }
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
-
- void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
-
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
-
- void set_scene_pass(uint64_t p_pass) override {}
- void set_time(double p_time, double p_step) override {}
- void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
-
- RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
- void gi_set_use_half_resolution(bool p_enable) override {}
-
- void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
- bool screen_space_roughness_limiter_is_active() const override { return false; }
-
- void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
- void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
-
- TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
-
- bool free(RID p_rid) override { return false; }
- void update() override {}
- void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
-
- virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
- virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
-
- RasterizerSceneDummy() {}
- ~RasterizerSceneDummy() {}
-};
-
-class RasterizerStorageDummy : public RendererStorage {
-public:
- bool can_create_resources_async() const override { return false; }
-
- /* TEXTURE API */
- struct DummyTexture {
- Ref<Image> image;
- };
- mutable RID_PtrOwner<DummyTexture> texture_owner;
-
- RID texture_allocate() override {
- DummyTexture *texture = memnew(DummyTexture);
- ERR_FAIL_COND_V(!texture, RID());
- return texture_owner.make_rid(texture);
- }
- void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
- DummyTexture *t = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!t);
- t->image = p_image->duplicate();
- }
-
- void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
- void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
- void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
- void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
- void texture_proxy_initialize(RID p_texture, RID p_base) override {}
- void texture_proxy_update(RID p_proxy, RID p_base) override {}
-
- void texture_2d_placeholder_initialize(RID p_texture) override {}
- void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {}
- void texture_3d_placeholder_initialize(RID p_texture) override {}
-
- Ref<Image> texture_2d_get(RID p_texture) const override {
- DummyTexture *t = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!t, Ref<Image>());
- return t->image;
- }
-
- Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
- Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
-
- void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); }
- void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
-
- void texture_set_path(RID p_texture, const String &p_path) override {}
- String texture_get_path(RID p_texture) const override { return String(); }
-
- void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
- void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
- void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {}
-
- void texture_debug_usage(List<RS::TextureInfo> *r_info) override {}
- void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {}
- Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }
-
- void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
- void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-
- /* CANVAS TEXTURE API */
-
- RID canvas_texture_allocate() override { return RID(); }
- void canvas_texture_initialize(RID p_rid) override {}
- void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {}
- void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {}
-
- void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {}
- void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {}
-
- /* SHADER API */
-
- RID shader_allocate() override { return RID(); }
- void shader_initialize(RID p_rid) override {}
- void shader_set_code(RID p_shader, const String &p_code) override {}
- String shader_get_code(RID p_shader) const override { return ""; }
- void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
-
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
- Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
-
- RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
-
- /* COMMON MATERIAL API */
-
- RID material_allocate() override { return RID(); }
- void material_initialize(RID p_rid) override {}
- void material_set_render_priority(RID p_material, int priority) override {}
- void material_set_shader(RID p_shader_material, RID p_shader) override {}
-
- void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {}
- Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); }
-
- void material_set_next_pass(RID p_material, RID p_next_material) override {}
-
- bool material_is_animated(RID p_material) override { return false; }
- bool material_casts_shadows(RID p_material) override { return false; }
- void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
- void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
-
- /* MESH API */
-
- RID mesh_allocate() override { return RID(); }
- void mesh_initialize(RID p_rid) override {}
- void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
- bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
- RID mesh_instance_create(RID p_base) override { return RID(); }
- void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
- void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
- void mesh_instance_check_for_update(RID p_mesh_instance) override {}
- void update_mesh_instances() override {}
- void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
- float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
-
- void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
-
- int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
- RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
-
- void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
- void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
- void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
-
- void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
- RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
-
- RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- int mesh_get_surface_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
- AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
-
- AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
- void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
- void mesh_clear(RID p_mesh) override {}
-
- /* MULTIMESH API */
-
- RID multimesh_allocate() override { return RID(); }
- void multimesh_initialize(RID p_rid) override {}
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
- int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
-
- RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
- AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
- Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
- int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
-
- /* SKELETON API */
-
- RID skeleton_allocate() override { return RID(); }
- void skeleton_initialize(RID p_rid) override {}
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
- int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
-
- /* Light API */
-
- RID directional_light_allocate() override { return RID(); }
- void directional_light_initialize(RID p_rid) override {}
- RID omni_light_allocate() override { return RID(); }
- void omni_light_initialize(RID p_rid) override {}
- RID spot_light_allocate() override { return RID(); }
- void spot_light_initialize(RID p_rid) override {}
- RID reflection_probe_allocate() override { return RID(); }
- void reflection_probe_initialize(RID p_rid) override {}
-
- void light_set_color(RID p_light, const Color &p_color) override {}
- void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
- void light_set_shadow(RID p_light, bool p_enabled) override {}
- void light_set_shadow_color(RID p_light, const Color &p_color) override {}
- void light_set_projector(RID p_light, RID p_texture) override {}
- void light_set_negative(RID p_light, bool p_enable) override {}
- void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
- void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
- void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
-
- void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
-
- void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
- void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
- bool light_directional_get_blend_splits(RID p_light) const override { return false; }
- void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {}
- bool light_directional_is_sky_only(RID p_light) const override { return false; }
-
- RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
- RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
-
- bool light_has_shadow(RID p_light) const override { return false; }
- bool light_has_projector(RID p_light) const override { return false; }
-
- RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
- AABB light_get_aabb(RID p_light) const override { return AABB(); }
- float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
- Color light_get_color(RID p_light) override { return Color(); }
- RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
- uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
- uint64_t light_get_version(RID p_light) const override { return 0; }
-
- /* PROBE API */
-
- void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
- void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
- void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
- void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
- void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
- void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
- void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
-
- AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
- RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
- Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
- Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
- float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
- bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
-
- void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
- void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
-
- /* DECAL API */
-
- RID decal_allocate() override { return RID(); }
- void decal_initialize(RID p_rid) override {}
- void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
- void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
- void decal_set_emission_energy(RID p_decal, float p_energy) override {}
- void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
- void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
- void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
- void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
- void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
- void decal_set_normal_fade(RID p_decal, float p_fade) override {}
-
- AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
-
- /* VOXEL GI API */
-
- RID voxel_gi_allocate() override { return RID(); }
- void voxel_gi_initialize(RID p_rid) override {}
- void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &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) override {}
-
- AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); }
- Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); }
- Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
- Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
- Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
-
- Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); }
- Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); }
-
- void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; }
-
- void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; }
-
- void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
-
- void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
-
- void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; }
-
- void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {}
- bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; }
-
- void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {}
- bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
-
- void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {}
- float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; }
-
- uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; }
-
- /* LIGHTMAP CAPTURE */
- RID lightmap_allocate() override { return RID(); }
- void lightmap_initialize(RID p_rid) override {}
- void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
- void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
- void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
- 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) override {}
- PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
- PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
- PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
- PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
- AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
- void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
- bool lightmap_is_interior(RID p_lightmap) const override { return false; }
- void lightmap_set_probe_capture_update_speed(float p_speed) override {}
- float lightmap_get_probe_capture_update_speed() const override { return 0; }
-
- /* OCCLUDER */
-
- void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
-
- /* PARTICLES */
-
- RID particles_allocate() override { return RID(); }
- void particles_initialize(RID p_rid) override {}
- void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
- void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
- void particles_set_emitting(RID p_particles, bool p_emitting) override {}
- void particles_set_amount(RID p_particles, int p_amount) override {}
- void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
- void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
- void particles_set_pre_process_time(RID p_particles, double p_time) override {}
- void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
- void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
- void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
- void particles_set_speed_scale(RID p_particles, double p_scale) override {}
- void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
- void particles_set_process_material(RID p_particles, RID p_material) override {}
- RID particles_get_process_material(RID p_particles) const override { return RID(); }
- void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
- void particles_set_interpolate(RID p_particles, bool p_enable) override {}
- void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
- void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
- void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
- void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
-
- void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
-
- void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
-
- void particles_restart(RID p_particles) override {}
-
- void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
-
- void particles_set_draw_passes(RID p_particles, int p_count) override {}
- void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
-
- void particles_request_process(RID p_particles) override {}
- AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
- AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
-
- void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
-
- bool particles_get_emitting(RID p_particles) override { return false; }
- int particles_get_draw_passes(RID p_particles) const override { return 0; }
- RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
-
- void particles_add_collision(RID p_particles, RID p_instance) override {}
- void particles_remove_collision(RID p_particles, RID p_instance) override {}
-
- void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
-
- void update_particles() override {}
-
- /* PARTICLES COLLISION */
-
- RID particles_collision_allocate() override { return RID(); }
- void particles_collision_initialize(RID p_rid) override {}
- void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
- void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
- void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
- void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
- void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
- void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
- void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
- void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
- void particles_collision_height_field_update(RID p_particles_collision) override {}
- void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
- AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
- bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
- RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
-
- RID particles_collision_instance_create(RID p_collision) override { return RID(); }
- void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
- void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
-
- /* FOG VOLUMES */
-
- RID fog_volume_allocate() override { return RID(); }
- void fog_volume_initialize(RID p_rid) override {}
-
- void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
- void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
- void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
- AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
- RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
-
- /* VISIBILITY NOTIFIER */
- virtual RID visibility_notifier_allocate() override { return RID(); }
- virtual void visibility_notifier_initialize(RID p_notifier) override {}
- virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
- virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
-
- virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
- virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
-
- /* GLOBAL VARIABLES */
-
- void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
- void global_variable_remove(const StringName &p_name) override {}
- Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
-
- void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
- void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
- Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
- RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
-
- void global_variables_load_settings(bool p_load_textures = true) override {}
- void global_variables_clear() override {}
-
- int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
- void global_variables_instance_free(RID p_instance) override {}
- void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
-
- bool particles_is_inactive(RID p_particles) const override { return false; }
-
- /* RENDER TARGET */
-
- RID render_target_create() override { return RID(); }
- void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
- void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
- RID render_target_get_texture(RID p_render_target) override { return RID(); }
- void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
- void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
- bool render_target_was_used(RID p_render_target) override { return false; }
- void render_target_set_as_unused(RID p_render_target) override {}
-
- void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
- bool render_target_is_clear_requested(RID p_render_target) override { return false; }
- Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
- void render_target_disable_clear_request(RID p_render_target) override {}
- void render_target_do_clear_request(RID p_render_target) override {}
-
- void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
- Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
- void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
-
- RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
- bool free(RID p_rid) override {
- if (texture_owner.owns(p_rid)) {
- // delete the texture
- DummyTexture *texture = texture_owner.get_or_null(p_rid);
- texture_owner.free(p_rid);
- memdelete(texture);
- return true;
- }
- return false;
- }
-
- virtual void update_memory_info() override {}
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
-
- bool has_os_feature(const String &p_feature) const override {
- return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
- }
-
- void update_dirty_resources() override {}
-
- void set_debug_generate_wireframes(bool p_generate) override {}
-
- String get_video_adapter_name() const override { return String(); }
- String get_video_adapter_vendor() const override { return String(); }
- RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
-
- static RendererStorage *base_singleton;
-
- void capture_timestamps_begin() override {}
- void capture_timestamp(const String &p_name) override {}
- uint32_t get_captured_timestamps_count() const override { return 0; }
- uint64_t get_captured_timestamps_frame() const override { return 0; }
- uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
- uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
- String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
-
- RasterizerStorageDummy() {}
- ~RasterizerStorageDummy() {}
-};
-
-class RasterizerCanvasDummy : public RendererCanvasRender {
-public:
- 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>()) override { return 0; }
- void free_polygon(PolygonID p_polygon) override {}
-
- 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) override {}
- void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
-
- RID light_create() override { return RID(); }
- void light_set_texture(RID p_rid, RID p_texture) override {}
- void light_set_use_shadow(RID p_rid, bool p_enable) override {}
- 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) override {}
- 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) override {}
-
- void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
- RID occluder_polygon_create() override { return RID(); }
- void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {}
- void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
- void set_shadow_texture_size(int p_size) override {}
-
- bool free(RID p_rid) override { return true; }
- void update() override {}
-
- RasterizerCanvasDummy() {}
- ~RasterizerCanvasDummy() {}
-};
-
-class RasterizerDummy : public RendererCompositor {
-private:
- uint64_t frame = 1;
- double delta = 0;
-
-protected:
- RasterizerCanvasDummy canvas;
- RasterizerStorageDummy storage;
- RasterizerSceneDummy scene;
-
-public:
- RendererStorage *get_storage() override { return &storage; }
- RendererCanvasRender *get_canvas() override { return &canvas; }
- RendererSceneRender *get_scene() override { return &scene; }
-
- void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {}
-
- void initialize() override {}
- void begin_frame(double frame_step) override {
- frame++;
- delta = frame_step;
- }
-
- void prepare_for_blitting_render_targets() override {}
- void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
-
- void end_frame(bool p_swap_buffers) override {
- if (p_swap_buffers) {
- DisplayServer::get_singleton()->swap_buffers();
- }
- }
-
- void finalize() override {}
-
- static RendererCompositor *_create_current() {
- return memnew(RasterizerDummy);
- }
-
- static void make_current() {
- _create_func = _create_current;
- }
-
- bool is_low_end() const override { return true; }
- uint64_t get_frame_number() const override { return frame; }
- double get_frame_delta_time() const override { return delta; }
-
- RasterizerDummy() {}
- ~RasterizerDummy() {}
-};
-
-#endif // RASTERIZER_DUMMY_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 418d2bc42e..bc1e8eb348 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -34,6 +34,7 @@
#include "renderer_viewport.h"
#include "rendering_server_default.h"
#include "rendering_server_globals.h"
+#include "servers/rendering/storage/texture_storage.h"
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
@@ -66,7 +67,7 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas
}
}
- RENDER_TIMESTAMP("Render Canvas Items");
+ RENDER_TIMESTAMP("Render CanvasItems");
bool sdf_flag;
RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, sdf_flag);
@@ -83,7 +84,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
if (r_items) {
r_items[r_index] = child_items[i];
child_items[i]->ysort_xform = p_transform;
- child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
child_items[i]->ysort_index = r_index;
}
@@ -235,7 +236,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
Transform2D xform = ci->xform;
if (snapping_2d_transforms_to_pixel) {
- xform.elements[2] = xform.elements[2].floor();
+ xform.columns[2] = xform.columns[2].floor();
}
xform = p_transform * xform;
@@ -338,7 +339,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
}
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");
+ RENDER_TIMESTAMP("> Render Canvas");
sdf_used = false;
snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel;
@@ -384,7 +385,7 @@ void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, co
}
}
- RENDER_TIMESTAMP("<End Render Canvas");
+ RENDER_TIMESTAMP("< Render Canvas");
}
bool RendererCanvasCull::was_sdf_used() {
@@ -551,27 +552,188 @@ void RendererCanvasCull::canvas_item_set_update_when_visible(RID p_item, bool p_
canvas_item->update_when_visible = p_update;
}
-void RendererCanvasCull::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, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!line);
+
+ Vector2 diff = (p_from - p_to);
+ Vector2 dir = diff.orthogonal().normalized();
+ Vector2 t = dir * p_width * 0.5;
+
+ Vector2 begin_left;
+ Vector2 begin_right;
+ Vector2 end_left;
+ Vector2 end_right;
+
if (p_width > 1.001) {
- Vector2 t = (p_from - p_to).orthogonal().normalized() * p_width * 0.5;
- line->points[0] = p_from + t;
- line->points[1] = p_from - t;
- line->points[2] = p_to - t;
- line->points[3] = p_to + t;
+ begin_left = p_from + t;
+ begin_right = p_from - t;
+ end_left = p_to + t;
+ end_right = p_to - t;
+
+ line->points[0] = begin_left;
+ line->points[1] = begin_right;
+ line->points[2] = end_right;
+ line->points[3] = end_left;
line->point_count = 4;
} else {
- line->point_count = 2;
+ begin_left = p_from;
+ begin_right = p_from;
+ end_left = p_to;
+ end_right = p_to;
+
line->points[0] = p_from;
line->points[1] = p_to;
+ line->point_count = 2;
}
for (uint32_t i = 0; i < line->point_count; i++) {
line->colors[i] = p_color;
}
+
+ if (p_antialiased) {
+ float border_size = 2.0;
+ if (p_width < border_size) {
+ border_size = p_width;
+ }
+ Vector2 dir2 = diff.normalized();
+
+ Vector2 border = dir * border_size;
+ Vector2 border2 = dir2 * border_size;
+
+ Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0);
+
+ {
+ Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!left_border);
+
+ left_border->points[0] = begin_left;
+ left_border->points[1] = begin_left + border;
+ left_border->points[2] = end_left + border;
+ left_border->points[3] = end_left;
+
+ left_border->colors[0] = p_color;
+ left_border->colors[1] = transparent;
+ left_border->colors[2] = transparent;
+ left_border->colors[3] = p_color;
+
+ left_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!right_border);
+
+ right_border->points[0] = begin_right;
+ right_border->points[1] = begin_right - border;
+ right_border->points[2] = end_right - border;
+ right_border->points[3] = end_right;
+
+ right_border->colors[0] = p_color;
+ right_border->colors[1] = transparent;
+ right_border->colors[2] = transparent;
+ right_border->colors[3] = p_color;
+
+ right_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!top_border);
+
+ top_border->points[0] = begin_left;
+ top_border->points[1] = begin_left + border2;
+ top_border->points[2] = begin_right + border2;
+ top_border->points[3] = begin_right;
+
+ top_border->colors[0] = p_color;
+ top_border->colors[1] = transparent;
+ top_border->colors[2] = transparent;
+ top_border->colors[3] = p_color;
+
+ top_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!bottom_border);
+
+ bottom_border->points[0] = end_left;
+ bottom_border->points[1] = end_left - border2;
+ bottom_border->points[2] = end_right - border2;
+ bottom_border->points[3] = end_right;
+
+ bottom_border->colors[0] = p_color;
+ bottom_border->colors[1] = transparent;
+ bottom_border->colors[2] = transparent;
+ bottom_border->colors[3] = p_color;
+
+ bottom_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!top_left_corner);
+
+ top_left_corner->points[0] = begin_left;
+ top_left_corner->points[1] = begin_left + border2;
+ top_left_corner->points[2] = begin_left + border + border2;
+ top_left_corner->points[3] = begin_left + border;
+
+ top_left_corner->colors[0] = p_color;
+ top_left_corner->colors[1] = transparent;
+ top_left_corner->colors[2] = transparent;
+ top_left_corner->colors[3] = transparent;
+
+ top_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!top_right_corner);
+
+ top_right_corner->points[0] = begin_right;
+ top_right_corner->points[1] = begin_right + border2;
+ top_right_corner->points[2] = begin_right - border + border2;
+ top_right_corner->points[3] = begin_right - border;
+
+ top_right_corner->colors[0] = p_color;
+ top_right_corner->colors[1] = transparent;
+ top_right_corner->colors[2] = transparent;
+ top_right_corner->colors[3] = transparent;
+
+ top_right_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!bottom_left_corner);
+
+ bottom_left_corner->points[0] = end_left;
+ bottom_left_corner->points[1] = end_left - border2;
+ bottom_left_corner->points[2] = end_left + border - border2;
+ bottom_left_corner->points[3] = end_left + border;
+
+ bottom_left_corner->colors[0] = p_color;
+ bottom_left_corner->colors[1] = transparent;
+ bottom_left_corner->colors[2] = transparent;
+ bottom_left_corner->colors[3] = transparent;
+
+ bottom_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!bottom_right_corner);
+
+ bottom_right_corner->points[0] = end_right;
+ bottom_right_corner->points[1] = end_right - border2;
+ bottom_right_corner->points[2] = end_right - border - border2;
+ bottom_right_corner->points[3] = end_right - border;
+
+ bottom_right_corner->colors[0] = p_color;
+ bottom_right_corner->colors[1] = transparent;
+ bottom_right_corner->colors[2] = transparent;
+ bottom_right_corner->colors[3] = transparent;
+
+ bottom_right_corner->point_count = 4;
+ }
+ }
}
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) {
@@ -601,42 +763,119 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
+ float border_size = 2.0;
+ if (p_width < border_size) {
+ border_size = p_width;
+ }
Color color2 = Color(1, 1, 1, 0);
- PackedColorArray colors_top;
- PackedVector2Array points_top;
+ PackedColorArray colors_begin;
+ PackedVector2Array points_begin;
+
+ colors_begin.resize(4);
+ points_begin.resize(4);
+
+ PackedColorArray colors_begin_left_corner;
+ PackedVector2Array points_begin_left_corner;
+
+ colors_begin_left_corner.resize(4);
+ points_begin_left_corner.resize(4);
+
+ PackedColorArray colors_begin_right_corner;
+ PackedVector2Array points_begin_right_corner;
+
+ colors_begin_right_corner.resize(4);
+ points_begin_right_corner.resize(4);
+
+ PackedColorArray colors_end;
+ PackedVector2Array points_end;
+
+ colors_end.resize(4);
+ points_end.resize(4);
+
+ PackedColorArray colors_end_left_corner;
+ PackedVector2Array points_end_left_corner;
+
+ colors_end_left_corner.resize(4);
+ points_end_left_corner.resize(4);
+
+ PackedColorArray colors_end_right_corner;
+ PackedVector2Array points_end_right_corner;
+
+ colors_end_right_corner.resize(4);
+ points_end_right_corner.resize(4);
+
+ PackedColorArray colors_left;
+ PackedVector2Array points_left;
+
+ colors_left.resize(pc2);
+ points_left.resize(pc2);
+
+ PackedColorArray colors_right;
+ PackedVector2Array points_right;
- colors_top.resize(pc2);
- points_top.resize(pc2);
+ colors_right.resize(pc2);
+ points_right.resize(pc2);
- PackedColorArray colors_bottom;
- PackedVector2Array points_bottom;
+ Item::CommandPolygon *pline_begin = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_begin);
- colors_bottom.resize(pc2);
- points_bottom.resize(pc2);
+ Item::CommandPolygon *pline_begin_left_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_begin_left_corner);
- Item::CommandPolygon *pline_top = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_COND(!pline_top);
+ Item::CommandPolygon *pline_begin_right_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_begin_right_corner);
- Item::CommandPolygon *pline_bottom = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_COND(!pline_bottom);
+ Item::CommandPolygon *pline_end = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_end);
- //make three trianglestrip's for drawing the antialiased line...
+ Item::CommandPolygon *pline_end_left_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_end_left_corner);
- Vector2 *points_top_ptr = points_top.ptrw();
- Vector2 *points_bottom_ptr = points_bottom.ptrw();
+ Item::CommandPolygon *pline_end_right_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_end_right_corner);
- Color *colors_top_ptr = colors_top.ptrw();
- Color *colors_bottom_ptr = colors_bottom.ptrw();
+ Item::CommandPolygon *pline_left = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_left);
+
+ Item::CommandPolygon *pline_right = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_right);
+
+ // Makes nine triangle strips for drawing the antialiased line.
+
+ Vector2 *points_begin_ptr = points_begin.ptrw();
+ Vector2 *points_begin_left_corner_ptr = points_begin_left_corner.ptrw();
+ Vector2 *points_begin_right_corner_ptr = points_begin_right_corner.ptrw();
+ Vector2 *points_end_ptr = points_end.ptrw();
+ Vector2 *points_end_left_corner_ptr = points_end_left_corner.ptrw();
+ Vector2 *points_end_right_corner_ptr = points_end_right_corner.ptrw();
+ Vector2 *points_left_ptr = points_left.ptrw();
+ Vector2 *points_right_ptr = points_right.ptrw();
+
+ Color *colors_begin_ptr = colors_begin.ptrw();
+ Color *colors_begin_left_corner_ptr = colors_begin_left_corner.ptrw();
+ Color *colors_begin_right_corner_ptr = colors_begin_right_corner.ptrw();
+ Color *colors_end_ptr = colors_end.ptrw();
+ Color *colors_end_left_corner_ptr = colors_end_left_corner.ptrw();
+ Color *colors_end_right_corner_ptr = colors_end_right_corner.ptrw();
+ Color *colors_left_ptr = colors_left.ptrw();
+ Color *colors_right_ptr = colors_right.ptrw();
for (int i = 0, j = 0; i < pc; i++, j += 2) {
+ bool is_begin = i == 0;
+ bool is_end = i == pc - 1;
+
Vector2 t;
- if (i == pc - 1) {
+ Vector2 end_border;
+ Vector2 begin_border;
+ if (is_end) {
t = prev_t;
+ end_border = (p_points[i] - p_points[i - 1]).normalized() * border_size;
} else {
t = (p_points[i + 1] - p_points[i]).normalized().orthogonal();
- if (i == 0) {
+ if (is_begin) {
prev_t = t;
+ begin_border = (p_points[i] - p_points[i + 1]).normalized() * border_size;
}
}
@@ -644,17 +883,17 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Vector2 dir = (t + prev_t).normalized();
Vector2 tangent = dir * p_width * 0.5;
- Vector2 border = dir * 2.0;
+ Vector2 border = dir * border_size;
Vector2 pos = p_points[i];
points_ptr[j] = pos + tangent;
points_ptr[j2] = pos - tangent;
- points_top_ptr[j] = pos + tangent + border;
- points_top_ptr[j2] = pos + tangent;
+ points_left_ptr[j] = pos + tangent + border;
+ points_left_ptr[j2] = pos + tangent;
- points_bottom_ptr[j] = pos - tangent;
- points_bottom_ptr[j2] = pos - tangent - border;
+ points_right_ptr[j] = pos - tangent;
+ points_right_ptr[j2] = pos - tangent - border;
if (i < p_colors.size()) {
color = p_colors[i];
@@ -664,22 +903,104 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
colors_ptr[j] = color;
colors_ptr[j2] = color;
- colors_top_ptr[j] = color2;
- colors_top_ptr[j2] = color;
+ colors_left_ptr[j] = color2;
+ colors_left_ptr[j2] = color;
+
+ colors_right_ptr[j] = color;
+ colors_right_ptr[j2] = color2;
+
+ if (is_begin) {
+ points_begin_ptr[0] = pos + tangent + begin_border;
+ points_begin_ptr[1] = pos - tangent + begin_border;
+ points_begin_ptr[2] = pos + tangent;
+ points_begin_ptr[3] = pos - tangent;
+
+ colors_begin_ptr[0] = color2;
+ colors_begin_ptr[1] = color2;
+ colors_begin_ptr[2] = color;
+ colors_begin_ptr[3] = color;
+
+ points_begin_left_corner_ptr[0] = pos - tangent - border;
+ points_begin_left_corner_ptr[1] = pos - tangent + begin_border - border;
+ points_begin_left_corner_ptr[2] = pos - tangent;
+ points_begin_left_corner_ptr[3] = pos - tangent + begin_border;
+
+ colors_begin_left_corner_ptr[0] = color2;
+ colors_begin_left_corner_ptr[1] = color2;
+ colors_begin_left_corner_ptr[2] = color;
+ colors_begin_left_corner_ptr[3] = color2;
+
+ points_begin_right_corner_ptr[0] = pos + tangent + begin_border;
+ points_begin_right_corner_ptr[1] = pos + tangent + begin_border + border;
+ points_begin_right_corner_ptr[2] = pos + tangent;
+ points_begin_right_corner_ptr[3] = pos + tangent + border;
+
+ colors_begin_right_corner_ptr[0] = color2;
+ colors_begin_right_corner_ptr[1] = color2;
+ colors_begin_right_corner_ptr[2] = color;
+ colors_begin_right_corner_ptr[3] = color2;
+ }
- colors_bottom_ptr[j] = color;
- colors_bottom_ptr[j2] = color2;
+ if (is_end) {
+ points_end_ptr[0] = pos + tangent + end_border;
+ points_end_ptr[1] = pos - tangent + end_border;
+ points_end_ptr[2] = pos + tangent;
+ points_end_ptr[3] = pos - tangent;
+
+ colors_end_ptr[0] = color2;
+ colors_end_ptr[1] = color2;
+ colors_end_ptr[2] = color;
+ colors_end_ptr[3] = color;
+
+ points_end_left_corner_ptr[0] = pos - tangent - border;
+ points_end_left_corner_ptr[1] = pos - tangent + end_border - border;
+ points_end_left_corner_ptr[2] = pos - tangent;
+ points_end_left_corner_ptr[3] = pos - tangent + end_border;
+
+ colors_end_left_corner_ptr[0] = color2;
+ colors_end_left_corner_ptr[1] = color2;
+ colors_end_left_corner_ptr[2] = color;
+ colors_end_left_corner_ptr[3] = color2;
+
+ points_end_right_corner_ptr[0] = pos + tangent + end_border;
+ points_end_right_corner_ptr[1] = pos + tangent + end_border + border;
+ points_end_right_corner_ptr[2] = pos + tangent;
+ points_end_right_corner_ptr[3] = pos + tangent + border;
+
+ colors_end_right_corner_ptr[0] = color2;
+ colors_end_right_corner_ptr[1] = color2;
+ colors_end_right_corner_ptr[2] = color;
+ colors_end_right_corner_ptr[3] = color2;
+ }
prev_t = t;
}
- pline_top->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
- pline_top->polygon.create(indices, points_top, colors_top);
+ pline_begin->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_begin->polygon.create(indices, points_begin, colors_begin);
+
+ pline_begin_left_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_begin_left_corner->polygon.create(indices, points_begin_left_corner, colors_begin_left_corner);
- pline_bottom->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
- pline_bottom->polygon.create(indices, points_bottom, colors_bottom);
+ pline_begin_right_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_begin_right_corner->polygon.create(indices, points_begin_right_corner, colors_begin_right_corner);
+
+ pline_end->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_end->polygon.create(indices, points_end, colors_end);
+
+ pline_end_left_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_end_left_corner->polygon.create(indices, points_end_left_corner, colors_end_left_corner);
+
+ pline_end_right_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_end_right_corner->polygon.create(indices, points_end_right_corner, colors_end_right_corner);
+
+ pline_left->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_left->polygon.create(indices, points_left, colors_left);
+
+ pline_right->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_right->polygon.create(indices, points_right, colors_right);
} else {
- //make a trianglestrip for drawing the line...
+ // Makes a single triangle strip for drawing the line.
for (int i = 0, j = 0; i < pc; i++, j += 2) {
Vector2 t;
@@ -996,8 +1317,8 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con
ERR_FAIL_COND(!m);
m->mesh = p_mesh;
if (canvas_item->skeleton.is_valid()) {
- m->mesh_instance = RSG::storage->mesh_instance_create(p_mesh);
- RSG::storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);
+ m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh);
+ RSG::mesh_storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);
}
m->texture = p_texture;
@@ -1017,7 +1338,7 @@ void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles,
part->texture = p_texture;
//take the chance and request processing for them, at least once until they become visible again
- RSG::storage->particles_request_process(p_particles);
+ RSG::particles_storage->particles_request_process(p_particles);
}
void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) {
@@ -1092,12 +1413,12 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton)
Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c);
if (canvas_item->skeleton.is_valid()) {
if (cm->mesh_instance.is_null()) {
- cm->mesh_instance = RSG::storage->mesh_instance_create(cm->mesh);
+ cm->mesh_instance = RSG::mesh_storage->mesh_instance_create(cm->mesh);
}
- RSG::storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);
+ RSG::mesh_storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);
} else {
if (cm->mesh_instance.is_valid()) {
- RSG::storage->free(cm->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(cm->mesh_instance);
cm->mesh_instance = RID();
}
}
@@ -1510,8 +1831,8 @@ void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygo
RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed);
- for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) {
- E->get()->aabb_cache = occluder_poly->aabb;
+ for (RendererCanvasRender::LightOccluderInstance *E : occluder_poly->owners) {
+ E->aabb_cache = occluder_poly->aabb;
}
}
@@ -1520,8 +1841,8 @@ void RendererCanvasCull::canvas_occluder_polygon_set_cull_mode(RID p_occluder_po
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<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) {
- E->get()->cull_cache = p_mode;
+ for (RendererCanvasRender::LightOccluderInstance *E : occluder_poly->owners) {
+ E->cull_cache = p_mode;
}
}
@@ -1530,26 +1851,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {
}
RID RendererCanvasCull::canvas_texture_allocate() {
- return RSG::storage->canvas_texture_allocate();
+ return RSG::texture_storage->canvas_texture_allocate();
}
void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {
- RSG::storage->canvas_texture_initialize(p_rid);
+ RSG::texture_storage->canvas_texture_initialize(p_rid);
}
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);
+ RSG::texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);
}
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);
+ RSG::texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);
}
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);
+ RSG::texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);
}
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);
+ RSG::texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);
}
void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) {
@@ -1607,26 +1928,26 @@ bool RendererCanvasCull::free(RID p_rid) {
ERR_FAIL_COND_V(!canvas, false);
while (canvas->viewports.size()) {
- RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.get_or_null(canvas->viewports.front()->get());
+ RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.get_or_null(*canvas->viewports.begin());
ERR_FAIL_COND_V(!vp, true);
- Map<RID, RendererViewport::Viewport::CanvasData>::Element *E = vp->canvas_map.find(p_rid);
+ HashMap<RID, RendererViewport::Viewport::CanvasData>::Iterator E = vp->canvas_map.find(p_rid);
ERR_FAIL_COND_V(!E, true);
vp->canvas_map.erase(p_rid);
- canvas->viewports.erase(canvas->viewports.front());
+ canvas->viewports.erase(*canvas->viewports.begin());
}
for (int i = 0; i < canvas->child_items.size(); i++) {
canvas->child_items[i].item->parent = RID();
}
- for (Set<RendererCanvasRender::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) {
- E->get()->canvas = RID();
+ for (RendererCanvasRender::Light *E : canvas->lights) {
+ E->canvas = RID();
}
- for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) {
- E->get()->canvas = RID();
+ for (RendererCanvasRender::LightOccluderInstance *E : canvas->occluders) {
+ E->canvas = RID();
}
canvas_owner.free(p_rid);
@@ -1663,6 +1984,11 @@ bool RendererCanvasCull::free(RID p_rid) {
}
*/
+ if (canvas_item->canvas_group != nullptr) {
+ memdelete(canvas_item->canvas_group);
+ canvas_item->canvas_group = nullptr;
+ }
+
canvas_item_owner.free(p_rid);
} else if (canvas_light_owner.owns(p_rid)) {
@@ -1704,8 +2030,8 @@ bool RendererCanvasCull::free(RID p_rid) {
RSG::canvas_render->free(occluder_poly->occluder);
while (occluder_poly->owners.size()) {
- occluder_poly->owners.front()->get()->polygon = RID();
- occluder_poly->owners.erase(occluder_poly->owners.front());
+ (*occluder_poly->owners.begin())->polygon = RID();
+ occluder_poly->owners.remove(occluder_poly->owners.begin());
}
canvas_light_occluder_polygon_owner.free(p_rid);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index fc53ce2327..963cca7630 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -108,7 +108,7 @@ public:
Rect2 aabb;
RS::CanvasOccluderPolygonCullMode cull_mode;
RID occluder;
- Set<RendererCanvasRender::LightOccluderInstance *> owners;
+ HashSet<RendererCanvasRender::LightOccluderInstance *> owners;
LightOccluderPolygon() {
active = false;
@@ -121,19 +121,19 @@ public:
RID_Owner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
struct Canvas : public RendererViewport::CanvasBase {
- Set<RID> viewports;
+ HashSet<RID> viewports;
struct ChildItem {
Point2 mirror;
- Item *item;
+ Item *item = nullptr;
bool operator<(const ChildItem &p_item) const {
return item->index < p_item.item->index;
}
};
- Set<RendererCanvasRender::Light *> lights;
- Set<RendererCanvasRender::Light *> directional_lights;
+ HashSet<RendererCanvasRender::Light *> lights;
+ HashSet<RendererCanvasRender::Light *> directional_lights;
- Set<RendererCanvasRender::LightOccluderInstance *> occluders;
+ HashSet<RendererCanvasRender::LightOccluderInstance *> occluders;
bool children_order_dirty;
Vector<ChildItem> child_items;
@@ -215,7 +215,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_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
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);
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 3b68cd74fd..163a24247e 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -29,3 +29,102 @@
/*************************************************************************/
#include "renderer_canvas_render.h"
+#include "servers/rendering/rendering_server_globals.h"
+
+const Rect2 &RendererCanvasRender::Item::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 = RSG::mesh_storage->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 = RSG::mesh_storage->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 = RSG::particles_storage->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);
+ }
+
+ if (first) {
+ rect = r;
+ first = false;
+ } else {
+ rect = rect.merge(r);
+ }
+ c = c->next;
+ }
+
+ rect_dirty = false;
+ return rect;
+}
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 1840925f78..1724a99b20 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -82,10 +82,10 @@ public:
Transform2D light_shader_xform;
//Vector2 light_shader_pos;
- Light *shadows_next_ptr;
- Light *filter_next_ptr;
- Light *next_ptr;
- Light *directional_next_ptr;
+ Light *shadows_next_ptr = nullptr;
+ Light *filter_next_ptr = nullptr;
+ Light *next_ptr = nullptr;
+ Light *directional_next_ptr = nullptr;
RID light_internal;
uint64_t version;
@@ -167,7 +167,7 @@ public:
MAX_SIZE = 4096
};
uint32_t usage;
- uint8_t *memory;
+ uint8_t *memory = nullptr;
};
struct Command {
@@ -184,7 +184,7 @@ public:
TYPE_ANIMATION_SLICE,
};
- Command *next;
+ Command *next = nullptr;
Type type;
virtual ~Command() {}
};
@@ -304,8 +304,8 @@ public:
};
struct ViewportRender {
- RenderingServer *owner;
- void *udata;
+ RenderingServer *owner = nullptr;
+ void *udata = nullptr;
Rect2 rect;
};
@@ -333,133 +333,37 @@ public:
RID material;
RID skeleton;
- Item *next;
+ Item *next = nullptr;
struct CopyBackBuffer {
Rect2 rect;
Rect2 screen_rect;
bool full;
};
- CopyBackBuffer *copy_back_buffer;
+ CopyBackBuffer *copy_back_buffer = nullptr;
Color final_modulate;
Transform2D final_transform;
Rect2 final_clip_rect;
- Item *final_clip_owner;
- Item *material_owner;
- Item *canvas_group_owner;
- ViewportRender *vp_render;
+ Item *final_clip_owner = nullptr;
+ Item *material_owner = nullptr;
+ Item *canvas_group_owner = nullptr;
+ ViewportRender *vp_render = nullptr;
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);
- }
-
- if (first) {
- rect = r;
- first = false;
- } else {
- rect = rect.merge(r);
- }
- c = c->next;
- }
-
- rect_dirty = false;
- return rect;
- }
+ const Rect2 &get_rect() const;
- Command *commands;
- Command *last_command;
+ Command *commands = nullptr;
+ Command *last_command = nullptr;
Vector<CommandBlock> blocks;
uint32_t current_block;
template <class T>
T *alloc_command() {
- T *command;
+ T *command = nullptr;
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
@@ -589,7 +493,7 @@ public:
bool sdf_collision;
RS::CanvasOccluderPolygonCullMode cull_cache;
- LightOccluderInstance *next;
+ LightOccluderInstance *next = nullptr;
LightOccluderInstance() {
enabled = true;
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index fa4d9c8b31..b331ec2c1d 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -35,6 +35,7 @@
#include "core/string/print_string.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
+bool RendererCompositor::low_end = false;
RendererCompositor *RendererCompositor::create() {
return _create_func();
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index e58fd7bebc..df3df1077a 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -34,6 +34,11 @@
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/light_storage.h"
+#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/particles_storage.h"
+#include "servers/rendering/storage/texture_storage.h"
#include "servers/rendering_server.h"
class RendererSceneRender;
@@ -66,10 +71,16 @@ private:
protected:
static RendererCompositor *(*_create_func)();
bool back_end = false;
+ static bool low_end;
public:
static RendererCompositor *create();
+ virtual RendererLightStorage *get_light_storage() = 0;
+ virtual RendererMaterialStorage *get_material_storage() = 0;
+ virtual RendererMeshStorage *get_mesh_storage() = 0;
+ virtual RendererParticlesStorage *get_particles_storage() = 0;
+ virtual RendererTextureStorage *get_texture_storage() = 0;
virtual RendererStorage *get_storage() = 0;
virtual RendererCanvasRender *get_canvas() = 0;
virtual RendererSceneRender *get_scene() = 0;
@@ -87,7 +98,7 @@ public:
virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0;
- _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; };
+ static bool is_low_end() { return low_end; };
virtual bool is_xr_enabled() const;
RendererCompositor();
diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub
index 64e613ab91..774a6b7951 100644
--- a/servers/rendering/renderer_rd/SCsub
+++ b/servers/rendering/renderer_rd/SCsub
@@ -4,6 +4,8 @@ Import("env")
env.add_source_files(env.servers_sources, "*.cpp")
+SConscript("effects/SCsub")
SConscript("forward_clustered/SCsub")
SConscript("forward_mobile/SCsub")
SConscript("shaders/SCsub")
+SConscript("storage_rd/SCsub")
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 6ad3556969..0b36fe3964 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -269,7 +269,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size);
cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size);
- render_elements = (RenderElementData *)memalloc(sizeof(RenderElementData *) * render_element_max);
+ render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData *) * render_element_max));
render_element_count = 0;
element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max);
@@ -287,21 +287,21 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 1;
- u.ids.push_back(state_uniform);
+ u.append_id(state_uniform);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(element_buffer);
+ u.append_id(element_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 3;
- u.ids.push_back(cluster_render_buffer);
+ u.append_id(cluster_render_buffer);
uniforms.push_back(u);
}
@@ -314,14 +314,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(cluster_render_buffer);
+ u.append_id(cluster_render_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(cluster_buffer);
+ u.append_id(cluster_buffer);
uniforms.push_back(u);
}
@@ -329,7 +329,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 3;
- u.ids.push_back(element_buffer);
+ u.append_id(element_buffer);
uniforms.push_back(u);
}
@@ -342,14 +342,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(cluster_buffer);
+ u.append_id(cluster_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(p_color_buffer);
+ u.append_id(p_color_buffer);
uniforms.push_back(u);
}
@@ -357,14 +357,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 3;
- u.ids.push_back(p_depth_buffer);
+ u.append_id(p_depth_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 4;
- u.ids.push_back(p_depth_buffer_sampler);
+ u.append_id(p_depth_buffer_sampler);
uniforms.push_back(u);
}
@@ -398,7 +398,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa
}
void ClusterBuilderRD::bake_cluster() {
- RENDER_TIMESTAMP(">Bake Cluster");
+ RENDER_TIMESTAMP("> Bake 3D Cluster");
RD::get_singleton()->draw_command_begin_label("Bake Light Cluster");
@@ -429,7 +429,7 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
- RENDER_TIMESTAMP("Render Elements");
+ RENDER_TIMESTAMP("Render 3D Cluster Elements");
//render elements
{
@@ -466,7 +466,7 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE);
}
//store elements
- RENDER_TIMESTAMP("Pack Elements");
+ RENDER_TIMESTAMP("Pack 3D Cluster Elements");
{
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -492,7 +492,7 @@ void ClusterBuilderRD::bake_cluster() {
} else {
RD::get_singleton()->barrier(RD::BARRIER_MASK_TRANSFER, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
- RENDER_TIMESTAMP("<Bake Cluster");
+ RENDER_TIMESTAMP("< Bake 3D Cluster");
RD::get_singleton()->draw_command_end_label();
}
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 7f6750fa7e..e82193ea6a 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -289,11 +289,11 @@ public:
e.touches_near = min_d < z_near;
} else {
//contains camera inside light
- Plane base_plane(-xform.basis.get_axis(Vector3::AXIS_Z), xform.origin);
+ Plane base_plane(-xform.basis.get_column(Vector3::AXIS_Z), xform.origin);
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
//inside, check angle
- float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_axis(Vector3::AXIS_Z))));
+ float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit
} else {
e.touches_near = false;
@@ -331,9 +331,9 @@ public:
//extract scale and scale the matrix by it, makes things simpler
Vector3 scale = p_half_extents;
for (uint32_t i = 0; i < 3; i++) {
- float s = xform.basis.elements[i].length();
+ float s = xform.basis.rows[i].length();
scale[i] *= s;
- xform.basis.elements[i] /= s;
+ xform.basis.rows[i] /= s;
};
float box_depth = Math::abs(xform.basis.xform_inv(Vector3(0, 0, -1)).dot(scale));
diff --git a/servers/rendering/renderer_rd/effects/SCsub b/servers/rendering/renderer_rd/effects/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
new file mode 100644
index 0000000000..cc7441776d
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
@@ -0,0 +1,475 @@
+/*************************************************************************/
+/* bokeh_dof.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "bokeh_dof.h"
+#include "copy_effects.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+BokehDOF::BokehDOF(bool p_prefer_raster_effects) {
+ prefer_raster_effects = p_prefer_raster_effects;
+
+ // Initialize bokeh
+ Vector<String> bokeh_modes;
+ bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
+ if (prefer_raster_effects) {
+ bokeh.raster_shader.initialize(bokeh_modes);
+
+ bokeh.shader_version = bokeh.raster_shader.version_create();
+
+ const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 };
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]);
+ bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ } else {
+ bokeh.compute_shader.initialize(bokeh_modes);
+ bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false);
+ bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false);
+ bokeh.shader_version = bokeh.compute_shader.version_create();
+
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ if (bokeh.compute_shader.is_variant_enabled(i)) {
+ bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
+ }
+ }
+
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ bokeh.raster_pipelines[i].clear();
+ }
+ }
+}
+
+BokehDOF::~BokehDOF() {
+ if (prefer_raster_effects) {
+ bokeh.raster_shader.version_free(bokeh.shader_version);
+ } else {
+ bokeh.compute_shader.version_free(bokeh.shader_version);
+ }
+}
+
+void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, 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) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our push constant
+ memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
+ 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;
+
+ bokeh.push_constant.blur_near_active = p_dof_near;
+ bokeh.push_constant.blur_near_begin = p_dof_near_begin;
+ bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
+ bokeh.push_constant.use_jitter = p_use_jitter;
+ bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
+
+ bokeh.push_constant.z_near = p_cam_znear;
+ bokeh.push_constant.z_far = p_cam_zfar;
+ bokeh.push_constant.orthogonal = p_cam_orthogonal;
+ bokeh.push_constant.blur_size = p_bokeh_size;
+
+ bokeh.push_constant.second_pass = false;
+ bokeh.push_constant.half_size = false;
+
+ bokeh.push_constant.blur_scale = 0.5;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture }));
+ RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture }));
+ RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture }));
+ RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] }));
+ RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] }));
+
+ RD::Uniform u_base_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.base_texture);
+ RD::Uniform u_secondary_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.secondary_texture);
+ RD::Uniform u_half_image0(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[0]);
+ RD::Uniform u_half_image1(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[1]);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ /* FIRST PASS */
+ // The alpha channel of the source color texture is filled with the expected circle size
+ // If used for DOF far, the size is positive, if used for near, its negative.
+
+ RID shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_texture), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ //second pass
+ BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[mode]);
+
+ static const int quality_samples[4] = { 6, 12, 12, 24 };
+
+ bokeh.push_constant.steps = quality_samples[p_quality];
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ bokeh.push_constant.blur_size *= 0.5;
+
+ } else {
+ //medium and high quality use full size
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_secondary_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //third pass
+ bokeh.push_constant.second_pass = true;
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_secondary_texture), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //forth pass, upscale for low quality
+
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture1), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.second_pass = false;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
+ }
+ } else {
+ //circle
+
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BOKEH_CIRCULAR);
+ ERR_FAIL_COND(shader.is_null());
+
+ //second pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
+
+ static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
+
+ bokeh.push_constant.steps = 0;
+ bokeh.push_constant.blur_scale = quality_scale[p_quality];
+
+ //circle always runs in half size, otherwise too expensive
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //circle is just one pass, then upscale
+
+ // upscale
+
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.second_pass = false;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, 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_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our base push constant
+ memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
+
+ bokeh.push_constant.orthogonal = p_cam_orthogonal;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.width;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.height;
+ bokeh.push_constant.z_far = p_cam_zfar;
+ bokeh.push_constant.z_near = p_cam_znear;
+
+ bokeh.push_constant.second_pass = false;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.blur_size = p_dof_blur_amount;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture }));
+ RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture }));
+ RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture }));
+ RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] }));
+ RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] }));
+ RD::Uniform u_weight_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[0] }));
+ RD::Uniform u_weight_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[1] }));
+ RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
+ RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
+
+ if (p_dof_far || p_dof_near) {
+ if (p_dof_far) {
+ bokeh.push_constant.blur_far_active = true;
+ bokeh.push_constant.blur_far_begin = p_dof_far_begin;
+ bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
+ }
+
+ if (p_dof_near) {
+ bokeh.push_constant.blur_near_active = true;
+ bokeh.push_constant.blur_near_begin = p_dof_near_begin;
+ bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
+ }
+
+ {
+ // generate our depth data
+ RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RID framebuffer = p_buffers.base_weight_fb;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ // double pass approach
+ BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+
+ RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ bokeh.push_constant.blur_size *= 0.5;
+ }
+
+ static const int quality_samples[4] = { 6, 12, 12, 24 };
+ bokeh.push_constant.blur_scale = 0.5;
+ bokeh.push_constant.steps = quality_samples[p_quality];
+
+ RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
+
+ // Pass 1
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ // Pass 2
+ if (!bokeh.push_constant.half_size) {
+ // do not output weight, we're writing back into our base buffer
+ mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
+
+ shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+ }
+ bokeh.push_constant.second_pass = true;
+
+ framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb;
+ RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture;
+ RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ if (bokeh.push_constant.half_size) {
+ // Compose pass
+ mode = BOKEH_COMPOSITE;
+ shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ framebuffer = p_buffers.base_fb;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ } else {
+ // circular is a single pass approach
+ BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR;
+
+ RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ {
+ // circle always runs in half size, otherwise too expensive (though the code below does support making this optional)
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ // bokeh.push_constant.blur_size *= 0.5;
+ }
+
+ static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
+ bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.steps = 0.0;
+
+ RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ if (bokeh.push_constant.half_size) {
+ // Compose
+ mode = BOKEH_COMPOSITE;
+ shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ framebuffer = p_buffers.base_fb;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ } else {
+ CopyEffects::get_singleton()->copy_raster(p_buffers.secondary_texture, p_buffers.base_fb);
+ }
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
new file mode 100644
index 0000000000..d7b736119c
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -0,0 +1,120 @@
+/*************************************************************************/
+/* bokeh_dof.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BOKEH_DOF_RD_H
+#define BOKEH_DOF_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class BokehDOF {
+private:
+ bool prefer_raster_effects;
+
+ struct BokehPushConstant {
+ uint32_t size[2];
+ float z_far;
+ float z_near;
+
+ uint32_t orthogonal;
+ float blur_size;
+ float blur_scale;
+ uint32_t steps;
+
+ uint32_t blur_near_active;
+ float blur_near_begin;
+ float blur_near_end;
+ uint32_t blur_far_active;
+
+ float blur_far_begin;
+ float blur_far_end;
+ uint32_t second_pass;
+ uint32_t half_size;
+
+ uint32_t use_jitter;
+ float jitter_seed;
+ uint32_t pad[2];
+ };
+
+ enum BokehMode {
+ BOKEH_GEN_BLUR_SIZE,
+ BOKEH_GEN_BOKEH_BOX,
+ BOKEH_GEN_BOKEH_BOX_NOWEIGHT,
+ BOKEH_GEN_BOKEH_HEXAGONAL,
+ BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT,
+ BOKEH_GEN_BOKEH_CIRCULAR,
+ BOKEH_COMPOSITE,
+ BOKEH_MAX
+ };
+
+ struct Bokeh {
+ BokehPushConstant push_constant;
+ BokehDofShaderRD compute_shader;
+ BokehDofRasterShaderRD raster_shader;
+ RID shader_version;
+ RID compute_pipelines[BOKEH_MAX];
+ PipelineCacheRD raster_pipelines[BOKEH_MAX];
+ } bokeh;
+
+public:
+ struct BokehBuffers {
+ // bokeh buffers
+
+ // textures
+ Size2i base_texture_size;
+ RID base_texture;
+ RID depth_texture;
+ RID secondary_texture;
+ RID half_texture[2];
+
+ // raster only
+ RID base_fb;
+ RID secondary_fb; // with weights
+ RID half_fb[2]; // with weights
+ RID base_weight_fb;
+ RID weight_texture[4];
+ };
+
+ BokehDOF(bool p_prefer_raster_effects);
+ ~BokehDOF();
+
+ void bokeh_dof_compute(const BokehBuffers &p_buffers, 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, RS::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 bokeh_dof_raster(const BokehBuffers &p_buffers, 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_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+};
+
+} // namespace RendererRD
+
+#endif // !BOKEH_DOF_RD_H
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
new file mode 100644
index 0000000000..6b786fdf16
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -0,0 +1,683 @@
+/*************************************************************************/
+/* copy_effects.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "copy_effects.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+CopyEffects *CopyEffects::singleton = nullptr;
+
+CopyEffects *CopyEffects::get_singleton() {
+ return singleton;
+}
+
+CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
+ singleton = this;
+ prefer_raster_effects = p_prefer_raster_effects;
+
+ if (prefer_raster_effects) {
+ // init blur shader (on compute use copy shader)
+
+ Vector<String> blur_modes;
+ blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
+ blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
+
+ blur_raster.shader.initialize(blur_modes);
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+ blur_raster.shader_version = blur_raster.shader.version_create();
+
+ for (int i = 0; i < BLUR_MODE_MAX; i++) {
+ blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+
+ } else {
+ // not used in clustered
+ for (int i = 0; i < BLUR_MODE_MAX; i++) {
+ blur_raster.pipelines[i].clear();
+ }
+
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_MIPMAP\n");
+ copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
+ copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
+ copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n");
+
+ copy.shader.initialize(copy_modes);
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.shader_version = copy.shader.version_create();
+
+ for (int i = 0; i < COPY_MODE_MAX; i++) {
+ if (copy.shader.is_variant_enabled(i)) {
+ copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
+ }
+ }
+ }
+
+ {
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n");
+ copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
+ copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
+ copy_modes.push_back("\n#define MULTIVIEW\n");
+ copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
+
+ copy_to_fb.shader.initialize(copy_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false);
+ copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false);
+ }
+
+ copy_to_fb.shader_version = copy_to_fb.shader.version_create();
+
+ //use additive
+
+ for (int i = 0; i < COPY_TO_FB_MAX; i++) {
+ if (copy_to_fb.shader.is_variant_enabled(i)) {
+ copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ copy_to_fb.pipelines[i].clear();
+ }
+ }
+ }
+}
+
+CopyEffects::~CopyEffects() {
+ if (prefer_raster_effects) {
+ blur_raster.shader.version_free(blur_raster.shader_version);
+ } else {
+ copy.shader.version_free(copy.shader_version);
+ }
+
+ copy_to_fb.shader.version_free(copy_to_fb.shader_version);
+
+ singleton = nullptr;
+}
+
+void CopyEffects::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) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_rect shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ if (p_force_luminance) {
+ copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
+ }
+
+ if (p_all_source) {
+ copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
+ }
+
+ if (p_alpha_to_one) {
+ copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_cubemap_to_panorama shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_panorama_size.width;
+ copy.push_constant.section[3] = p_panorama_size.height;
+ copy.push_constant.target[0] = 0;
+ copy.push_constant.target[1] = 0;
+ copy.push_constant.camera_z_far = p_lod;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_cube(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cube }));
+ RD::Uniform u_dest_panorama(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_panorama);
+
+ CopyMode mode = p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cube), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_panorama), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = COPY_MODE_SIMPLY_COPY_DEPTH;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::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) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect_and_linearize shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+ copy.push_constant.camera_z_far = p_z_far;
+ copy.push_constant.camera_z_near = p_z_near;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = COPY_MODE_LINEARIZE_DEPTH;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::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) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
+ copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
+ copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
+ copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
+
+ if (p_flip_y) {
+ copy_to_fb.push_constant.flip_y = true;
+ }
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ CopyToFBMode mode = p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY;
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = p_draw_list;
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+}
+
+void CopyEffects::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, bool p_multiview) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ if (p_flip_y) {
+ copy_to_fb.push_constant.flip_y = true;
+ }
+ if (p_force_luminance) {
+ copy_to_fb.push_constant.force_luminance = true;
+ }
+ if (p_alpha_to_zero) {
+ copy_to_fb.push_constant.alpha_to_zero = true;
+ }
+ if (p_srgb) {
+ copy_to_fb.push_constant.srgb = true;
+ }
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ CopyToFBMode mode;
+ if (p_multiview) {
+ mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW;
+ } else {
+ mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY;
+ }
+
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ 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>(), 1.0, 0, p_rect);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ if (p_secondary.is_valid()) {
+ // TODO may need to do this differently when reading from depth buffer for multiview
+ RD::Uniform u_secondary(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_secondary }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_secondary), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the copy with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, BLUR_MODE_COPY);
+ ERR_FAIL_COND(shader.is_null());
+
+ // Just copy it back (we use our blur raster shader here)..
+ 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);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = p_region.position.x;
+ copy.push_constant.section[1] = p_region.position.y;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_texture);
+
+ CopyMode mode = p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ //HORIZONTAL
+ RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_texture), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::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_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
+ uint32_t base_flags = 0;
+
+ copy.push_constant.section[2] = p_size.x;
+ copy.push_constant.section[3] = p_size.y;
+
+ copy.push_constant.glow_strength = p_strength;
+ copy.push_constant.glow_bloom = p_bloom;
+ copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
+ copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+ copy.push_constant.glow_exposure = p_exposure;
+ copy.push_constant.glow_white = 0; //actually unused
+ copy.push_constant.glow_luminance_cap = p_luminance_cap;
+
+ copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_back_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_back_texture);
+
+ RID shader = copy.shader.version_get_shader(copy.shader_version, copy_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_back_texture), 3);
+ if (p_auto_exposure.is_valid() && p_first_pass) {
+ RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
+ }
+
+ copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, 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_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
+ uint32_t base_flags = 0;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ blur_raster.push_constant.glow_strength = p_strength;
+ blur_raster.push_constant.glow_bloom = p_bloom;
+ blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
+ blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+ blur_raster.push_constant.glow_exposure = p_exposure;
+ blur_raster.push_constant.glow_white = 0; //actually unused
+ blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
+
+ blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+
+ blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ //HORIZONTAL
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ if (p_auto_exposure.is_valid() && p_first_pass) {
+ RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
+
+ shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ //VERTICAL
+ 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);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ blur_raster.push_constant.flags = base_flags;
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the make_mipmap shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_size.width;
+ copy.push_constant.section[3] = p_size.height;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = COPY_MODE_MIPMAP;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode mode = BLUR_MIPMAP;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ 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);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the set_color shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+ copy.push_constant.target[0] = p_region.position.x;
+ copy.push_constant.target[1] = p_region.position.y;
+ copy.push_constant.set_color[0] = p_color.r;
+ copy.push_constant.set_color[1] = p_color.g;
+ copy.push_constant.set_color[2] = p_color.b;
+ copy.push_constant.set_color[3] = p_color.a;
+
+ // setup our uniforms
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
new file mode 100644
index 0000000000..e522408d20
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -0,0 +1,220 @@
+/*************************************************************************/
+/* copy_effects.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef COPY_RD_H
+#define COPY_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class CopyEffects {
+private:
+ bool prefer_raster_effects;
+
+ // Blur raster shader
+
+ enum BlurRasterMode {
+ BLUR_MIPMAP,
+
+ BLUR_MODE_GAUSSIAN_BLUR,
+ BLUR_MODE_GAUSSIAN_GLOW,
+ BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+ BLUR_MODE_COPY,
+
+ BLUR_MODE_MAX
+ };
+
+ enum {
+ BLUR_FLAG_HORIZONTAL = (1 << 0),
+ BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
+ BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
+ };
+
+ struct BlurRasterPushConstant {
+ float pixel_size[2];
+ uint32_t flags;
+ uint32_t pad;
+
+ //glow
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+
+ float luminance_multiplier;
+ float res1;
+ float res2;
+ float res3;
+ };
+
+ struct BlurRaster {
+ BlurRasterPushConstant push_constant;
+ BlurRasterShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[BLUR_MODE_MAX];
+ } blur_raster;
+
+ // Copy shader
+
+ enum CopyMode {
+ COPY_MODE_GAUSSIAN_COPY,
+ COPY_MODE_GAUSSIAN_COPY_8BIT,
+ COPY_MODE_GAUSSIAN_GLOW,
+ COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+ COPY_MODE_SIMPLY_COPY,
+ COPY_MODE_SIMPLY_COPY_8BIT,
+ COPY_MODE_SIMPLY_COPY_DEPTH,
+ COPY_MODE_SET_COLOR,
+ COPY_MODE_SET_COLOR_8BIT,
+ COPY_MODE_MIPMAP,
+ COPY_MODE_LINEARIZE_DEPTH,
+ COPY_MODE_CUBE_TO_PANORAMA,
+ COPY_MODE_CUBE_ARRAY_TO_PANORAMA,
+ COPY_MODE_MAX,
+
+ };
+
+ enum {
+ COPY_FLAG_HORIZONTAL = (1 << 0),
+ COPY_FLAG_USE_COPY_SECTION = (1 << 1),
+ COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
+ COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
+ COPY_FLAG_GLOW_FIRST_PASS = (1 << 4),
+ COPY_FLAG_FLIP_Y = (1 << 5),
+ COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
+ COPY_FLAG_ALL_SOURCE = (1 << 7),
+ COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
+ COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
+ };
+
+ struct CopyPushConstant {
+ int32_t section[4];
+ int32_t target[2];
+ uint32_t flags;
+ uint32_t pad;
+ // Glow.
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+ // DOF.
+ float camera_z_far;
+ float camera_z_near;
+ uint32_t pad2[2];
+ //SET color
+ float set_color[4];
+ };
+
+ struct Copy {
+ CopyPushConstant push_constant;
+ CopyShaderRD shader;
+ RID shader_version;
+ RID pipelines[COPY_MODE_MAX];
+
+ } copy;
+
+ // Copy to FB shader
+
+ enum CopyToFBMode {
+ COPY_TO_FB_COPY,
+ COPY_TO_FB_COPY_PANORAMA_TO_DP,
+ COPY_TO_FB_COPY2,
+
+ COPY_TO_FB_MULTIVIEW,
+ COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
+ COPY_TO_FB_MAX,
+ };
+
+ struct CopyToFbPushConstant {
+ float section[4];
+ float pixel_size[2];
+ uint32_t flip_y;
+ uint32_t use_section;
+
+ uint32_t force_luminance;
+ uint32_t alpha_to_zero;
+ uint32_t srgb;
+ uint32_t pad;
+ };
+
+ struct CopyToFb {
+ CopyToFbPushConstant push_constant;
+ CopyToFbShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[COPY_TO_FB_MAX];
+
+ } copy_to_fb;
+
+ static CopyEffects *singleton;
+
+public:
+ static CopyEffects *get_singleton();
+
+ CopyEffects(bool p_prefer_raster_effects);
+ ~CopyEffects();
+
+ void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
+ void 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 copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
+ void 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 copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
+ void 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 = false, bool p_panorama = false);
+ void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
+
+ void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+
+ void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
+ void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
+
+ void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
+};
+
+} // namespace RendererRD
+
+#endif // !COPY_RD_H
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
new file mode 100644
index 0000000000..38a4a37b8a
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -0,0 +1,257 @@
+/*************************************************************************/
+/* tone_mapper.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "tone_mapper.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+ToneMapper::ToneMapper() {
+ {
+ // Initialize tonemapper
+ 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_modes.push_back("\n#define SUBPASS\n");
+ tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
+
+ // multiview versions of our shaders
+ tonemap_modes.push_back("\n#define MULTIVIEW\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
+
+ tonemap.shader.initialize(tonemap_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_NORMAL_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW, false);
+ }
+
+ tonemap.shader_version = tonemap.shader.version_create();
+
+ for (int i = 0; i < TONEMAP_MODE_MAX; i++) {
+ if (tonemap.shader.is_variant_enabled(i)) {
+ tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ tonemap.pipelines[i].clear();
+ }
+ }
+ }
+}
+
+ToneMapper::~ToneMapper() {
+ tonemap.shader.version_free(tonemap.shader_version);
+}
+
+void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
+
+ tonemap.push_constant.use_bcs = p_settings.use_bcs;
+ tonemap.push_constant.bcs[0] = p_settings.brightness;
+ tonemap.push_constant.bcs[1] = p_settings.contrast;
+ tonemap.push_constant.bcs[2] = p_settings.saturation;
+
+ tonemap.push_constant.use_glow = p_settings.use_glow;
+ tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
+ tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength;
+ tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
+ tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1];
+ tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2];
+ tonemap.push_constant.glow_levels[3] = p_settings.glow_levels[3];
+ tonemap.push_constant.glow_levels[4] = p_settings.glow_levels[4];
+ tonemap.push_constant.glow_levels[5] = p_settings.glow_levels[5];
+ tonemap.push_constant.glow_levels[6] = p_settings.glow_levels[6];
+ tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x;
+ tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y;
+ tonemap.push_constant.glow_mode = p_settings.glow_mode;
+
+ 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;
+ tonemap.push_constant.exposure = p_settings.exposure;
+ tonemap.push_constant.white = p_settings.white;
+ tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
+
+ tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
+
+ tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
+ tonemap.push_constant.use_debanding = p_settings.use_debanding;
+ tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
+ tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
+
+ if (p_settings.view_count > 1) {
+ // Use MULTIVIEW versions
+ mode += 6;
+ }
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_color(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_color }));
+
+ RD::Uniform u_exposure_texture;
+ u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_exposure_texture.binding = 0;
+ u_exposure_texture.append_id(default_sampler);
+ u_exposure_texture.append_id(p_settings.exposure_texture);
+
+ RD::Uniform u_glow_texture;
+ u_glow_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_glow_texture.binding = 0;
+ u_glow_texture.append_id(default_mipmap_sampler);
+ u_glow_texture.append_id(p_settings.glow_texture);
+
+ RD::Uniform u_glow_map;
+ u_glow_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_glow_map.binding = 1;
+ u_glow_map.append_id(default_mipmap_sampler);
+ u_glow_map.append_id(p_settings.glow_map);
+
+ RD::Uniform u_color_correction_texture;
+ u_color_correction_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_color_correction_texture.binding = 0;
+ u_color_correction_texture.append_id(default_sampler);
+ u_color_correction_texture.append_id(p_settings.color_correction_texture);
+
+ RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
+
+ tonemap.push_constant.use_bcs = p_settings.use_bcs;
+ tonemap.push_constant.bcs[0] = p_settings.brightness;
+ tonemap.push_constant.bcs[1] = p_settings.contrast;
+ tonemap.push_constant.bcs[2] = p_settings.saturation;
+
+ ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
+ tonemap.push_constant.use_glow = p_settings.use_glow;
+
+ int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
+ if (p_settings.view_count > 1) {
+ // Use MULTIVIEW versions
+ mode += 6;
+ }
+
+ tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
+ tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
+ tonemap.push_constant.exposure = p_settings.exposure;
+ tonemap.push_constant.white = p_settings.white;
+ tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+
+ tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
+
+ tonemap.push_constant.use_debanding = p_settings.use_debanding;
+ tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_color;
+ u_source_color.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT;
+ u_source_color.binding = 0;
+ u_source_color.append_id(p_source_color);
+
+ RD::Uniform u_exposure_texture;
+ u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_exposure_texture.binding = 0;
+ u_exposure_texture.append_id(default_sampler);
+ u_exposure_texture.append_id(p_settings.exposure_texture);
+
+ RD::Uniform u_glow_texture;
+ u_glow_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_glow_texture.binding = 0;
+ u_glow_texture.append_id(default_mipmap_sampler);
+ u_glow_texture.append_id(p_settings.glow_texture);
+
+ RD::Uniform u_glow_map;
+ u_glow_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_glow_map.binding = 1;
+ u_glow_map.append_id(default_mipmap_sampler);
+ u_glow_map.append_id(p_settings.glow_map);
+
+ RD::Uniform u_color_correction_texture;
+ u_color_correction_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_color_correction_texture.binding = 0;
+ u_color_correction_texture.append_id(default_sampler);
+ u_color_correction_texture.append_id(p_settings.color_correction_texture);
+
+ RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); // should be set to a default texture, it's ignored
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); // should be set to a default texture, it's ignored
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
+ RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
+ RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
+}
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
new file mode 100644
index 0000000000..a90849dbeb
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -0,0 +1,152 @@
+/*************************************************************************/
+/* tone_mapper.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TONE_MAPPER_RD_H
+#define TONE_MAPPER_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/tonemap.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class ToneMapper {
+private:
+ enum TonemapMode {
+ TONEMAP_MODE_NORMAL,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER,
+ TONEMAP_MODE_1D_LUT,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
+ TONEMAP_MODE_SUBPASS,
+ TONEMAP_MODE_SUBPASS_1D_LUT,
+
+ TONEMAP_MODE_NORMAL_MULTIVIEW,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
+ TONEMAP_MODE_1D_LUT_MULTIVIEW,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
+ TONEMAP_MODE_SUBPASS_MULTIVIEW,
+ TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW,
+
+ TONEMAP_MODE_MAX
+ };
+
+ struct TonemapPushConstant {
+ float bcs[3]; // 12 - 12
+ uint32_t use_bcs; // 4 - 16
+
+ uint32_t use_glow; // 4 - 20
+ uint32_t use_auto_exposure; // 4 - 24
+ uint32_t use_color_correction; // 4 - 28
+ uint32_t tonemapper; // 4 - 32
+
+ uint32_t glow_texture_size[2]; // 8 - 40
+ float glow_intensity; // 4 - 44
+ float glow_map_strength; // 4 - 48
+
+ uint32_t glow_mode; // 4 - 52
+ float glow_levels[7]; // 28 - 80
+
+ float exposure; // 4 - 84
+ float white; // 4 - 88
+ float auto_exposure_grey; // 4 - 92
+ float luminance_multiplier; // 4 - 96
+
+ float pixel_size[2]; // 8 - 104
+ uint32_t use_fxaa; // 4 - 108
+ uint32_t use_debanding; // 4 - 112
+ };
+
+ /* tonemap actually writes to a framebuffer, which is
+ * better to do using the raster pipeline rather than
+ * compute, as that framebuffer might be in different formats
+ */
+ struct Tonemap {
+ TonemapPushConstant push_constant;
+ TonemapShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[TONEMAP_MODE_MAX];
+ } tonemap;
+
+public:
+ ToneMapper();
+ ~ToneMapper();
+
+ struct TonemapSettings {
+ bool use_glow = false;
+ enum GlowMode {
+ GLOW_MODE_ADD,
+ GLOW_MODE_SCREEN,
+ GLOW_MODE_SOFTLIGHT,
+ GLOW_MODE_REPLACE,
+ GLOW_MODE_MIX
+ };
+
+ GlowMode glow_mode = GLOW_MODE_ADD;
+ float glow_intensity = 1.0;
+ float glow_map_strength = 0.0f;
+ float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
+ Vector2i glow_texture_size;
+ bool glow_use_bicubic_upscale = false;
+ RID glow_texture;
+ RID glow_map;
+
+ RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
+ float exposure = 1.0;
+ float white = 1.0;
+
+ bool use_auto_exposure = false;
+ float auto_exposure_grey = 0.5;
+ RID exposure_texture;
+ float luminance_multiplier = 1.0;
+
+ bool use_bcs = false;
+ float brightness = 1.0;
+ float contrast = 1.0;
+ float saturation = 1.0;
+
+ bool use_color_correction = false;
+ bool use_1d_color_correction = false;
+ RID color_correction_texture;
+
+ bool use_fxaa = false;
+ bool use_debanding = false;
+ Vector2i texture_size;
+ uint32_t view_count = 1;
+ };
+
+ void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
+ void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
+};
+
+} // namespace RendererRD
+
+#endif // !TONE_MAPPER_RD_H
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index fe3863fec7..bf97c6fbe9 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -60,7 +60,7 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 0;
- u.ids.push_back(p_image);
+ u.append_id(p_image);
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, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1);
@@ -70,28 +70,6 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
return uniform_set;
}
-RID EffectsRD::_get_uniform_set_for_input(RID p_texture) {
- if (input_to_uniform_set_cache.has(p_texture)) {
- RID uniform_set = input_to_uniform_set_cache[p_texture];
- 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_INPUT_ATTACHMENT;
- u.binding = 0;
- u.ids.push_back(p_texture);
- uniforms.push_back(u);
- // This is specific to our subpass shader
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, TONEMAP_MODE_SUBPASS), 0);
-
- input_to_uniform_set_cache[p_texture] = uniform_set;
-
- return uniform_set;
-}
-
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];
@@ -104,54 +82,17 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
RD::Uniform u;
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);
+ u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.append_id(p_texture);
uniforms.push_back(u);
// 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);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
return uniform_set;
}
-RID EffectsRD::_get_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;
-
- if (texture_pair_to_uniform_set_cache.has(tp)) {
- RID uniform_set = texture_pair_to_uniform_set_cache[tp];
- 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_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.ids.push_back(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- 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);
- uniforms.push_back(u);
- }
- // 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), 2);
-
- texture_pair_to_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
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];
@@ -164,8 +105,8 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
RD::Uniform u;
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);
+ u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.append_id(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, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0);
@@ -191,8 +132,8 @@ RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture,
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);
+ u.append_id(p_sampler);
+ u.append_id(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);
@@ -219,16 +160,16 @@ RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_
RD::Uniform u;
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);
+ u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.append_id(p_texture1);
uniforms.push_back(u);
}
{
RD::Uniform u;
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);
+ u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.append_id(p_texture2);
uniforms.push_back(u);
}
//any thing with the same configuration (one texture in binding 0 for set 0), is good
@@ -256,14 +197,14 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 0;
- u.ids.push_back(p_texture1);
+ u.append_id(p_texture1);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(p_texture2);
+ u.append_id(p_texture2);
uniforms.push_back(u);
}
//any thing with the same configuration (one texture in binding 0 for set 0), is good
@@ -311,295 +252,35 @@ void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RI
RD::get_singleton()->compute_list_end(compute_list);
}
-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) {
- memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
-
- copy_to_fb.push_constant.use_section = true;
- copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
- copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
- copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
- copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
-
- if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
- }
-
- RD::DrawListID draw_list = p_draw_list;
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
-}
-
-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, bool p_multiview) {
- memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
-
- if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
- }
- if (p_force_luminance) {
- copy_to_fb.push_constant.force_luminance = true;
- }
- if (p_alpha_to_zero) {
- copy_to_fb.push_constant.alpha_to_zero = true;
- }
- if (p_srgb) {
- copy_to_fb.push_constant.srgb = true;
- }
-
- CopyToFBMode mode;
- if (p_multiview) {
- mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW;
- } else {
- mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY;
- }
-
- 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>(), 1.0, 0, p_rect);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- if (p_secondary.is_valid()) {
- // TODO may need to do this differently when reading from depth buffer for multiview
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1);
- }
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-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) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
- if (p_flip_y) {
- copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
- }
-
- if (p_force_luminance) {
- copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
- }
-
- if (p_all_source) {
- copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
- }
-
- if (p_alpha_to_one) {
- copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
- }
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_rect.size.width;
- copy.push_constant.section[3] = p_rect.size.height;
- copy.push_constant.target[0] = p_rect.position.x;
- copy.push_constant.target[1] = p_rect.position.y;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-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) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_panorama_size.width;
- copy.push_constant.section[3] = p_panorama_size.height;
- copy.push_constant.target[0] = 0;
- copy.push_constant.target[1] = 0;
- copy.push_constant.camera_z_far = p_lod;
+ RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-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) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
- if (p_flip_y) {
- copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
- }
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_rect.size.width;
- copy.push_constant.section[3] = p_rect.size.height;
- copy.push_constant.target[0] = p_rect.position.x;
- copy.push_constant.target[1] = p_rect.position.y;
- copy.push_constant.camera_z_far = p_z_far;
- copy.push_constant.camera_z_near = p_z_near;
+ memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant));
+ TAA_resolve.push_constant.resolution_width = p_resolution.width;
+ TAA_resolve.push_constant.resolution_height = p_resolution.height;
+ TAA_resolve.push_constant.disocclusion_threshold = 0.025f;
+ TAA_resolve.push_constant.disocclusion_scale = 10.0f;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline);
+
+ RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
+ RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
+ RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
+ RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
+ RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
- if (p_flip_y) {
- copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
- }
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_rect.size.width;
- copy.push_constant.section[3] = p_rect.size.height;
- copy.push_constant.target[0] = p_rect.position.x;
- copy.push_constant.target[1] = p_rect.position.y;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_region.size.width;
- copy.push_constant.section[3] = p_region.size.height;
- copy.push_constant.target[0] = p_region.position.x;
- copy.push_constant.target[1] = p_region.position.y;
- copy.push_constant.set_color[0] = p_color.r;
- copy.push_constant.set_color[1] = p_color.g;
- copy.push_constant.set_color[2] = p_color.b;
- copy.push_constant.set_color[3] = p_color.a;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
-
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = p_region.position.x;
- copy.push_constant.section[1] = p_region.position.y;
- copy.push_constant.section[2] = p_region.size.width;
- copy.push_constant.section[3] = p_region.size.height;
-
- //HORIZONTAL
- RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-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_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
-
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
- uint32_t base_flags = 0;
-
- copy.push_constant.section[2] = p_size.x;
- copy.push_constant.section[3] = p_size.y;
-
- copy.push_constant.glow_strength = p_strength;
- copy.push_constant.glow_bloom = p_bloom;
- copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
- copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
- copy.push_constant.glow_exposure = p_exposure;
- copy.push_constant.glow_white = 0; //actually unused
- copy.push_constant.glow_luminance_cap = p_luminance_cap;
-
- copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
- if (p_auto_exposure.is_valid() && p_first_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1);
- }
-
- copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_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_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
-
- BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
- uint32_t base_flags = 0;
-
- blur_raster.push_constant.pixel_size[0] = p_pixel_size.x;
- blur_raster.push_constant.pixel_size[1] = p_pixel_size.y;
-
- blur_raster.push_constant.glow_strength = p_strength;
- blur_raster.push_constant.glow_bloom = p_bloom;
- blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
- blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
- blur_raster.push_constant.glow_exposure = p_exposure;
- blur_raster.push_constant.glow_white = 0; //actually unused
- blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
-
- blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
-
- //HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- if (p_auto_exposure.is_valid() && p_first_pass) {
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
- }
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
-
- //VERTICAL
- 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);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- blur_raster.push_constant.flags = base_flags;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
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();
@@ -763,7 +444,7 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept
}
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>());
+ 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_READ, Vector<Color>());
if (p_reflection.is_valid()) {
if (p_base.is_valid()) {
@@ -792,43 +473,6 @@ void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_bas
RD::get_singleton()->draw_list_end();
}
-void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_size.width;
- copy.push_constant.section[3] = p_size.height;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
-
- BlurRasterMode mode = BLUR_MIPMAP;
-
- blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
- blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
-
- 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);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
CopyToDPPushConstant push_constant;
push_constant.screen_rect[0] = p_rect.position.x;
@@ -851,105 +495,6 @@ void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffe
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
}
-void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
- memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
-
- tonemap.push_constant.use_bcs = p_settings.use_bcs;
- tonemap.push_constant.bcs[0] = p_settings.brightness;
- tonemap.push_constant.bcs[1] = p_settings.contrast;
- tonemap.push_constant.bcs[2] = p_settings.saturation;
-
- tonemap.push_constant.use_glow = p_settings.use_glow;
- tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
- tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength;
- tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
- tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1];
- tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2];
- tonemap.push_constant.glow_levels[3] = p_settings.glow_levels[3];
- tonemap.push_constant.glow_levels[4] = p_settings.glow_levels[4];
- tonemap.push_constant.glow_levels[5] = p_settings.glow_levels[5];
- tonemap.push_constant.glow_levels[6] = p_settings.glow_levels[6];
- tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x;
- tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y;
- tonemap.push_constant.glow_mode = p_settings.glow_mode;
-
- 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;
- tonemap.push_constant.exposure = p_settings.exposure;
- tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
- tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
-
- tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
-
- tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
- tonemap.push_constant.use_debanding = p_settings.use_debanding;
- tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
- tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
-
- if (p_settings.view_count > 1) {
- // Use MULTIVIEW versions
- mode += 6;
- }
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings) {
- memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
-
- tonemap.push_constant.use_bcs = p_settings.use_bcs;
- tonemap.push_constant.bcs[0] = p_settings.brightness;
- tonemap.push_constant.bcs[1] = p_settings.contrast;
- tonemap.push_constant.bcs[2] = p_settings.saturation;
-
- ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
- tonemap.push_constant.use_glow = p_settings.use_glow;
-
- int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
- if (p_settings.view_count > 1) {
- // Use MULTIVIEW versions
- mode += 6;
- }
-
- tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
- tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
- tonemap.push_constant.exposure = p_settings.exposure;
- tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
-
- tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
-
- tonemap.push_constant.use_debanding = p_settings.use_debanding;
- tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
-
- RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
- RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); // should be set to a default texture, it's ignored
- RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2); // should be set to a default texture, it's ignored
- RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
-
- RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
- RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
-}
-
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) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
@@ -1023,332 +568,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
}
}
-void EffectsRD::bokeh_dof(const BokehBuffers &p_buffers, 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) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer.");
-
- 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;
-
- bokeh.push_constant.blur_near_active = p_dof_near;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
- bokeh.push_constant.use_jitter = p_use_jitter;
- bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
-
- bokeh.push_constant.z_near = p_cam_znear;
- bokeh.push_constant.z_far = p_cam_zfar;
- bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.blur_size = p_bokeh_size;
-
- bokeh.push_constant.second_pass = false;
- bokeh.push_constant.half_size = false;
-
- bokeh.push_constant.blur_scale = 0.5;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- /* FIRST PASS */
- // The alpha channel of the source color texture is filled with the expected circle size
- // If used for DOF far, the size is positive, if used for near, its negative.
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.depth_texture), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
- //second pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
-
- static const int quality_samples[4] = { 6, 12, 12, 24 };
-
- bokeh.push_constant.steps = quality_samples[p_quality];
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
- bokeh.push_constant.blur_size *= 0.5;
-
- } else {
- //medium and high quality use full size
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.secondary_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //third pass
- bokeh.push_constant.second_pass = true;
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[1]), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.secondary_texture), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- //forth pass, upscale for low quality
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[1]), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
- bokeh.push_constant.half_size = false;
- bokeh.push_constant.second_pass = false;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
- }
- } else {
- //circle
-
- //second pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
-
- static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
-
- bokeh.push_constant.steps = 0;
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
-
- //circle always runs in half size, otherwise too expensive
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //circle is just one pass, then upscale
-
- // upscale
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
- bokeh.push_constant.half_size = false;
- bokeh.push_constant.second_pass = false;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, 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_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer.");
-
- memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
-
- bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.width;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.height;
- bokeh.push_constant.z_far = p_cam_zfar;
- bokeh.push_constant.z_near = p_cam_znear;
-
- bokeh.push_constant.second_pass = false;
- bokeh.push_constant.half_size = false;
- bokeh.push_constant.blur_size = p_dof_blur_amount;
-
- if (p_dof_far || p_dof_near) {
- if (p_dof_far) {
- bokeh.push_constant.blur_far_active = true;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
- }
-
- if (p_dof_near) {
- bokeh.push_constant.blur_near_active = true;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
- }
-
- {
- // generate our depth data
- RID framebuffer = p_buffers.base_weight_fb;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.depth_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
-
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
- // double pass approach
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
- bokeh.push_constant.blur_size *= 0.5;
- }
-
- static const int quality_samples[4] = { 6, 12, 12, 24 };
- bokeh.push_constant.blur_scale = 0.5;
- bokeh.push_constant.steps = quality_samples[p_quality];
-
- RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
-
- // Pass 1
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- // Pass 2
- if (!bokeh.push_constant.half_size) {
- // do not output weight, we're writing back into our base buffer
- mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
- }
- bokeh.push_constant.second_pass = true;
-
- framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb;
- RID texture = bokeh.push_constant.half_size ? p_buffers.half_texture[0] : p_buffers.secondary_texture;
- RID weight = bokeh.push_constant.half_size ? p_buffers.weight_texture[2] : p_buffers.weight_texture[1];
-
- draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(weight), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- if (bokeh.push_constant.half_size) {
- // Compose pass
- mode = BOKEH_COMPOSITE;
- framebuffer = p_buffers.base_fb;
-
- draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[1]), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[3]), 1);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
-
- } else {
- // circular is a single pass approach
- BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR;
-
- {
- // circle always runs in half size, otherwise too expensive (though the code below does support making this optional)
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
- // bokeh.push_constant.blur_size *= 0.5;
- }
-
- static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
- bokeh.push_constant.steps = 0.0;
-
- RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- if (bokeh.push_constant.half_size) {
- // Compose
- mode = BOKEH_COMPOSITE;
- framebuffer = p_buffers.base_fb;
-
- draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[0]), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[2]), 1);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- } else {
- // Just copy it back (we use our blur raster shader here)..
- draw_list = RD::get_singleton()->draw_list_begin(p_buffers.base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_buffers.base_fb)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.secondary_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
- }
- }
-}
-
void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) {
// Downsample and deinterleave the depth buffer for SSAO and SSIL
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -1389,28 +608,28 @@ void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 0;
- u.ids.push_back(p_depth_mipmaps[depth_index + 1]);
+ u.append_id(p_depth_mipmaps[depth_index + 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[depth_index + 2]);
+ u.append_id(p_depth_mipmaps[depth_index + 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[depth_index + 3]);
+ u.append_id(p_depth_mipmaps[depth_index + 3]);
uniforms.push_back(u);
}
if (use_full_mips) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 3;
- u.ids.push_back(p_depth_mipmaps[4]);
+ u.append_id(p_depth_mipmaps[4]);
uniforms.push_back(u);
}
ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
@@ -1537,22 +756,22 @@ void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.ids.push_back(default_sampler);
- u.ids.push_back(p_depth_mipmaps_texture);
+ u.append_id(default_sampler);
+ u.append_id(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);
+ u.append_id(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(ss_effects.gather_constants_buffer);
+ u.append_id(ss_effects.gather_constants_buffer);
uniforms.push_back(u);
}
r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
@@ -1564,22 +783,22 @@ void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 0;
- u.ids.push_back(p_ao_pong);
+ u.append_id(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);
+ u.append_id(default_sampler);
+ u.append_id(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);
+ u.append_id(ssao.importance_map_load_counter);
uniforms.push_back(u);
}
r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
@@ -1811,15 +1030,15 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.ids.push_back(default_mipmap_sampler);
- u.ids.push_back(p_diffuse);
+ u.append_id(default_mipmap_sampler);
+ u.append_id(p_diffuse);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 1;
- u.ids.push_back(ssil.projection_uniform_buffer);
+ u.append_id(ssil.projection_uniform_buffer);
uniforms.push_back(u);
}
r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
@@ -1831,22 +1050,22 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.ids.push_back(default_sampler);
- u.ids.push_back(p_depth_mipmaps_texture);
+ u.append_id(default_sampler);
+ u.append_id(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);
+ u.append_id(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(ss_effects.gather_constants_buffer);
+ u.append_id(ss_effects.gather_constants_buffer);
uniforms.push_back(u);
}
r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
@@ -1858,22 +1077,22 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 0;
- u.ids.push_back(p_ssil_pong);
+ u.append_id(p_ssil_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);
+ u.append_id(default_sampler);
+ u.append_id(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(ssil.importance_map_load_counter);
+ u.append_id(ssil.importance_map_load_counter);
uniforms.push_back(u);
}
r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
@@ -2131,7 +1350,7 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = i;
- u.ids.push_back(p_dest_cubemap[i]);
+ u.append_id(p_dest_cubemap[i]);
uniforms.push_back(u);
}
if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
@@ -2310,94 +1529,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
prefer_raster_effects = p_prefer_raster_effects;
- if (prefer_raster_effects) {
- // init blur shader (on compute use copy shader)
-
- Vector<String> blur_modes;
- blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP
- blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
- blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
- blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
- blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
-
- blur_raster.shader.initialize(blur_modes);
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
- blur_raster.shader_version = blur_raster.shader.version_create();
-
- for (int i = 0; i < BLUR_MODE_MAX; i++) {
- blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- }
-
- } else {
- // not used in clustered
- for (int i = 0; i < BLUR_MODE_MAX; i++) {
- blur_raster.pipelines[i].clear();
- }
- }
-
- if (!prefer_raster_effects) { // Initialize copy
- Vector<String> copy_modes;
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n");
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
- copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
- copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
- copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
- copy_modes.push_back("\n#define MODE_SET_COLOR\n");
- copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
- copy_modes.push_back("\n#define MODE_MIPMAP\n");
- copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
- copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
- copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n");
-
- copy.shader.initialize(copy_modes);
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- if (prefer_raster_effects) {
- // disable shaders we can't use
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY, false);
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY_8BIT, false);
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW, false);
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, false);
- }
-
- copy.shader_version = copy.shader.version_create();
-
- for (int i = 0; i < COPY_MODE_MAX; i++) {
- if (copy.shader.is_variant_enabled(i)) {
- copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
- }
- }
- }
- {
- Vector<String> copy_modes;
- copy_modes.push_back("\n");
- copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
- copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
- copy_modes.push_back("\n#define MULTIVIEW\n");
- copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
-
- copy_to_fb.shader.initialize(copy_modes);
-
- if (!RendererCompositorRD::singleton->is_xr_enabled()) {
- copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false);
- copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false);
- }
-
- copy_to_fb.shader_version = copy_to_fb.shader.version_create();
-
- //use additive
-
- for (int i = 0; i < COPY_TO_FB_MAX; i++) {
- if (copy_to_fb.shader.is_variant_enabled(i)) {
- copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- } else {
- copy_to_fb.pipelines[i].clear();
- }
- }
- }
-
{
// Initialize roughness
Vector<String> cubemap_roughness_modes;
@@ -2420,46 +1551,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
}
- {
- // Initialize tonemapper
- 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_modes.push_back("\n#define SUBPASS\n");
- tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
-
- // multiview versions of our shaders
- tonemap_modes.push_back("\n#define MULTIVIEW\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
- tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
-
- tonemap.shader.initialize(tonemap_modes);
-
- if (!RendererCompositorRD::singleton->is_xr_enabled()) {
- tonemap.shader.set_variant_enabled(TONEMAP_MODE_NORMAL_MULTIVIEW, false);
- tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
- tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
- tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
- tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_MULTIVIEW, false);
- tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW, false);
- }
-
- tonemap.shader_version = tonemap.shader.version_create();
-
- for (int i = 0; i < TONEMAP_MODE_MAX; i++) {
- if (tonemap.shader.is_variant_enabled(i)) {
- tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- } else {
- tonemap.pipelines[i].clear();
- }
- }
- }
-
if (prefer_raster_effects) {
Vector<String> luminance_reduce_modes;
luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
@@ -2509,42 +1600,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
}
- // Initialize bokeh
- Vector<String> bokeh_modes;
- bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n");
- bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
- if (prefer_raster_effects) {
- bokeh.raster_shader.initialize(bokeh_modes);
-
- bokeh.shader_version = bokeh.raster_shader.version_create();
-
- const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 };
- for (int i = 0; i < BOKEH_MAX; i++) {
- RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]);
- bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- } else {
- bokeh.compute_shader.initialize(bokeh_modes);
- bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false);
- bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false);
- bokeh.shader_version = bokeh.compute_shader.version_create();
-
- for (int i = 0; i < BOKEH_MAX; i++) {
- if (bokeh.compute_shader.is_variant_enabled(i)) {
- bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
- }
- }
-
- for (int i = 0; i < BOKEH_MAX; i++) {
- bokeh.raster_pipelines[i].clear();
- }
- }
-
if (!prefer_raster_effects) {
{
// Initialize depth buffer for screen space effects
@@ -2651,7 +1706,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.ids.push_back(ssao.importance_map_load_counter);
+ u.append_id(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);
@@ -2766,7 +1821,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.ids.push_back(filter.coefficient_buffer);
+ u.append_id(filter.coefficient_buffer);
uniforms.push_back(u);
}
filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
@@ -2784,7 +1839,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.ids.push_back(filter.coefficient_buffer);
+ u.append_id(filter.coefficient_buffer);
uniforms.push_back(u);
}
filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
@@ -2921,7 +1976,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.ids.push_back(ssil.importance_map_load_counter);
+ u.append_id(ssil.importance_map_load_counter);
uniforms.push_back(u);
}
ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
@@ -2986,6 +2041,14 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
}
+ {
+ Vector<String> taa_modes;
+ taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
+ TAA_resolve.shader.initialize(taa_modes);
+ TAA_resolve.shader_version = TAA_resolve.shader.version_create();
+ TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0));
+ }
+
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
@@ -3034,22 +2097,19 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(filter.coefficient_buffer);
FSR_upscale.shader.version_free(FSR_upscale.shader_version);
+ TAA_resolve.shader.version_free(TAA_resolve.shader_version);
if (prefer_raster_effects) {
- blur_raster.shader.version_free(blur_raster.shader_version);
- bokeh.raster_shader.version_free(blur_raster.shader_version);
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
roughness.raster_shader.version_free(roughness.shader_version);
cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
filter.raster_shader.version_free(filter.shader_version);
} else {
- bokeh.compute_shader.version_free(bokeh.shader_version);
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
roughness.compute_shader.version_free(roughness.shader_version);
cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
filter.compute_shader.version_free(filter.shader_version);
}
if (!prefer_raster_effects) {
- copy.shader.version_free(copy.shader_version);
resolve.shader.version_free(resolve.shader_version);
specular_merge.shader.version_free(specular_merge.shader_version);
ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
@@ -3073,8 +2133,6 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(ssil.importance_map_load_counter);
RD::get_singleton()->free(ssil.projection_uniform_buffer);
}
- copy_to_fb.shader.version_free(copy_to_fb.shader_version);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
sort.shader.version_free(sort.shader_version);
- tonemap.shader.version_free(tonemap.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index eca5e09800..787873642e 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -33,11 +33,6 @@
#include "core/math/camera_matrix.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/bokeh_dof_raster.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_downsampler_raster.glsl.gen.h"
@@ -65,7 +60,7 @@
#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/ssil_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/renderer_rd/shaders/taa_resolve.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -96,139 +91,19 @@ private:
RID pipeline;
} FSR_upscale;
- enum BlurRasterMode {
- BLUR_MIPMAP,
-
- BLUR_MODE_GAUSSIAN_BLUR,
- BLUR_MODE_GAUSSIAN_GLOW,
- BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
- BLUR_MODE_COPY,
-
- BLUR_MODE_MAX
- };
-
- enum {
- BLUR_FLAG_HORIZONTAL = (1 << 0),
- BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
- BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
- };
-
- struct BlurRasterPushConstant {
- float pixel_size[2];
- uint32_t flags;
- uint32_t pad;
-
- //glow
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
-
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
- };
-
- struct BlurRaster {
- BlurRasterPushConstant push_constant;
- BlurRasterShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[BLUR_MODE_MAX];
- } blur_raster;
-
- enum CopyMode {
- COPY_MODE_GAUSSIAN_COPY,
- COPY_MODE_GAUSSIAN_COPY_8BIT,
- COPY_MODE_GAUSSIAN_GLOW,
- COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
- COPY_MODE_SIMPLY_COPY,
- COPY_MODE_SIMPLY_COPY_8BIT,
- COPY_MODE_SIMPLY_COPY_DEPTH,
- COPY_MODE_SET_COLOR,
- COPY_MODE_SET_COLOR_8BIT,
- COPY_MODE_MIPMAP,
- COPY_MODE_LINEARIZE_DEPTH,
- COPY_MODE_CUBE_TO_PANORAMA,
- COPY_MODE_CUBE_ARRAY_TO_PANORAMA,
- COPY_MODE_MAX,
-
- };
-
- enum {
- COPY_FLAG_HORIZONTAL = (1 << 0),
- COPY_FLAG_USE_COPY_SECTION = (1 << 1),
- COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
- COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
- COPY_FLAG_GLOW_FIRST_PASS = (1 << 4),
- COPY_FLAG_FLIP_Y = (1 << 5),
- COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
- COPY_FLAG_ALL_SOURCE = (1 << 7),
- COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
- COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
- };
-
- struct CopyPushConstant {
- int32_t section[4];
- int32_t target[2];
- uint32_t flags;
- uint32_t pad;
- // Glow.
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
-
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
- // DOF.
- float camera_z_far;
- float camera_z_near;
- uint32_t pad2[2];
- //SET color
- float set_color[4];
- };
-
- struct Copy {
- CopyPushConstant push_constant;
- CopyShaderRD shader;
- RID shader_version;
- RID pipelines[COPY_MODE_MAX];
-
- } copy;
-
- enum CopyToFBMode {
- COPY_TO_FB_COPY,
- COPY_TO_FB_COPY_PANORAMA_TO_DP,
- COPY_TO_FB_COPY2,
-
- COPY_TO_FB_MULTIVIEW,
- COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
- COPY_TO_FB_MAX,
-
- };
-
- struct CopyToFbPushConstant {
- float section[4];
- float pixel_size[2];
- uint32_t flip_y;
- uint32_t use_section;
-
- uint32_t force_luminance;
- uint32_t alpha_to_zero;
- uint32_t srgb;
- uint32_t pad;
+ struct TAAResolvePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float disocclusion_threshold;
+ float disocclusion_scale;
};
- struct CopyToFb {
- CopyToFbPushConstant push_constant;
- CopyToFbShaderRD shader;
+ struct TAAResolve {
+ TAAResolvePushConstant push_constant;
+ TaaResolveShaderRD shader;
RID shader_version;
- PipelineCacheRD pipelines[COPY_TO_FB_MAX];
-
- } copy_to_fb;
+ RID pipeline;
+ } TAA_resolve;
struct CubemapRoughnessPushConstant {
uint32_t face_id;
@@ -248,61 +123,6 @@ private:
PipelineCacheRD raster_pipeline;
} roughness;
- enum TonemapMode {
- TONEMAP_MODE_NORMAL,
- TONEMAP_MODE_BICUBIC_GLOW_FILTER,
- TONEMAP_MODE_1D_LUT,
- TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
- TONEMAP_MODE_SUBPASS,
- TONEMAP_MODE_SUBPASS_1D_LUT,
-
- TONEMAP_MODE_NORMAL_MULTIVIEW,
- TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
- TONEMAP_MODE_1D_LUT_MULTIVIEW,
- TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
- TONEMAP_MODE_SUBPASS_MULTIVIEW,
- TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW,
-
- TONEMAP_MODE_MAX
- };
-
- struct TonemapPushConstant {
- float bcs[3]; // 12 - 12
- uint32_t use_bcs; // 4 - 16
-
- uint32_t use_glow; // 4 - 20
- uint32_t use_auto_exposure; // 4 - 24
- uint32_t use_color_correction; // 4 - 28
- uint32_t tonemapper; // 4 - 32
-
- uint32_t glow_texture_size[2]; // 8 - 40
- float glow_intensity; // 4 - 44
- float glow_map_strength; // 4 - 48
-
- uint32_t glow_mode; // 4 - 52
- float glow_levels[7]; // 28 - 80
-
- float exposure; // 4 - 84
- float white; // 4 - 88
- float auto_exposure_grey; // 4 - 92
- float luminance_multiplier; // 4 - 96
-
- float pixel_size[2]; // 8 - 104
- uint32_t use_fxaa; // 4 - 108
- uint32_t use_debanding; // 4 - 112
- };
-
- /* tonemap actually writes to a framebuffer, which is
- * better to do using the raster pipeline rather than
- * compute, as that framebuffer might be in different formats
- */
- struct Tonemap {
- TonemapPushConstant push_constant;
- TonemapShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[TONEMAP_MODE_MAX];
- } tonemap;
-
enum LuminanceReduceMode {
LUMINANCE_REDUCE_READ,
LUMINANCE_REDUCE,
@@ -361,51 +181,6 @@ private:
PipelineCacheRD pipeline;
} cube_to_dp;
- struct BokehPushConstant {
- uint32_t size[2];
- float z_far;
- float z_near;
-
- uint32_t orthogonal;
- float blur_size;
- float blur_scale;
- uint32_t steps;
-
- uint32_t blur_near_active;
- float blur_near_begin;
- float blur_near_end;
- uint32_t blur_far_active;
-
- float blur_far_begin;
- float blur_far_end;
- uint32_t second_pass;
- uint32_t half_size;
-
- uint32_t use_jitter;
- float jitter_seed;
- uint32_t pad[2];
- };
-
- enum BokehMode {
- BOKEH_GEN_BLUR_SIZE,
- BOKEH_GEN_BOKEH_BOX,
- BOKEH_GEN_BOKEH_BOX_NOWEIGHT,
- BOKEH_GEN_BOKEH_HEXAGONAL,
- BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT,
- BOKEH_GEN_BOKEH_CIRCULAR,
- BOKEH_COMPOSITE,
- BOKEH_MAX
- };
-
- struct Bokeh {
- BokehPushConstant push_constant;
- BokehDofShaderRD compute_shader;
- BokehDofRasterShaderRD raster_shader;
- RID shader_version;
- RID compute_pipelines[BOKEH_MAX];
- PipelineCacheRD raster_pipelines[BOKEH_MAX];
- } bokeh;
-
struct SSEffectsDownsamplePushConstant {
float pixel_size[2];
float z_far;
@@ -848,10 +623,10 @@ private:
RID index_buffer;
RID index_array;
- Map<RID, RID> texture_to_uniform_set_cache;
- Map<RID, RID> input_to_uniform_set_cache;
+ HashMap<RID, RID> texture_to_uniform_set_cache;
+ HashMap<RID, RID> input_to_uniform_set_cache;
- Map<RID, RID> image_to_uniform_set_cache;
+ HashMap<RID, RID> image_to_uniform_set_cache;
struct TexturePair {
RID texture1;
@@ -877,16 +652,14 @@ private:
}
};
- Map<TexturePair, RID> texture_pair_to_uniform_set_cache;
- 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;
+ RBMap<TexturePair, RID> texture_pair_to_uniform_set_cache;
+ RBMap<RID, RID> texture_to_compute_uniform_set_cache;
+ RBMap<TexturePair, RID> texture_pair_to_compute_uniform_set_cache;
+ RBMap<TexturePair, RID> image_pair_to_compute_uniform_set_cache;
+ RBMap<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
RID _get_uniform_set_from_image(RID p_texture);
- RID _get_uniform_set_for_input(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
- RID _get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, 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);
@@ -896,89 +669,14 @@ public:
bool get_prefer_raster_effects();
void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
- void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
- void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
- void 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 copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
- void 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 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 = false, bool p_panorama = false);
- void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
- void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness_raster(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 make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
- void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void 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 = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- struct BokehBuffers {
- // bokeh buffers
-
- // textures
- Size2i base_texture_size;
- RID base_texture;
- RID depth_texture;
- RID secondary_texture;
- RID half_texture[2];
-
- // raster only
- RID base_fb;
- RID secondary_fb; // with weights
- RID half_fb[2]; // with weights
- RID base_weight_fb;
- RID weight_texture[4];
- };
-
- void bokeh_dof(const BokehBuffers &p_buffers, 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, RS::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 bokeh_dof_raster(const BokehBuffers &p_buffers, 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_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
-
- struct TonemapSettings {
- bool use_glow = false;
- enum GlowMode {
- GLOW_MODE_ADD,
- GLOW_MODE_SCREEN,
- GLOW_MODE_SOFTLIGHT,
- GLOW_MODE_REPLACE,
- GLOW_MODE_MIX
- };
-
- GlowMode glow_mode = GLOW_MODE_ADD;
- float glow_intensity = 1.0;
- float glow_map_strength = 0.0f;
- float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
- Vector2i glow_texture_size;
- bool glow_use_bicubic_upscale = false;
- RID glow_texture;
- RID glow_map;
-
- RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
- float exposure = 1.0;
- float white = 1.0;
-
- bool use_auto_exposure = false;
- float auto_exposure_grey = 0.5;
- RID exposure_texture;
- float luminance_multiplier = 1.0;
-
- bool use_bcs = false;
- float brightness = 1.0;
- float contrast = 1.0;
- float saturation = 1.0;
-
- bool use_color_correction = false;
- bool use_1d_color_correction = false;
- RID color_correction_texture;
-
- bool use_fxaa = false;
- bool use_debanding = false;
- Vector2i texture_size;
- uint32_t view_count = 1;
- };
-
struct SSAOSettings {
float radius = 1.0;
float intensity = 2.0;
@@ -1017,9 +715,6 @@ public:
Size2i quarter_screen_size = Size2i();
};
- void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
- void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
-
void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index d113fcd4f0..2d3998bd90 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -30,6 +30,11 @@
#include "render_forward_clustered.h"
#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -57,14 +62,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
Vector<RID> fb;
- fb.push_back(color);
- fb.push_back(specular);
- fb.push_back(depth);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -77,14 +74,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
{
Vector<RID> fb;
- fb.push_back(color_msaa);
- fb.push_back(specular_msaa);
- fb.push_back(depth_msaa);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular_msaa);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -93,6 +82,27 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
}
}
+void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_velocity() {
+ if (!velocity_buffer.is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16_SFLOAT;
+ tf.width = width;
+ tf.height = height;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ RD::TextureFormat tf_aa = tf;
+ tf_aa.samples = texture_samples;
+ tf_aa.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ velocity_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView());
+
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ }
+
+ velocity_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+}
+
void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() {
if (!voxelgi_buffer.is_valid()) {
RD::TextureFormat tf;
@@ -163,11 +173,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
color = RID();
depth = RID();
- color_specular_fb = RID();
- specular_only_fb = RID();
- color_fb = RID();
depth_fb = RID();
+ color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
+
if (normal_roughness_buffer.is_valid()) {
RD::get_singleton()->free(normal_roughness_buffer);
if (normal_roughness_buffer_msaa.is_valid()) {
@@ -181,17 +190,27 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) {
RD::get_singleton()->free(render_sdfgi_uniform_set);
}
+
+ if (velocity_buffer != RID()) {
+ RD::get_singleton()->free(velocity_buffer);
+ velocity_buffer = RID();
+ }
+
+ if (velocity_buffer_msaa != RID()) {
+ RD::get_singleton()->free(velocity_buffer_msaa);
+ velocity_buffer_msaa = RID();
+ }
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
+void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
clear();
- ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support");
-
msaa = p_msaa;
+ use_taa = p_use_taa;
width = p_width;
height = p_height;
+ view_count = p_view_count;
color = p_color_buffer;
depth = p_depth_buffer;
@@ -202,23 +221,28 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(p_color_buffer);
fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
fb.push_back(depth);
- depth_fb = RD::get_singleton()->framebuffer_create(fb);
+ depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
} else {
RD::TextureFormat tf;
+ if (view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ }
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = p_width;
tf.height = p_height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = view_count; // create a layer for every view
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] = {
+ const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
RD::TEXTURE_SAMPLES_1,
RD::TEXTURE_SAMPLES_2,
RD::TEXTURE_SAMPLES_4,
@@ -240,17 +264,49 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
fb.push_back(depth_msaa);
- depth_fb = RD::get_singleton()->framebuffer_create(fb);
+ depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
}
}
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) {
+ if (color_framebuffers.has(p_color_pass_flags)) {
+ return color_framebuffers[p_color_pass_flags];
+ }
+
+ bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED;
+
+ Vector<RID> fb;
+ fb.push_back(use_msaa ? color_msaa : color);
+
+ if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ ensure_specular();
+ fb.push_back(use_msaa ? specular_msaa : specular);
+ } else {
+ fb.push_back(RID());
+ }
+
+ if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) {
+ ensure_velocity();
+ fb.push_back(use_msaa ? velocity_buffer_msaa : velocity_buffer);
+ } else {
+ fb.push_back(RID());
+ }
+
+ fb.push_back(use_msaa ? depth_msaa : depth);
+
+ int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
+ RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
+ color_framebuffers[p_color_pass_flags] = framebuffer;
+ return framebuffer;
+}
+
void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) {
if (rb->normal_roughness_buffer.is_valid()) {
return;
@@ -300,8 +356,9 @@ bool RenderForwardClustered::free(RID p_rid) {
/// RENDERING ///
-template <RenderForwardClustered::PassMode p_pass_mode>
+template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags>
void RenderForwardClustered::_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) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -334,7 +391,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
- if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
}
@@ -397,10 +454,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
-
+ uint32_t pipeline_color_pass_flags = 0;
uint32_t pipeline_specialization = 0;
- if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) {
+ if (p_pass_mode == PASS_MODE_COLOR) {
if (element_info.uses_softshadow) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
}
@@ -416,52 +473,64 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
switch (p_pass_mode) {
case PASS_MODE_COLOR: {
if (element_info.uses_lightmap) {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS;
- } else {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS;
- }
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- if (element_info.uses_lightmap) {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS;
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_LIGHTMAP;
} else {
if (element_info.uses_forward_gi) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
}
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS;
}
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- if (element_info.uses_lightmap) {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
- } else {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MULTIVIEW;
}
+
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS;
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS;
+ pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS;
} break;
case PASS_MODE_SHADOW_DP: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for depth/roughness pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for voxel GI pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
case PASS_MODE_SDF: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for SDF pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF;
} break;
}
PipelineCacheRD *pipeline = nullptr;
- pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ if constexpr (p_pass_mode == PASS_MODE_COLOR) {
+ pipeline = &shader->color_pipelines[cull_variant][primitive][pipeline_color_pass_flags];
+ } else {
+ pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ }
RD::VertexFormatID vertex_format = -1;
RID vertex_array_rd;
@@ -469,12 +538,12 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
//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);
+ mesh_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);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
+ index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -532,14 +601,28 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
//use template for faster performance (pass mode comparisons are inlined)
switch (p_params->pass_mode) {
+#define VALID_FLAG_COMBINATION(f) \
+ case f: { \
+ _render_list_template<PASS_MODE_COLOR, f>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); \
+ } break;
+
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);
+ switch (p_params->color_pass_flags) {
+ VALID_FLAG_COMBINATION(0);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR | COLOR_PASS_FLAG_MULTIVIEW);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR | COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MOTION_VECTORS);
+ default: {
+ ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags));
+ }
+ }
+
} 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);
@@ -596,13 +679,23 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
CameraMatrix correction;
correction.set_depth_correction(p_flip_y);
+ correction.add_jitter_offset(p_render_data->taa_jitter);
CameraMatrix projection = correction * p_render_data->cam_projection;
//store camera into ubo
RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
+ RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
+ RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
+
+ for (uint32_t v = 0; v < p_render_data->view_count; v++) {
+ projection = correction * p_render_data->view_projection[v];
+ RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
+ RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
+ }
+
+ scene_state.ubo.taa_jitter[0] = p_render_data->taa_jitter.x;
+ scene_state.ubo.taa_jitter[1] = p_render_data->taa_jitter.y;
scene_state.ubo.z_far = p_render_data->z_far;
scene_state.ubo.z_near = p_render_data->z_near;
@@ -645,7 +738,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_enabled = false;
if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
+ RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
scene_state.ubo.gi_upscale_for_msaa = true;
}
@@ -667,61 +760,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
}
}
}
-#if 0
- if (p_render_data->render_buffers.is_valid() && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
- scene_state.ubo.sdfgi_cascade_count = render_buffers_get_sdfgi_cascade_count(p_render_data->render_buffers);
- scene_state.ubo.sdfgi_probe_axis_size = render_buffers_get_sdfgi_cascade_probe_count(p_render_data->render_buffers);
- scene_state.ubo.sdfgi_cascade_probe_size[0] = scene_state.ubo.sdfgi_probe_axis_size - 1; //float version for performance
- scene_state.ubo.sdfgi_cascade_probe_size[1] = scene_state.ubo.sdfgi_probe_axis_size - 1;
- scene_state.ubo.sdfgi_cascade_probe_size[2] = scene_state.ubo.sdfgi_probe_axis_size - 1;
-
- float csize = render_buffers_get_sdfgi_cascade_size(p_render_data->render_buffers);
- scene_state.ubo.sdfgi_probe_to_uvw = 1.0 / float(scene_state.ubo.sdfgi_cascade_probe_size[0]);
- float occ_bias = 0.0;
- scene_state.ubo.sdfgi_occlusion_bias = occ_bias / csize;
- scene_state.ubo.sdfgi_use_occlusion = render_buffers_is_sdfgi_using_occlusion(p_render_data->render_buffers);
- scene_state.ubo.sdfgi_energy = render_buffers_get_sdfgi_energy(p_render_data->render_buffers);
-
- float cascade_voxel_size = (csize / scene_state.ubo.sdfgi_cascade_probe_size[0]);
- float occlusion_clamp = (cascade_voxel_size - 0.5) / cascade_voxel_size;
- scene_state.ubo.sdfgi_occlusion_clamp[0] = occlusion_clamp;
- scene_state.ubo.sdfgi_occlusion_clamp[1] = occlusion_clamp;
- scene_state.ubo.sdfgi_occlusion_clamp[2] = occlusion_clamp;
- scene_state.ubo.sdfgi_normal_bias = (render_buffers_get_sdfgi_normal_bias(p_render_data->render_buffers) / csize) * scene_state.ubo.sdfgi_cascade_probe_size[0];
-
- //vec2 tex_pixel_size = 1.0 / vec2(ivec2( (OCT_SIZE+2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE+2) * params.probe_axis_size ) );
- //vec3 probe_uv_offset = (ivec3(OCT_SIZE+2,OCT_SIZE+2,(OCT_SIZE+2) * params.probe_axis_size)) * tex_pixel_size.xyx;
-
- uint32_t oct_size = gi.sdfgi_get_lightprobe_octahedron_size();
-
- scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size * scene_state.ubo.sdfgi_probe_axis_size);
- scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size);
- scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[2] = 1.0;
-
- scene_state.ubo.sdfgi_probe_uv_offset[0] = float(oct_size + 2) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0];
- scene_state.ubo.sdfgi_probe_uv_offset[1] = float(oct_size + 2) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1];
- scene_state.ubo.sdfgi_probe_uv_offset[2] = float((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0];
-
- scene_state.ubo.sdfgi_occlusion_renormalize[0] = 0.5;
- scene_state.ubo.sdfgi_occlusion_renormalize[1] = 1.0;
- scene_state.ubo.sdfgi_occlusion_renormalize[2] = 1.0 / float(scene_state.ubo.sdfgi_cascade_count);
-
- for (uint32_t i = 0; i < scene_state.ubo.sdfgi_cascade_count; i++) {
- SceneState::UBO::SDFGICascade &c = scene_state.ubo.sdfgi_cascades[i];
- Vector3 pos = render_buffers_get_sdfgi_cascade_offset(p_render_data->render_buffers, i);
- pos -= p_render_data->cam_transform.origin; //make pos local to camera, to reduce numerical error
- c.position[0] = pos.x;
- c.position[1] = pos.y;
- c.position[2] = pos.z;
- c.to_probe = 1.0 / render_buffers_get_sdfgi_cascade_probe_size(p_render_data->render_buffers, i);
-
- Vector3i probe_ofs = render_buffers_get_sdfgi_cascade_probe_offset(p_render_data->render_buffers, i);
- c.probe_world_offset[0] = probe_ofs.x;
- c.probe_world_offset[1] = probe_ofs.y;
- c.probe_world_offset[2] = probe_ofs.z;
- }
- }
-#endif
+
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.ambient_light_color_energy[0] = 1;
@@ -744,7 +783,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
@@ -754,7 +793,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
} else {
float energy = environment_get_ambient_light_energy(p_render_data->environment);
Color color = environment_get_ambient_light_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
@@ -790,7 +829,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
- Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
+ Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
@@ -800,12 +839,12 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
} else {
- if (p_render_data->reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
scene_state.ubo.use_ambient_light = false;
} else {
scene_state.ubo.use_ambient_light = true;
Color clear_color = p_default_bg_color;
- clear_color = clear_color.to_linear();
+ clear_color = clear_color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
@@ -821,15 +860,41 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
+ if (p_render_data->render_buffers.is_valid()) {
+ RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
+ if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
+ memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO));
+
+ CameraMatrix prev_correction;
+ prev_correction.set_depth_correction(true);
+ prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter);
+ CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection;
+
+ //store camera into ubo
+ RendererStorageRD::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix);
+ RendererStorageRD::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix);
+ RendererStorageRD::store_transform(p_render_data->prev_cam_transform, scene_state.prev_ubo.inv_view_matrix);
+ RendererStorageRD::store_transform(p_render_data->prev_cam_transform.affine_inverse(), scene_state.prev_ubo.view_matrix);
+
+ for (uint32_t v = 0; v < p_render_data->view_count; v++) {
+ prev_projection = prev_correction * p_render_data->view_projection[v];
+ RendererStorageRD::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix_view[v]);
+ RendererStorageRD::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix_view[v]);
+ }
+ scene_state.prev_ubo.taa_jitter[0] = p_render_data->prev_taa_jitter.x;
+ scene_state.prev_ubo.taa_jitter[1] = p_render_data->prev_taa_jitter.y;
+ scene_state.prev_ubo.time -= time_step;
+ }
+ }
+
if (p_index >= (int)scene_state.uniform_buffers.size()) {
uint32_t from = scene_state.uniform_buffers.size();
scene_state.uniform_buffers.resize(p_index + 1);
- render_pass_uniform_sets.resize(p_index + 1);
for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) {
- scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
+ scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO) * 2);
}
}
- RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER);
+ RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO) * 2, &scene_state.ubo_data, RD::BARRIER_MASK_RASTER);
}
void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) {
@@ -855,6 +920,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
if (p_render_info) {
p_render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] += element_total;
}
+ uint64_t frame = RSG::rasterizer->get_frame_number();
uint32_t repeats = 0;
GeometryInstanceSurfaceDataCache *prev_surface = nullptr;
for (uint32_t i = 0; i < element_total; i++) {
@@ -863,10 +929,17 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset];
+ if (inst->prev_transform_dirty && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame) {
+ inst->prev_transform = inst->transform;
+ inst->prev_transform_dirty = false;
+ }
+
if (inst->store_transform_cache) {
RendererStorageRD::store_transform(inst->transform, instance_data.transform);
+ RendererStorageRD::store_transform(inst->prev_transform, instance_data.prev_transform);
} else {
RendererStorageRD::store_transform(Transform3D(), instance_data.transform);
+ RendererStorageRD::store_transform(Transform3D(), instance_data.prev_transform);
}
instance_data.flags = inst->flags_cache;
@@ -927,6 +1000,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
@@ -935,7 +1010,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
+ Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1063,7 +1138,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1082,12 +1157,12 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
distance = -distance_max;
}
- if (p_render_data->cam_ortogonal) {
+ if (p_render_data->cam_orthogonal) {
distance = 1.0;
}
uint32_t indices;
- surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1099,13 +1174,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
} else {
surf->sort.lod_index = 0;
if (p_render_data->render_info) {
- uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
} else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
}
}
}
@@ -1190,7 +1265,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
to_lm = to_lm.inverse().transposed(); //will transform normals
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.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
scene_state.lightmaps_used++;
}
@@ -1200,11 +1275,9 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
}
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
- ERR_FAIL_COND_MSG(p_render_data->view_count != 1, "Multiview is currently not supported in the clustered renderer. Please use the mobile renderer for VR.");
-
RenderBufferDataForwardClustered *render_buffer = nullptr;
if (p_render_data->render_buffers.is_valid()) {
- render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
+ render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
}
RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
@@ -1215,20 +1288,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RENDER_TIMESTAMP("Setup 3D Scene");
//scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
-
- Vector2 vp_he = p_render_data->cam_projection.get_viewport_half_extents();
- scene_state.ubo.viewport_size[0] = vp_he.x;
- scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
- RID opaque_framebuffer;
- RID opaque_specular_framebuffer;
+ RID color_framebuffer;
+ RID color_only_framebuffer;
RID depth_framebuffer;
- RID alpha_framebuffer;
PassMode depth_pass_mode = PASS_MODE_DEPTH;
+ uint32_t color_pass_flags = 0;
Vector<Color> depth_pass_clear;
bool using_separate_specular = false;
bool using_ssr = false;
@@ -1241,15 +1310,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- opaque_framebuffer = render_buffer->color_fb;
+ if (render_buffer->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
+ color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS;
+ }
if (p_render_data->voxel_gi_instances->size() > 0) {
using_voxelgi = true;
}
- if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ if (p_render_data->view_count > 1) {
+ depth_pass_mode = PASS_MODE_DEPTH;
+ } else if (!p_render_data->environment.is_valid() && using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
if (environment_is_sdfgi_enabled(p_render_data->environment)) {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
@@ -1257,14 +1329,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} else {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
-
if (environment_is_ssr_enabled(p_render_data->environment)) {
- render_buffer->ensure_specular();
using_separate_specular = true;
using_ssr = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1289,17 +1358,22 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
};
}
- alpha_framebuffer = opaque_framebuffer;
+ if (p_render_data->view_count > 1) {
+ color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
+ color_only_framebuffer = render_buffer->color_only_fb;
} else if (p_render_data->reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_only_framebuffer = color_framebuffer;
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- alpha_framebuffer = opaque_framebuffer;
- if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
env = nullptr;
}
@@ -1309,6 +1383,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
ERR_FAIL(); //bug?
}
+ scene_state.ubo.viewport_size[0] = screen_size.x;
+ scene_state.ubo.viewport_size[1] = screen_size.y;
+
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
@@ -1327,11 +1404,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
- if (using_sss) {
+ if (using_sss && !using_separate_specular) {
using_separate_specular = true;
- render_buffer->ensure_specular();
- using_separate_specular = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
}
RID radiance_texture;
bool draw_sky = false;
@@ -1351,9 +1427,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy;
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
+ if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_COLOR: {
@@ -1361,9 +1437,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy;
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
+ if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
@@ -1417,7 +1493,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_voxelgi);
if (needs_pre_resolve) {
- RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (parallel)");
+ RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (Parallel)");
} else {
RENDER_TIMESTAMP("Render Depth Pre-Pass");
}
@@ -1434,7 +1510,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1444,8 +1520,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RENDER_TIMESTAMP("Resolve Depth Pre-Pass");
- RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass");
+ RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)");
+ RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)");
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) {
if (needs_pre_resolve) {
RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE);
@@ -1480,20 +1556,22 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
- //regular forward for now
Vector<Color> c;
- if (using_separate_specular) {
- Color cc = clear_color.to_linear();
- cc.a = 0; //subsurf scatter must be 0
+ {
+ Color cc = clear_color.srgb_to_linear();
+ if (using_separate_specular || render_buffer) {
+ cc.a = 0; //subsurf scatter must be 0
+ }
c.push_back(cc);
- c.push_back(Color(0, 0, 0, 0));
- } else {
- c.push_back(clear_color.to_linear());
+
+ if (render_buffer) {
+ c.push_back(Color(0, 0, 0, 0)); // Separate specular
+ c.push_back(Color(0, 0, 0, 0)); // Motion vectors
+ }
}
- RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_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_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ _render_list_with_threads(&render_list_params, color_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_CONTINUE : RD::INITIAL_ACTION_KEEP) : 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
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);
@@ -1511,10 +1589,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->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);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_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);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
- gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
+ gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
}
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
@@ -1528,9 +1606,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->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);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_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);
RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
- _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm);
+ _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm);
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
@@ -1538,14 +1616,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (draw_sky || draw_sky_fog_only) {
RENDER_TIMESTAMP("Render Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ RD::get_singleton()->draw_command_begin_label("Draw Sky");
+
if (p_render_data->reflection_probe.is_valid()) {
CameraMatrix correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->cam_projection;
+ CameraMatrix projection = correction * p_render_data->cam_projection;
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ } else {
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
- RD::get_singleton()->draw_command_begin_label("Draw Sky");
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
RD::get_singleton()->draw_command_end_label();
}
@@ -1562,21 +1642,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (using_separate_specular) {
if (using_sss) {
- RENDER_TIMESTAMP("Sub Surface Scattering");
- RD::get_singleton()->draw_command_begin_label("Process Sub Surface Scattering");
+ RENDER_TIMESTAMP("Sub-Surface Scattering");
+ RD::get_singleton()->draw_command_begin_label("Process Sub-Surface Scattering");
_process_sss(p_render_data->render_buffers, p_render_data->cam_projection);
RD::get_singleton()->draw_command_end_label();
}
if (using_ssr) {
- RENDER_TIMESTAMP("Screen Space Reflection");
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Reflections");
- _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ RENDER_TIMESTAMP("Screen-Space Reflections");
+ RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
+ _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
}
}
@@ -1590,16 +1670,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_render_buffers_copy_depth_texture(p_render_data);
}
- RENDER_TIMESTAMP("Render Transparent Pass");
+ RENDER_TIMESTAMP("Render 3D Transparent Pass");
- RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
+ RD::get_singleton()->draw_command_begin_label("Render 3D Transparent Pass");
rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold);
+ uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_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);
}
@@ -1611,6 +1693,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
+ if (render_buffer->use_taa) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->velocity_buffer_msaa, render_buffer->velocity_buffer);
+ }
storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
}
@@ -1618,11 +1703,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Copy framebuffer for SSIL");
if (using_ssil) {
- RENDER_TIMESTAMP("Copy Final Framebuffer");
+ RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL)");
_copy_framebuffer_to_ssil(p_render_data->render_buffers);
}
RD::get_singleton()->draw_command_end_label();
+ if (render_buffer && render_buffer->use_taa) {
+ RENDER_TIMESTAMP("TAA")
+ _process_taa(p_render_data->render_buffers, render_buffer->velocity_buffer, p_render_data->z_near, p_render_data->z_far);
+ }
+
if (p_render_data->render_buffers.is_valid()) {
_debug_draw_cluster(p_render_data->render_buffers);
@@ -1649,6 +1739,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
RenderDataRD render_data;
render_data.cam_projection = p_projection;
render_data.cam_transform = p_transform;
+ render_data.view_projection[0] = p_projection;
render_data.z_far = p_zfar;
render_data.z_near = 0.0;
render_data.cluster_size = 1;
@@ -1720,7 +1811,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1731,13 +1822,14 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
}
void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
- RENDER_TIMESTAMP("Setup Render Collider Heightfield");
+ RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
render_data.cam_transform = p_cam_transform;
+ render_data.view_projection[0] = p_cam_projection;
render_data.z_near = 0.0;
render_data.z_far = p_cam_projection.get_z_far();
render_data.cluster_size = 1;
@@ -1762,20 +1854,21 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
{
//regular forward for now
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, 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);
}
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_material(const Transform3D &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");
+void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+ RENDER_TIMESTAMP("Setup Rendering 3D Material");
- RD::get_singleton()->draw_command_begin_label("Render Material");
+ RD::get_singleton()->draw_command_begin_label("Render 3D Material");
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
render_data.cam_transform = p_cam_transform;
+ render_data.view_projection[0] = p_cam_projection;
render_data.cluster_size = 1;
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
@@ -1795,10 +1888,10 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
- RENDER_TIMESTAMP("Render Material");
+ RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1841,10 +1934,10 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
- RENDER_TIMESTAMP("Render Material");
+ RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1898,7 +1991,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
_update_render_base_uniform_set();
- RenderBufferDataForwardClustered *render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers);
+ RenderBufferDataForwardClustered *render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
ERR_FAIL_COND(!render_buffer);
PassMode pass_mode = PASS_MODE_SDF;
@@ -1936,9 +2029,9 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
fb_size.y = p_size[up_axis];
render_data.cam_transform.origin = center + axis * half_extents;
- render_data.cam_transform.basis.set_axis(0, right);
- render_data.cam_transform.basis.set_axis(1, up);
- render_data.cam_transform.basis.set_axis(2, axis);
+ render_data.cam_transform.basis.set_column(0, right);
+ render_data.cam_transform.basis.set_column(1, up);
+ render_data.cam_transform.basis.set_column(2, axis);
//print_line("pass: " + itos(i) + " xform " + render_data.cam_transform);
@@ -1958,14 +2051,14 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
- Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size);
+ HashMap<Size2i, RID>::Iterator E = sdfgi_framebuffer_size_cache.find(fb_size);
if (!E) {
RID fb = RD::get_singleton()->framebuffer_create_empty(fb_size);
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, 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);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false);
+ _render_list_with_threads(&render_list_params, E->value, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
RD::get_singleton()->draw_command_end_label();
@@ -1979,35 +2072,39 @@ void RenderForwardClustered::_base_uniforms_changed() {
}
void RenderForwardClustered::_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()) || base_uniform_set_updated) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version()) || base_uniform_set_updated) {
base_uniform_set_updated = false;
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);
}
- lightmap_texture_array_version = storage->lightmap_array_get_version();
+ lightmap_texture_array_version = light_storage->lightmap_array_get_version();
Vector<RD::Uniform> uniforms;
{
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 1;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+
uniforms.push_back(u);
}
@@ -2015,7 +2112,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.ids.push_back(scene_shader.shadow_sampler);
+ u.append_id(scene_shader.shadow_sampler);
uniforms.push_back(u);
}
@@ -2026,23 +2123,23 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
- u.ids.push_back(sampler);
+ u.append_id(sampler);
uniforms.push_back(u);
}
@@ -2053,23 +2150,23 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
- u.ids.push_back(sampler);
+ u.append_id(sampler);
uniforms.push_back(u);
}
@@ -2077,14 +2174,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_omni_light_buffer());
+ u.append_id(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_spot_light_buffer());
+ u.append_id(get_spot_light_buffer());
uniforms.push_back(u);
}
@@ -2092,51 +2189,51 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_reflection_probe_buffer());
+ u.append_id(get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(get_directional_light_buffer());
+ u.append_id(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.lightmap_buffer);
+ u.append_id(scene_state.lightmap_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.lightmap_capture_buffer);
+ u.append_id(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = storage->decal_atlas_get_texture();
- u.ids.push_back(decal_atlas);
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
+ u.append_id(decal_atlas);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = storage->decal_atlas_get_texture_srgb();
- u.ids.push_back(decal_atlas);
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_srgb();
+ u.append_id(decal_atlas);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_decal_buffer());
+ u.append_id(get_decal_buffer());
uniforms.push_back(u);
}
@@ -2144,7 +2241,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.ids.push_back(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2152,7 +2249,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 15;
- u.ids.push_back(sdfgi_get_ubo());
+ u.append_id(sdfgi_get_ubo());
uniforms.push_back(u);
}
@@ -2161,12 +2258,12 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
- //there should always be enough uniform buffers for render passes, otherwise bugs
- ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RenderBufferDataForwardClustered *rb = nullptr;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
+ rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
}
//default render buffer and scene state uniform set
@@ -2177,7 +2274,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(scene_state.uniform_buffers[p_index]);
+ u.append_id(scene_state.uniform_buffers[p_index]);
uniforms.push_back(u);
}
{
@@ -2188,7 +2285,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (instance_buffer == RID()) {
instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used
}
- u.ids.push_back(instance_buffer);
+ u.append_id(instance_buffer);
uniforms.push_back(u);
}
{
@@ -2196,12 +2293,12 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
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);
+ radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(radiance_texture);
+ u.append_id(radiance_texture);
uniforms.push_back(u);
}
@@ -2211,9 +2308,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (ref_texture.is_valid()) {
- u.ids.push_back(ref_texture);
+ u.append_id(ref_texture);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
}
uniforms.push_back(u);
}
@@ -2227,9 +2324,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
}
- u.ids.push_back(texture);
+ u.append_id(texture);
uniforms.push_back(u);
}
{
@@ -2237,9 +2334,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
- u.ids.push_back(directional_shadow_get_texture());
+ u.append_id(directional_shadow_get_texture());
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -2247,16 +2344,16 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 6;
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);
+
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
- RID texture = storage->lightmap_get_texture(base);
- RID rd_texture = storage->texture_get_rd_texture(texture);
- u.ids.write[i] = rd_texture;
+ RID texture = light_storage->lightmap_get_texture(base);
+ RID rd_texture = texture_storage->texture_get_rd_texture(texture);
+ u.append_id(rd_texture);
} else {
- u.ids.write[i] = default_tex;
+ u.append_id(default_tex);
}
}
@@ -2266,17 +2363,16 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
- RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) {
RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]);
if (!tex.is_valid()) {
tex = default_tex;
}
- u.ids.write[i] = tex;
+ u.append_id(tex);
} else {
- u.ids.write[i] = default_tex;
+ u.append_id(default_tex);
}
}
@@ -2288,7 +2384,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = (p_render_data && p_render_data->cluster_buffer.is_valid()) ? p_render_data->cluster_buffer : scene_shader.default_vec4_xform_buffer;
- u.ids.push_back(cb);
+ u.append_id(cb);
uniforms.push_back(u);
}
@@ -2297,8 +2393,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
- u.ids.push_back(texture);
+ RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ u.append_id(texture);
uniforms.push_back(u);
}
{
@@ -2306,8 +2402,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
- RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(texture);
+ RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -2316,8 +2412,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 11;
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);
+ RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -2326,8 +2422,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID();
- RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(texture);
+ RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -2336,8 +2432,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID();
- RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(texture);
+ RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -2346,8 +2442,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 14;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID();
- RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(texture);
+ RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
uniforms.push_back(u);
}
{
@@ -2358,9 +2454,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers);
} else {
- t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
}
- u.ids.push_back(t);
+ u.append_id(t);
uniforms.push_back(u);
}
{
@@ -2368,9 +2464,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 16;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
- u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
+ u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
uniforms.push_back(u);
}
@@ -2378,7 +2474,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 17;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer());
+ u.append_id(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer());
uniforms.push_back(u);
}
{
@@ -2389,12 +2485,12 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers);
if (vfog.is_null()) {
- vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
}
} else {
- vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
}
- u.ids.push_back(vfog);
+ u.append_id(vfog);
uniforms.push_back(u);
}
{
@@ -2402,62 +2498,50 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 19;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID();
- RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(texture);
+ RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
uniforms.push_back(u);
}
}
- if (p_index >= (int)render_pass_uniform_sets.size()) {
- render_pass_uniform_sets.resize(p_index + 1);
- }
-
- if (render_pass_uniform_sets[p_index].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[p_index])) {
- RD::get_singleton()->free(render_pass_uniform_sets[p_index]);
- }
-
- render_pass_uniform_sets[p_index] = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET);
- return render_pass_uniform_sets[p_index];
+ return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms);
}
RID RenderForwardClustered::_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);
- }
-
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(scene_state.uniform_buffers[0]);
+ u.append_id(scene_state.uniform_buffers[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 1;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
+ u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
uniforms.push_back(u);
}
{
// 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);
+ RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(radiance_texture);
+ u.append_id(radiance_texture);
uniforms.push_back(u);
}
{
// No reflection atlas.
- RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(ref_texture);
+ u.append_id(ref_texture);
uniforms.push_back(u);
}
@@ -2466,8 +2550,8 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
- u.ids.push_back(texture);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -2476,8 +2560,8 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
- u.ids.push_back(texture);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -2486,10 +2570,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 6;
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);
+
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
- u.ids.write[i] = default_tex;
+ u.append_id(default_tex);
}
uniforms.push_back(u);
@@ -2500,10 +2584,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
- RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
- u.ids.write[i] = default_tex;
+ u.append_id(default_tex);
}
uniforms.push_back(u);
@@ -2514,7 +2598,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = scene_shader.default_vec4_xform_buffer;
- u.ids.push_back(cb);
+ u.append_id(cb);
uniforms.push_back(u);
}
@@ -2524,39 +2608,44 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.ids.push_back(p_albedo_texture);
+ u.append_id(p_albedo_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
- u.ids.push_back(p_emission_texture);
+ u.append_id(p_emission_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 11;
- u.ids.push_back(p_emission_aniso_texture);
+ u.append_id(p_emission_aniso_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 12;
- u.ids.push_back(p_geom_facing_texture);
+ u.append_id(p_geom_facing_texture);
uniforms.push_back(u);
}
- sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET);
- return sdfgi_pass_uniform_set;
+ return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET, uniforms);
}
RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) {
- RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers);
+ RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
+
+ return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->normal_roughness_buffer : rb->normal_roughness_buffer_msaa;
+}
+
+RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_buffers) {
+ RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
- return rb->normal_roughness_buffer;
+ return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->velocity_buffer : rb->velocity_buffer_msaa;
}
RenderForwardClustered *RenderForwardClustered::singleton = nullptr;
@@ -2582,8 +2671,10 @@ void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_g
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
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_base_alpha = (p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha;
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
bool has_alpha = has_base_alpha || has_blend_alpha;
@@ -2628,14 +2719,14 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
void *surface_shadow = nullptr;
- if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
+ if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
- RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+ RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
if (shadow_mesh.is_valid()) {
- surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface);
}
} else {
@@ -2648,8 +2739,8 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
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 = mesh_storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
@@ -2685,23 +2776,25 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
SceneShaderForwardClustered::MaterialData *material = p_material;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::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);
+ material_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);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
}
}
void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2709,7 +2802,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
SceneShaderForwardClustered::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2717,10 +2810,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (material) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2731,10 +2824,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
@@ -2743,6 +2836,8 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
}
void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2756,7 +2851,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
uint32_t surface_count;
RID mesh = ginstance->data->base;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_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();
@@ -2773,19 +2868,19 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
} break;
case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ RID mesh = 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);
+ materials = mesh_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);
+ ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
@@ -2799,10 +2894,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
} break;
#endif
case RS::INSTANCE_PARTICLES: {
- int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+ int draw_passes = particles_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);
+ RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
if (!mesh.is_valid()) {
continue;
}
@@ -2810,7 +2905,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_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);
@@ -2818,7 +2913,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
}
}
- ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
+ ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
} break;
@@ -2834,17 +2929,17 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
- if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
}
- if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2855,16 +2950,16 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
//for particles, stride is the trail size
ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
- if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+ if (!particles_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, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
- if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
- ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
if (ginstance->data->dirty_dependencies) {
- storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
}
}
}
@@ -2904,7 +2999,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
@@ -2970,6 +3065,13 @@ void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstanc
void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
+
+ uint64_t frame = RSG::rasterizer->get_frame_number();
+ if (frame != ginstance->prev_transform_change_frame) {
+ ginstance->prev_transform = ginstance->transform;
+ ginstance->prev_transform_change_frame = frame;
+ ginstance->prev_transform_dirty = true;
+ }
ginstance->transform = p_transform;
ginstance->mirror = p_transform.basis.determinant() < 0;
ginstance->data->aabb = p_aabb;
@@ -3218,17 +3320,6 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
RenderForwardClustered::~RenderForwardClustered() {
directional_shadow_atlas_set_size(0);
- //clear base uniform set if still valid
- for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) {
- if (render_pass_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[i])) {
- RD::get_singleton()->free(render_pass_uniform_sets[i]);
- }
- }
-
- 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);
- }
-
{
for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) {
RD::get_singleton()->free(scene_state.uniform_buffers[i]);
@@ -3243,8 +3334,8 @@ RenderForwardClustered::~RenderForwardClustered() {
memdelete_arr(scene_state.lightmap_captures);
}
- while (sdfgi_framebuffer_size_cache.front()) {
- RD::get_singleton()->free(sdfgi_framebuffer_size_cache.front()->get());
- sdfgi_framebuffer_size_cache.erase(sdfgi_framebuffer_size_cache.front());
+ while (sdfgi_framebuffer_size_cache.begin()) {
+ RD::get_singleton()->free(sdfgi_framebuffer_size_cache.begin()->value);
+ sdfgi_framebuffer_size_cache.remove(sdfgi_framebuffer_size_cache.begin());
}
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index f858887bd0..6ad42bf0ec 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -89,9 +89,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID specular;
RID normal_roughness_buffer;
RID voxelgi_buffer;
+ RID velocity_buffer;
RS::ViewportMSAA msaa;
RD::TextureSamples texture_samples;
+ bool use_taa;
RID color_msaa;
RID depth_msaa;
@@ -99,20 +101,24 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID normal_roughness_buffer_msaa;
RID roughness_buffer_msaa;
RID voxelgi_buffer_msaa;
+ RID velocity_buffer_msaa;
RID depth_fb;
RID depth_normal_roughness_fb;
RID depth_normal_roughness_voxelgi_fb;
- RID color_fb;
- RID color_specular_fb;
+ RID color_only_fb;
RID specular_only_fb;
int width, height;
+ HashMap<uint32_t, RID> color_framebuffers;
+ uint32_t view_count;
RID render_sdfgi_uniform_set;
void ensure_specular();
void ensure_voxelgi();
+ void ensure_velocity();
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
+ RID get_color_pass_fb(uint32_t p_color_pass_flags);
~RenderBufferDataForwardClustered();
};
@@ -121,13 +127,12 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
RID render_base_uniform_set;
- LocalVector<RID> render_pass_uniform_sets;
- RID sdfgi_pass_uniform_set;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
virtual void _base_uniforms_changed() override;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
+ virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
bool base_uniform_set_updated = false;
void _update_render_base_uniform_set();
@@ -136,8 +141,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
enum PassMode {
PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
@@ -147,6 +150,13 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PASS_MODE_SDF,
};
+ enum ColorPassFlags {
+ COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ COLOR_PASS_FLAG_MULTIVIEW = 1 << 2,
+ COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 3,
+ };
+
struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
@@ -156,7 +166,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
int element_count = 0;
bool reverse_cull = false;
PassMode pass_mode = PASS_MODE_COLOR;
+ uint32_t color_pass_flags = 0;
bool no_gi = false;
+ uint32_t view_count = 1;
RID render_pass_uniform_set;
bool force_wireframe = false;
Vector2 uv_offset;
@@ -168,13 +180,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t barrier = RD::BARRIER_MASK_ALL;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, 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_mesh_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, 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_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
pass_mode = p_pass_mode;
+ color_pass_flags = p_color_pass_flags;
no_gi = p_no_gi;
+ view_count = p_view_count;
render_pass_uniform_set = p_render_pass_uniform_set;
force_wireframe = p_force_wireframe;
uv_offset = p_uv_offset;
@@ -210,7 +224,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
INSTANCE_DATA_FLAGS_FADE_SHIFT = 24,
- INSTANCE_DATA_FLAGS_FADE_MASK = 0xFF << INSTANCE_DATA_FLAGS_FADE_SHIFT
+ INSTANCE_DATA_FLAGS_FADE_MASK = 0xFFUL << INSTANCE_DATA_FLAGS_FADE_SHIFT
};
struct SceneState {
@@ -218,8 +232,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
- float camera_matrix[16];
- float inv_camera_matrix[16];
+ float inv_view_matrix[16];
+ float view_matrix[16];
+
+ float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
float viewport_size[2];
float screen_pixel_size[2];
@@ -289,6 +306,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float reflection_multiplier;
uint32_t pancake_shadows;
+
+ float taa_jitter[2];
+ uint32_t pad[2];
};
struct PushConstant {
@@ -299,6 +319,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct InstanceData {
float transform[16];
+ float prev_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)
@@ -306,7 +327,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float lightmap_uv_scale[4];
};
- UBO ubo;
+ UBO ubo_data[2];
+ UBO &ubo = ubo_data[0];
+ UBO &prev_ubo = ubo_data[1];
LocalVector<RID> uniform_buffers;
@@ -321,7 +344,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 };
LocalVector<InstanceData> instance_data[RENDER_LIST_MAX];
- LightmapCaptureData *lightmap_captures;
+ LightmapCaptureData *lightmap_captures = nullptr;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
@@ -370,7 +393,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t lod_index : 8;
};
- template <PassMode p_pass_mode>
+ template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0>
_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);
@@ -385,7 +408,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false);
- Map<Size2i, RID> sdfgi_framebuffer_size_cache;
+ HashMap<Size2i, RID> sdfgi_framebuffer_size_cache;
struct GeometryInstanceData;
struct GeometryInstanceForwardClustered;
@@ -481,7 +504,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
//used during setup
uint32_t base_flags = 0;
+ uint64_t prev_transform_change_frame = 0xFFFFFFFF;
+ bool prev_transform_dirty = true;
Transform3D transform;
+ Transform3D prev_transform;
RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE];
RID lightmap_instance;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
@@ -600,7 +626,7 @@ protected:
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
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) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 24be451e78..cfb30ef2f3 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -32,6 +32,8 @@
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
#include "render_forward_clustered.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
using namespace RendererSceneRenderImplementation;
@@ -53,10 +55,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
- int cull = CULL_BACK;
+ int cull_modei = CULL_BACK;
uses_point_size = false;
uses_alpha = false;
+ uses_alpha_clip = false;
uses_blend_alpha = false;
uses_depth_pre_pass = false;
uses_discard = false;
@@ -98,15 +101,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
- actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED);
- actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT);
- actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK);
+ actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
+ actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
+ actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
actions.render_mode_flags["unshaded"] = &unshaded;
actions.render_mode_flags["wireframe"] = &wireframe;
actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
+ actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -141,6 +145,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
+ cull_mode = Cull(cull_modei);
#if 0
print_line("**compiling shader:");
@@ -149,7 +154,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- Map<String, String>::Element * el = gen_code.code.front();
+ RBMap<String, String>::Element *el = gen_code.code.front();
while (el) {
print_line("\n**code " + el->key() + ":\n" + el->value());
@@ -230,10 +235,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
}
- RD::PipelineColorBlendState blend_state_blend;
- blend_state_blend.attachments.push_back(blend_attachment);
- RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
- RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
+ // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular, attachment 2: Motion Vectors
+ RD::PipelineColorBlendState blend_state_color_blend;
+ blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment(), RD::PipelineColorBlendState::Attachment() };
+ RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(3);
RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1);
RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2);
@@ -254,7 +259,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
};
- RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull];
+ RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull_mode];
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
@@ -276,12 +281,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
+ SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
};
shader_version = shader_version_table[k];
@@ -293,42 +294,74 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
raster_state.cull_mode = cull_mode_rd;
raster_state.wireframe = wireframe;
- RD::PipelineColorBlendState blend_state;
- RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
- RD::PipelineMultisampleState multisample_state;
-
- if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS) {
- if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
- multisample_state.enable_alpha_to_coverage = true;
- } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
- multisample_state.enable_alpha_to_coverage = true;
- multisample_state.enable_alpha_to_one = true;
+ if (k == PIPELINE_VERSION_COLOR_PASS) {
+ for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
+ if (!shader_singleton->valid_color_pass_pipelines.has(l)) {
+ continue;
+ }
+
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+ RD::PipelineMultisampleState multisample_state;
+
+ int shader_flags = 0;
+ if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
+ if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ multisample_state.enable_alpha_to_one = true;
+ }
+
+ blend_state = blend_state_color_blend;
+
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ }
+ } else {
+ blend_state = blend_state_color_opaque;
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ }
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_MOTION_VECTORS;
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP;
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ int variant = shader_version + shader_flags;
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, variant);
+ color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
-
- blend_state = blend_state_blend;
-
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
- }
- } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS) {
- blend_state = blend_state_opaque;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
} else {
- //specular write
- blend_state = blend_state_opaque_specular;
- }
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+ RD::PipelineMultisampleState multisample_state;
+
+ if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) {
+ //none, leave empty
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal_roughness;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ blend_state = blend_state_depth_normal_roughness_giprobe;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
+ blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
+ blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
+ }
- RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ }
}
}
}
@@ -347,14 +380,14 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St
}
} else {
if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
+ default_texture_params[p_name] = HashMap<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
+ HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
@@ -375,13 +408,13 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
}
}
-void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -423,8 +456,6 @@ RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_s
SceneShaderForwardClustered::ShaderData::ShaderData() :
shader_list_element(this) {
- valid = false;
- uses_screen_texture = false;
}
SceneShaderForwardClustered::ShaderData::~ShaderData() {
@@ -436,7 +467,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -450,7 +481,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
next_pass = p_pass;
}
-bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER);
@@ -460,7 +491,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -475,17 +506,20 @@ SceneShaderForwardClustered::SceneShaderForwardClustered() {
}
SceneShaderForwardClustered::~SceneShaderForwardClustered() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(overdraw_material_shader);
- storage->free(default_shader);
+ material_storage->shader_free(overdraw_material_shader);
+ material_storage->shader_free(default_shader);
- storage->free(overdraw_material);
- storage->free(default_material);
+ material_storage->material_free(overdraw_material);
+ material_storage->material_free(default_material);
}
void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{
@@ -496,27 +530,75 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
- shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
- shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
+
+ Vector<String> color_pass_flags = {
+ "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
+ "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP
+ "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW
+ "\n#define MOTION_VECTORS\n", // SHADER_COLOR_PASS_FLAG_MOTION_VECTORS
+ };
+
+ for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
+ String version = "";
+ for (int j = 0; (1 << j) < SHADER_COLOR_PASS_FLAG_COUNT; j += 1) {
+ if ((1 << j) & i) {
+ version += color_pass_flags[j];
+ }
+ }
+ shader_versions.push_back(version);
+ }
shader.initialize(shader_versions, p_defines);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
+ // TODO Add a way to enable/disable color pass flags
+ }
}
- 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);
+ valid_color_pass_pipelines.insert(0);
+
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
+
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
ShaderCompiler::DefaultIdentifierActions actions;
- actions.renames["WORLD_MATRIX"] = "world_matrix";
- actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix";
- actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix";
- actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix";
+ actions.renames["MODEL_MATRIX"] = "model_matrix";
+ actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix";
+ actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix";
+ actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix";
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
- actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix";
+ actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions.renames["MODELVIEW_MATRIX"] = "modelview";
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
@@ -539,7 +621,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
//builtins
- actions.renames["TIME"] = "scene_data.time";
+ actions.renames["TIME"] = "scene_data_block.data.time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -587,8 +669,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
- // not implemented but need these just in case code is in the shaders
- actions.renames["VIEW_INDEX"] = "0";
+ actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -597,7 +678,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT"] = "light";
actions.renames["ATTENUATION"] = "attenuation";
- actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation";
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
actions.renames["SPECULAR_LIGHT"] = "specular_light";
@@ -680,21 +760,21 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
+ actions.base_varying_index = 11;
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 = "instances.data[instance_index_interp].instance_uniforms_ofs";
compiler.initialize(actions);
}
{
//default material and shader
- default_shader = storage->shader_allocate();
- storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, R"(
+ default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_shader);
+ material_storage->shader_set_code(default_shader, R"(
// Default 3D material shader (clustered).
shader_type spatial;
@@ -709,11 +789,11 @@ void fragment() {
METALLIC = 0.2;
}
)");
- default_material = storage->material_allocate();
- storage->material_initialize(default_material);
- storage->material_set_shader(default_material, default_shader);
+ default_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_material);
+ material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
@@ -722,10 +802,10 @@ void fragment() {
}
{
- overdraw_material_shader = storage->shader_allocate();
- storage->shader_initialize(overdraw_material_shader);
+ overdraw_material_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
- storage->shader_set_code(overdraw_material_shader, R"(
+ material_storage->shader_set_code(overdraw_material_shader, R"(
// 3D editor Overdraw debug draw mode shader (clustered).
shader_type spatial;
@@ -737,11 +817,11 @@ void fragment() {
ALPHA = 0.1;
}
)");
- overdraw_material = storage->material_allocate();
- storage->material_initialize(overdraw_material);
- storage->material_set_shader(overdraw_material, overdraw_material_shader);
+ overdraw_material = material_storage->material_allocate();
+ material_storage->material_initialize(overdraw_material);
+ material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
@@ -751,7 +831,7 @@ void fragment() {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(default_vec4_xform_buffer);
+ u.append_id(default_vec4_xform_buffer);
u.binding = 0;
uniforms.push_back(u);
@@ -775,6 +855,9 @@ void SceneShaderForwardClustered::set_default_specialization_constants(const Vec
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
}
+ for (int k = 0; k < PIPELINE_COLOR_PASS_FLAG_COUNT; k++) {
+ E->self()->color_pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
+ }
}
}
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 33049fad9c..79ccf10090 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -42,7 +42,7 @@ private:
static SceneShaderForwardClustered *singleton;
public:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
@@ -51,13 +51,19 @@ public:
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
+ SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
SHADER_VERSION_MAX
};
+ enum ShaderColorPassFlags {
+ SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0,
+ SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1,
+ SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2,
+ SHADER_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 3,
+ SHADER_COLOR_PASS_FLAG_COUNT = 1 << 4
+ };
+
enum PipelineVersion {
PIPELINE_VERSION_DEPTH_PASS,
PIPELINE_VERSION_DEPTH_PASS_DP,
@@ -65,15 +71,20 @@ public:
PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
- PIPELINE_VERSION_OPAQUE_PASS,
- PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_TRANSPARENT_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS,
+ PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW,
+ PIPELINE_VERSION_COLOR_PASS,
PIPELINE_VERSION_MAX
};
+ enum PipelineColorPassFlags {
+ PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
+ PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
+ PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 4,
+ PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 5,
+ };
+
enum ShaderSpecializations {
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
@@ -81,7 +92,7 @@ public:
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
};
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct ShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -121,46 +132,48 @@ public:
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
};
- bool valid;
+ bool valid = false;
RID version;
- uint32_t vertex_input_mask;
+ uint32_t vertex_input_mask = 0;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
+ PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
String path;
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String code;
- Map<StringName, Map<int, RID>> default_texture_params;
+ HashMap<StringName, HashMap<int, 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 uses_particle_trails;
-
- bool unshaded;
- bool uses_vertex;
- bool uses_position;
- 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;
+ bool uses_point_size = false;
+ bool uses_alpha = false;
+ bool uses_blend_alpha = false;
+ bool uses_alpha_clip = false;
+ bool uses_depth_pre_pass = false;
+ bool uses_discard = false;
+ bool uses_roughness = false;
+ bool uses_normal = false;
+ bool uses_particle_trails = false;
+
+ bool unshaded = false;
+ bool uses_vertex = false;
+ bool uses_position = false;
+ bool uses_sss = false;
+ bool uses_transmittance = false;
+ bool uses_screen_texture = false;
+ bool uses_depth_texture = false;
+ bool uses_normal_texture = false;
+ bool uses_time = false;
+ bool writes_modelview_or_projection = false;
+ bool uses_world_coordinates = false;
+ Cull cull_mode = CULL_DISABLED;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -168,7 +181,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -183,13 +196,13 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct MaterialData : public RendererRD::MaterialData {
+ ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -197,12 +210,12 @@ public:
uint8_t priority;
virtual void set_render_priority(int p_priority);
virtual void set_next_pass(RID p_pass);
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const HashMap<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) {
+ RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -228,6 +241,7 @@ public:
ShaderData *overdraw_material_shader_ptr = nullptr;
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
+ HashSet<uint32_t> valid_color_pass_pipelines;
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index a623af7533..b2e0af06cd 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -30,6 +30,10 @@
#include "render_forward_mobile.h"
#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -83,7 +87,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
}
}
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
clear();
msaa = p_msaa;
@@ -154,7 +158,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
tf.array_layers = view_count; // create a layer for every view
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] = {
+ const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
RD::TEXTURE_SAMPLES_1,
RD::TEXTURE_SAMPLES_2,
RD::TEXTURE_SAMPLES_4,
@@ -289,12 +293,14 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() {
}
RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
//there should always be enough uniform buffers for render passes, otherwise bugs
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
RenderBufferDataForwardMobile *rb = nullptr;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers);
+ rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
}
// default render buffer and scene state uniform set
@@ -306,7 +312,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(scene_state.uniform_buffers[p_index]);
+ u.append_id(scene_state.uniform_buffers[p_index]);
uniforms.push_back(u);
}
@@ -315,12 +321,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
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);
+ radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(radiance_texture);
+ u.append_id(radiance_texture);
uniforms.push_back(u);
}
@@ -330,9 +336,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (ref_texture.is_valid()) {
- u.ids.push_back(ref_texture);
+ u.append_id(ref_texture);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
}
uniforms.push_back(u);
}
@@ -346,9 +352,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
}
- u.ids.push_back(texture);
+ u.append_id(texture);
uniforms.push_back(u);
}
{
@@ -356,9 +362,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
- u.ids.push_back(directional_shadow_get_texture());
+ u.append_id(directional_shadow_get_texture());
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -368,16 +374,16 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 6;
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);
+
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
- RID texture = storage->lightmap_get_texture(base);
- RID rd_texture = storage->texture_get_rd_texture(texture);
- u.ids.write[i] = rd_texture;
+ RID texture = RendererRD::LightStorage::get_singleton()->lightmap_get_texture(base);
+ RID rd_texture = texture_storage->texture_get_rd_texture(texture);
+ u.append_id(rd_texture);
} else {
- u.ids.write[i] = default_tex;
+ u.append_id(default_tex);
}
}
@@ -390,7 +396,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
- RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
if (i < (int)p_voxel_gi_instances.size()) {
RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]);
@@ -411,7 +417,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer;
- u.ids.push_back(cb);
+ u.append_id(cb);
uniforms.push_back(u);
}
*/
@@ -421,8 +427,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
- u.ids.push_back(texture);
+ RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ u.append_id(texture);
uniforms.push_back(u);
}
{
@@ -430,8 +436,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
- RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(texture);
+ RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
uniforms.push_back(u);
}
@@ -461,7 +467,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
to_lm = to_lm.inverse().transposed(); //will transform normals
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.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
scene_state.lightmaps_used++;
}
@@ -473,15 +479,12 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RenderBufferDataForwardMobile *render_buffer = nullptr;
if (p_render_data->render_buffers.is_valid()) {
- render_buffer = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers);
+ render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
}
RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
RENDER_TIMESTAMP("Setup 3D Scene");
- Vector2 vp_he = p_render_data->cam_projection.get_viewport_half_extents();
- scene_state.ubo.viewport_size[0] = vp_he.x;
- scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
scene_state.ubo.opaque_prepass_threshold = 0.0;
@@ -549,7 +552,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
env = nullptr;
}
@@ -561,6 +564,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
ERR_FAIL(); //bug?
}
+ scene_state.ubo.viewport_size[0] = screen_size.x;
+ scene_state.ubo.viewport_size[1] = screen_size.y;
+
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
@@ -592,7 +598,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
*/
} break;
@@ -604,7 +610,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
*/
} break;
@@ -653,9 +659,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only) {
// !BAS! @TODO See if we can limit doing some things double and maybe even move this into _pre_opaque_render
// and change Forward Clustered in the same way as we have here (but without using subpasses)
- RENDER_TIMESTAMP("Setup Sky resolution buffers");
+ RENDER_TIMESTAMP("Setup Sky Resolution Buffers");
- RD::get_singleton()->draw_command_begin_label("Setup Sky resolution buffers");
+ RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers");
if (p_render_data->reflection_probe.is_valid()) {
CameraMatrix correction;
@@ -719,10 +725,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
{
// regular forward for now
Vector<Color> c;
- c.push_back(clear_color.to_linear()); // our render buffer
+ c.push_back(clear_color.srgb_to_linear()); // our render buffer
if (render_buffer) {
if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- c.push_back(clear_color.to_linear()); // our resolve buffer
+ c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
}
if (using_subpass_post_process) {
c.push_back(Color()); // our 2D buffer we're copying into
@@ -971,10 +977,10 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
-void RenderForwardMobile::_render_material(const Transform3D &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");
+void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+ RENDER_TIMESTAMP("Setup Rendering 3D Material");
- RD::get_singleton()->draw_command_begin_label("Render Material");
+ RD::get_singleton()->draw_command_begin_label("Render 3D Material");
_update_render_base_uniform_set();
@@ -997,7 +1003,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
- RENDER_TIMESTAMP("Render Material");
+ RENDER_TIMESTAMP("Render 3D Material");
{
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, 0);
@@ -1039,7 +1045,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
- RENDER_TIMESTAMP("Render Material");
+ RENDER_TIMESTAMP("Render 3D Material");
{
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true, false);
@@ -1089,7 +1095,7 @@ void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_
}
void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
- RENDER_TIMESTAMP("Setup Render Collider Heightfield");
+ RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -1133,35 +1139,39 @@ void RenderForwardMobile::_base_uniforms_changed() {
}
void RenderForwardMobile::_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())) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_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);
}
// This is all loaded into set 0
- lightmap_texture_array_version = storage->lightmap_array_get_version();
+ lightmap_texture_array_version = light_storage->lightmap_array_get_version();
Vector<RD::Uniform> uniforms;
{
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 1;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+
uniforms.push_back(u);
}
@@ -1169,7 +1179,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.ids.push_back(scene_shader.shadow_sampler);
+ u.append_id(scene_shader.shadow_sampler);
uniforms.push_back(u);
}
@@ -1180,23 +1190,23 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
- u.ids.push_back(sampler);
+ u.append_id(sampler);
uniforms.push_back(u);
}
@@ -1207,23 +1217,23 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
- u.ids.push_back(sampler);
+ u.append_id(sampler);
uniforms.push_back(u);
}
@@ -1231,14 +1241,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_omni_light_buffer());
+ u.append_id(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_spot_light_buffer());
+ u.append_id(get_spot_light_buffer());
uniforms.push_back(u);
}
@@ -1246,51 +1256,51 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_reflection_probe_buffer());
+ u.append_id(get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(get_directional_light_buffer());
+ u.append_id(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.lightmap_buffer);
+ u.append_id(scene_state.lightmap_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.lightmap_capture_buffer);
+ u.append_id(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = storage->decal_atlas_get_texture();
- u.ids.push_back(decal_atlas);
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
+ u.append_id(decal_atlas);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = storage->decal_atlas_get_texture_srgb();
- u.ids.push_back(decal_atlas);
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_srgb();
+ u.append_id(decal_atlas);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_decal_buffer());
+ u.append_id(get_decal_buffer());
uniforms.push_back(u);
}
@@ -1298,7 +1308,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.ids.push_back(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1314,6 +1324,10 @@ RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers
return RID();
}
+RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) {
+ return RID();
+}
+
_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) {
static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 };
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
@@ -1321,6 +1335,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
}
void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
@@ -1329,7 +1345,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
+ Plane near_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1410,7 +1426,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1429,12 +1445,12 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
distance = -distance_max;
}
- if (p_render_data->cam_ortogonal) {
+ if (p_render_data->cam_orthogonal) {
distance = 1.0;
}
uint32_t indices;
- surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1446,13 +1462,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
} else {
surf->lod_index = 0;
if (p_render_data->render_info) {
- uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
} else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
}
}
}
@@ -1519,8 +1535,8 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
//store camera into ubo
RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
+ RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
+ RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
projection = correction * p_render_data->view_projection[v];
@@ -1562,7 +1578,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_enabled = false;
if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardMobile *render_buffers = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers);
+ RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
scene_state.ubo.gi_upscale_for_msaa = true;
}
@@ -1609,7 +1625,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
@@ -1619,7 +1635,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
} else {
float energy = environment_get_ambient_light_energy(p_render_data->environment);
Color color = environment_get_ambient_light_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
@@ -1650,7 +1666,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
- Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
+ Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
@@ -1660,12 +1676,12 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
} else {
- if (p_render_data->reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
scene_state.ubo.use_ambient_light = false;
} else {
scene_state.ubo.use_ambient_light = true;
Color clear_color = p_default_bg_color;
- clear_color = clear_color.to_linear();
+ clear_color = clear_color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
@@ -1810,6 +1826,8 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF
template <RenderForwardMobile::PassMode p_pass_mode>
void RenderForwardMobile::_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) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -1952,12 +1970,12 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
//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);
+ mesh_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);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
+ index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -2276,8 +2294,10 @@ void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geom
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
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_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha);
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
bool has_alpha = has_base_alpha || has_blend_alpha;
@@ -2322,14 +2342,14 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
SceneShaderForwardMobile::MaterialData *material_shadow = nullptr;
void *surface_shadow = nullptr;
- if (!p_material->shader_data->uses_particle_trails && !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) {
+ if (!p_material->shader_data->uses_particle_trails && !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 && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
- RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+ RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
if (shadow_mesh.is_valid()) {
- surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface);
}
} else {
@@ -2342,8 +2362,8 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
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 = mesh_storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
@@ -2377,23 +2397,25 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
SceneShaderForwardMobile::MaterialData *material = p_material;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::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);
+ material_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);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
}
}
void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2401,7 +2423,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
SceneShaderForwardMobile::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2409,10 +2431,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (material) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2423,10 +2445,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
@@ -2435,6 +2457,8 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
}
void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2448,7 +2472,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
uint32_t surface_count;
RID mesh = ginstance->data->base;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_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();
@@ -2465,19 +2489,19 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
} break;
case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ RID mesh = 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);
+ materials = mesh_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);
+ ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
@@ -2491,10 +2515,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
} break;
#endif
case RS::INSTANCE_PARTICLES: {
- int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+ int draw_passes = particles_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);
+ RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
if (!mesh.is_valid()) {
continue;
}
@@ -2502,7 +2526,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_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);
@@ -2510,7 +2534,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
}
}
- ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
+ ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
} break;
@@ -2525,17 +2549,17 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
- if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
}
- if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2549,16 +2573,16 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
//for particles, stride is the trail size
ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
- if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+ if (!particles_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, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
- if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
- ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
if (ginstance->data->dirty_dependencies) {
- storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
}
}
}
@@ -2591,7 +2615,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage:
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RenderForwardMobile *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 8274dc3b0c..fc6f32ecb0 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -136,7 +136,7 @@ protected:
uint32_t view_count;
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
~RenderBufferDataForwardMobile();
};
@@ -214,7 +214,7 @@ protected:
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
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) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
@@ -224,6 +224,7 @@ protected:
virtual void _base_uniforms_changed() override;
void _update_render_base_uniform_set();
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
+ virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);
@@ -254,8 +255,8 @@ protected:
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
- float camera_matrix[16];
- float inv_camera_matrix[16];
+ float inv_view_matrix[16];
+ float view_matrix[16];
float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
@@ -328,7 +329,7 @@ protected:
uint32_t max_lightmaps;
RID lightmap_buffer;
- LightmapCaptureData *lightmap_captures;
+ LightmapCaptureData *lightmap_captures = nullptr;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 34b2fa9440..f66ad529de 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "render_forward_mobile.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
using namespace RendererSceneRenderImplementation;
@@ -60,6 +61,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_point_size = false;
uses_alpha = false;
+ uses_alpha_clip = false;
uses_blend_alpha = false;
uses_depth_pre_pass = false;
uses_discard = false;
@@ -109,6 +111,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
+ actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
// actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -151,7 +154,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- Map<String, String>::Element * el = gen_code.code.front();
+ RBMap<String, String>::Element * el = gen_code.code.front();
while (el) {
print_line("\n**code " + el->key() + ":\n" + el->value());
@@ -293,7 +296,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_blend;
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
@@ -336,14 +339,14 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin
}
} else {
if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
+ default_texture_params[p_name] = HashMap<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
+ HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
@@ -364,13 +367,13 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
}
}
-void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -412,8 +415,6 @@ RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_sour
SceneShaderForwardMobile::ShaderData::ShaderData() :
shader_list_element(this) {
- valid = false;
- uses_screen_texture = false;
}
SceneShaderForwardMobile::ShaderData::~ShaderData() {
@@ -425,7 +426,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -439,7 +440,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
next_pass = p_pass;
}
-bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER);
@@ -449,7 +450,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -467,6 +468,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
storage = p_storage;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
/* SCENE SHADER */
@@ -492,17 +494,17 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
- 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);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
ShaderCompiler::DefaultIdentifierActions actions;
- actions.renames["WORLD_MATRIX"] = "world_matrix";
- actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix";
- actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix";
- actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix";
+ actions.renames["MODEL_MATRIX"] = "model_matrix";
+ actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix";
+ actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix";
+ actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix";
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions.renames["MODELVIEW_MATRIX"] = "modelview";
@@ -527,7 +529,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
//builtins
- actions.renames["TIME"] = "scene_data.time";
+ actions.renames["TIME"] = "scene_data_block.data.time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -584,7 +586,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT"] = "light";
actions.renames["ATTENUATION"] = "attenuation";
- actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation";
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
actions.renames["SPECULAR_LIGHT"] = "specular_light";
@@ -676,9 +677,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
{
//default material and shader
- default_shader = storage->shader_allocate();
- storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, R"(
+ default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_shader);
+ material_storage->shader_set_code(default_shader, R"(
// Default 3D material shader (mobile).
shader_type spatial;
@@ -693,11 +694,11 @@ void fragment() {
METALLIC = 0.2;
}
)");
- default_material = storage->material_allocate();
- storage->material_initialize(default_material);
- storage->material_set_shader(default_material, default_shader);
+ default_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_material);
+ material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_material_shader_ptr = md->shader_data;
@@ -705,10 +706,10 @@ void fragment() {
}
{
- overdraw_material_shader = storage->shader_allocate();
- storage->shader_initialize(overdraw_material_shader);
+ overdraw_material_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
- storage->shader_set_code(overdraw_material_shader, R"(
+ material_storage->shader_set_code(overdraw_material_shader, R"(
// 3D editor Overdraw debug draw mode shader (mobile).
shader_type spatial;
@@ -720,11 +721,11 @@ void fragment() {
ALPHA = 0.1;
}
)");
- overdraw_material = storage->material_allocate();
- storage->material_initialize(overdraw_material);
- storage->material_set_shader(overdraw_material, overdraw_material_shader);
+ overdraw_material = material_storage->material_allocate();
+ material_storage->material_initialize(overdraw_material);
+ material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
@@ -734,7 +735,7 @@ void fragment() {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(default_vec4_xform_buffer);
+ u.append_id(default_vec4_xform_buffer);
u.binding = 0;
uniforms.push_back(u);
@@ -764,12 +765,14 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector
}
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(overdraw_material_shader);
- storage->free(default_shader);
+ material_storage->shader_free(overdraw_material_shader);
+ material_storage->shader_free(default_shader);
- storage->free(overdraw_material);
- storage->free(default_material);
+ material_storage->material_free(overdraw_material);
+ material_storage->material_free(default_material);
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 92db15e3b0..f325d5c0a5 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -40,7 +40,7 @@ namespace RendererSceneRenderImplementation {
class SceneShaderForwardMobile {
private:
static SceneShaderForwardMobile *singleton;
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
public:
enum ShaderVersion {
@@ -57,7 +57,7 @@ public:
SHADER_VERSION_MAX
};
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct ShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -97,45 +97,45 @@ public:
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
};
- bool valid;
+ bool valid = false;
RID version;
- uint32_t vertex_input_mask;
+ uint32_t vertex_input_mask = 0;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
String path;
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String code;
- Map<StringName, Map<int, RID>> default_texture_params;
+ HashMap<StringName, HashMap<int, 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 uses_particle_trails;
-
- 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;
+ bool uses_point_size = false;
+ bool uses_alpha = false;
+ bool uses_blend_alpha = false;
+ bool uses_alpha_clip = false;
+ bool uses_depth_pre_pass = false;
+ bool uses_discard = false;
+ bool uses_roughness = false;
+ bool uses_normal = false;
+ bool uses_particle_trails = false;
+
+ bool unshaded = false;
+ bool uses_vertex = false;
+ bool uses_sss = false;
+ bool uses_transmittance = false;
+ bool uses_screen_texture = false;
+ bool uses_depth_texture = false;
+ bool uses_normal_texture = false;
+ bool uses_time = false;
+ bool writes_modelview_or_projection = false;
+ bool uses_world_coordinates = false;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -143,7 +143,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -157,13 +157,13 @@ public:
virtual ~ShaderData();
};
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct MaterialData : public RendererRD::MaterialData {
+ ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -171,14 +171,14 @@ public:
uint8_t priority;
virtual void set_render_priority(int p_priority);
virtual void set_next_pass(RID p_pass);
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~MaterialData();
};
SelfList<ShaderData>::List shader_list;
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index e812a48d3d..9151c53823 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -58,7 +58,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass, specialization_constants);
ERR_FAIL_COND_V(pipeline.is_null(), RID());
- versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
+ versions = static_cast<Version *>(memrealloc(versions, sizeof(Version) * (version_count + 1)));
versions[version_count].framebuffer_id = p_framebuffer_format_id;
versions[version_count].vertex_id = p_vertex_format_id;
versions[version_count].wireframe = wireframe;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 8d82480b38..ad83fc76b7 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -45,7 +45,7 @@ class PipelineCacheRD {
RD::PipelineMultisampleState multisample_state;
RD::PipelineDepthStencilState depth_stencil_state;
RD::PipelineColorBlendState blend_state;
- int dynamic_state_flags;
+ int dynamic_state_flags = 0;
Vector<RD::PipelineSpecializationConstant> base_specialization_constants;
struct Version {
@@ -57,7 +57,7 @@ class PipelineCacheRD {
RID pipeline;
};
- Version *versions;
+ Version *versions = nullptr;
uint32_t version_count;
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 0f3daef371..3c2f3f8a42 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -35,60 +35,63 @@
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
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[0] = p_transform.columns[0][0];
+ p_mat4[1] = p_transform.columns[0][1];
p_mat4[2] = 0;
p_mat4[3] = 0;
- p_mat4[4] = p_transform.elements[1][0];
- p_mat4[5] = p_transform.elements[1][1];
+ p_mat4[4] = p_transform.columns[1][0];
+ p_mat4[5] = p_transform.columns[1][1];
p_mat4[6] = 0;
p_mat4[7] = 0;
p_mat4[8] = 0;
p_mat4[9] = 0;
p_mat4[10] = 1;
p_mat4[11] = 0;
- p_mat4[12] = p_transform.elements[2][0];
- p_mat4[13] = p_transform.elements[2][1];
+ p_mat4[12] = p_transform.columns[2][0];
+ p_mat4[13] = p_transform.columns[2][1];
p_mat4[14] = 0;
p_mat4[15] = 1;
}
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[0] = p_transform.columns[0][0];
+ p_mat2x4[1] = p_transform.columns[1][0];
p_mat2x4[2] = 0;
- p_mat2x4[3] = p_transform.elements[2][0];
+ p_mat2x4[3] = p_transform.columns[2][0];
- p_mat2x4[4] = p_transform.elements[0][1];
- p_mat2x4[5] = p_transform.elements[1][1];
+ p_mat2x4[4] = p_transform.columns[0][1];
+ p_mat2x4[5] = p_transform.columns[1][1];
p_mat2x4[6] = 0;
- p_mat2x4[7] = p_transform.elements[2][1];
+ p_mat2x4[7] = p_transform.columns[2][1];
}
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];
- p_mat2x3[3] = p_transform.elements[1][1];
- p_mat2x3[4] = p_transform.elements[2][0];
- p_mat2x3[5] = p_transform.elements[2][1];
+ p_mat2x3[0] = p_transform.columns[0][0];
+ p_mat2x3[1] = p_transform.columns[0][1];
+ p_mat2x3[2] = p_transform.columns[1][0];
+ p_mat2x3[3] = p_transform.columns[1][1];
+ p_mat2x3[4] = p_transform.columns[2][0];
+ p_mat2x3[5] = p_transform.columns[2][1];
}
void RendererCanvasRenderRD::_update_transform_to_mat4(const Transform3D &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];
+ p_mat4[0] = p_transform.basis.rows[0][0];
+ p_mat4[1] = p_transform.basis.rows[1][0];
+ p_mat4[2] = p_transform.basis.rows[2][0];
p_mat4[3] = 0;
- p_mat4[4] = p_transform.basis.elements[0][1];
- p_mat4[5] = p_transform.basis.elements[1][1];
- p_mat4[6] = p_transform.basis.elements[2][1];
+ p_mat4[4] = p_transform.basis.rows[0][1];
+ p_mat4[5] = p_transform.basis.rows[1][1];
+ p_mat4[6] = p_transform.basis.rows[2][1];
p_mat4[7] = 0;
- p_mat4[8] = p_transform.basis.elements[0][2];
- p_mat4[9] = p_transform.basis.elements[1][2];
- p_mat4[10] = p_transform.basis.elements[2][2];
+ p_mat4[8] = p_transform.basis.rows[0][2];
+ p_mat4[9] = p_transform.basis.rows[1][2];
+ p_mat4[10] = p_transform.basis.rows[2][2];
p_mat4[11] = 0;
p_mat4[12] = p_transform.origin.x;
p_mat4[13] = p_transform.origin.y;
@@ -105,6 +108,8 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
// This dramatically reduces the amount of pipeline objects
// that need to be created for these formats.
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
uint32_t vertex_count = p_points.size();
uint32_t stride = 2; //vertices always repeat
if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) {
@@ -127,9 +132,9 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
buffers.resize(5);
{
- const uint8_t *r = polygon_buffer.ptr();
- float *fptr = (float *)r;
- uint32_t *uptr = (uint32_t *)r;
+ uint8_t *r = polygon_buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(r);
+ uint32_t *uptr = reinterpret_cast<uint32_t *>(r);
uint32_t base_offset = 0;
{ //vertices
RD::VertexAttribute vd;
@@ -187,7 +192,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[1] = vd;
- buffers.write[1] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_COLOR);
+ buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR);
}
//uvs
@@ -215,7 +220,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[2] = vd;
- buffers.write[2] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_TEX_UV);
+ buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV);
}
//bones
@@ -248,7 +253,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[3] = vd;
- buffers.write[3] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES);
+ buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES);
}
//weights
@@ -281,7 +286,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_WEIGHTS);
+ buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -358,7 +363,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
bool use_normal;
bool use_specular;
- bool success = storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+ bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
//something odd happened
if (!success) {
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -395,6 +400,9 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
//create an empty push constant
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
RS::CanvasItemTextureFilter current_filter = default_filter;
RS::CanvasItemTextureRepeat current_repeat = default_repeat;
@@ -694,9 +702,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
_bind_canvas_texture(p_draw_list, RID(), current_filter, current_repeat, last_texture, push_constant, texpixel_size);
- RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3, primitive->point_count) - 1]);
+ RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]);
- for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) {
+ for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) {
push_constant.points[j * 2 + 0] = primitive->points[j].x;
push_constant.points[j * 2 + 1] = primitive->points[j].y;
push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x;
@@ -749,48 +757,48 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
RID multimesh = mm->multimesh;
- mesh = storage->multimesh_get_mesh(multimesh);
+ mesh = mesh_storage->multimesh_get_mesh(multimesh);
texture = mm->texture;
- if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
break;
}
- instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
if (instance_count == 0) {
break;
}
- RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
+ RID uniform_set = mesh_storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= 1; //multimesh, trails disabled
- if (storage->multimesh_uses_colors(multimesh)) {
+ if (mesh_storage->multimesh_uses_colors(multimesh)) {
push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;
}
- if (storage->multimesh_uses_custom_data(multimesh)) {
+ if (mesh_storage->multimesh_uses_custom_data(multimesh)) {
push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
}
} else if (c->type == Item::Command::TYPE_PARTICLES) {
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
- ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
- storage->particles_request_process(pt->particles);
+ ERR_BREAK(particles_storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
+ particles_storage->particles_request_process(pt->particles);
- if (storage->particles_is_inactive(pt->particles)) {
+ if (particles_storage->particles_is_inactive(pt->particles)) {
break;
}
RenderingServerDefault::redraw_request(); // active particles means redraw request
bool local_coords = true;
- int dpc = storage->particles_get_draw_passes(pt->particles);
+ int dpc = particles_storage->particles_get_draw_passes(pt->particles);
if (dpc == 0) {
break; //nothing to draw
}
uint32_t divisor = 1;
- instance_count = storage->particles_get_amount(pt->particles, divisor);
+ instance_count = particles_storage->particles_get_amount(pt->particles, divisor);
- RID uniform_set = storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
+ RID uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= divisor;
@@ -799,10 +807,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;
push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
- mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
+ mesh = particles_storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
texture = pt->texture;
- if (storage->particles_has_collision(pt->particles) && storage->render_target_is_sdf_enabled(p_render_target)) {
+ if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
//pass collision information
Transform2D xform;
if (local_coords) {
@@ -811,19 +819,19 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
xform = p_canvas_transform_inverse;
}
- RID sdf_texture = storage->render_target_get_sdf_texture(p_render_target);
+ RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
Rect2 to_screen;
{
- Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_render_target);
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_render_target);
to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
to_screen.position = -sdf_rect.position * to_screen.size;
}
- storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
} else {
- storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
}
}
@@ -833,7 +841,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
_bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
- uint32_t surf_count = storage->mesh_get_surface_count(mesh);
+ uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
push_constant.modulation[0] = base_color.r * modulate.r;
@@ -848,9 +856,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
for (uint32_t j = 0; j < surf_count; j++) {
- void *surface = storage->mesh_get_surface(mesh, j);
+ void *surface = mesh_storage->mesh_get_surface(mesh, j);
- RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface);
+ RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask();
@@ -859,15 +867,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID;
if (mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
}
RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- RID index_array = storage->mesh_surface_get_index_array(surface, 0);
+ RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0);
if (index_array.is_valid()) {
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array);
@@ -924,6 +932,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
//re create canvas state
Vector<RD::Uniform> uniforms;
@@ -931,7 +942,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 1;
- u.ids.push_back(state.canvas_state_buffer);
+ u.append_id(state.canvas_state_buffer);
uniforms.push_back(u);
}
@@ -939,7 +950,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 2;
- u.ids.push_back(state.lights_uniform_buffer);
+ u.append_id(state.lights_uniform_buffer);
uniforms.push_back(u);
}
@@ -947,7 +958,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 3;
- u.ids.push_back(storage->decal_atlas_get_texture());
+ u.append_id(RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture());
uniforms.push_back(u);
}
@@ -955,7 +966,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 4;
- u.ids.push_back(state.shadow_texture);
+ u.append_id(state.shadow_texture);
uniforms.push_back(u);
}
@@ -963,7 +974,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 5;
- u.ids.push_back(state.shadow_sampler);
+ u.append_id(state.shadow_sampler);
uniforms.push_back(u);
}
@@ -973,14 +984,14 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
u.binding = 6;
RID screen;
if (p_backbuffer) {
- screen = storage->render_target_get_rd_texture(p_to_render_target);
+ screen = texture_storage->render_target_get_rd_texture(p_to_render_target);
} else {
- screen = storage->render_target_get_rd_backbuffer(p_to_render_target);
+ screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target);
if (screen.is_null()) { //unallocated backbuffer
- screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
}
- u.ids.push_back(screen);
+ u.append_id(screen);
uniforms.push_back(u);
}
@@ -988,30 +999,31 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
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);
+ RID sdf = texture_storage->render_target_get_sdf_texture(p_to_render_target);
+ u.append_id(sdf);
uniforms.push_back(u);
}
{
//needs samplers for the material (uses custom textures) create them
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 8;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 8, ids);
+
uniforms.push_back(u);
}
@@ -1019,21 +1031,24 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 9;
- u.ids.push_back(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, BASE_UNIFORM_SET);
if (p_backbuffer) {
- storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set);
+ texture_storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set);
} else {
- storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set);
+ texture_storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set);
}
return uniform_set;
}
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) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1044,21 +1059,21 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
Vector<Color> clear_colors;
if (p_to_backbuffer) {
- framebuffer = storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
- fb_uniform_set = storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
+ framebuffer = texture_storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
+ fb_uniform_set = texture_storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
} else {
- framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
+ framebuffer = texture_storage->render_target_get_rd_framebuffer(p_to_render_target);
- if (storage->render_target_is_clear_requested(p_to_render_target)) {
+ if (texture_storage->render_target_is_clear_requested(p_to_render_target)) {
clear = true;
- clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
- storage->render_target_disable_clear_request(p_to_render_target);
+ clear_colors.push_back(texture_storage->render_target_get_clear_request_color(p_to_render_target));
+ texture_storage->render_target_disable_clear_request(p_to_render_target);
}
#ifndef _MSC_VER
#warning TODO obtain from framebuffer format eventually when this is implemented
#endif
- fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+ fb_uniform_set = texture_storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
}
if (fb_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fb_uniform_set)) {
@@ -1098,9 +1113,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
if (material != prev_material) {
- MaterialData *material_data = nullptr;
+ CanvasMaterialData *material_data = nullptr;
if (material.is_valid()) {
- material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+ material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
}
if (material_data) {
@@ -1127,6 +1142,10 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
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) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
r_sdf_used = false;
int item_count = 0;
@@ -1156,7 +1175,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
ERR_CONTINUE(!clight);
}
- Vector2 canvas_light_dir = l->xform_cache.elements[1].normalized();
+ Vector2 canvas_light_dir = l->xform_cache.columns[1].normalized();
state.light_uniforms[index].position[0] = -canvas_light_dir.x;
state.light_uniforms[index].position[1] = -canvas_light_dir.y;
@@ -1227,7 +1246,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix);
_update_transform_2d_to_mat2x4(l->xform_cache.affine_inverse(), state.light_uniforms[index].shadow_matrix);
- state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss
+ state.light_uniforms[index].height = l->height * (p_canvas_transform.columns[0].length() + p_canvas_transform.columns[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss
for (int i = 0; i < 4; i++) {
state.light_uniforms[index].shadow_color[i] = uint8_t(CLAMP(int32_t(l->shadow_color[i] * 255.0), 0, 255));
state.light_uniforms[index].color[i] = l->color[i];
@@ -1252,7 +1271,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
}
if (clight->texture.is_valid()) {
- Rect2 atlas_rect = storage->decal_atlas_get_texture_rect(clight->texture);
+ Rect2 atlas_rect = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_rect(clight->texture);
state.light_uniforms[index].atlas_rect[0] = atlas_rect.position.x;
state.light_uniforms[index].atlas_rect[1] = atlas_rect.position.y;
state.light_uniforms[index].atlas_rect[2] = atlas_rect.size.width;
@@ -1282,7 +1301,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
//update canvas state uniform buffer
State::Buffer state_buffer;
- Size2i ssize = storage->render_target_get_size(p_to_render_target);
+ Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
@@ -1291,9 +1310,9 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
Transform2D normal_transform = p_canvas_transform;
- normal_transform.elements[0].normalize();
- normal_transform.elements[1].normalize();
- normal_transform.elements[2] = Vector2();
+ normal_transform.columns[0].normalize();
+ normal_transform.columns[1].normalize();
+ normal_transform.columns[2] = Vector2();
_update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform);
state_buffer.canvas_modulate[0] = p_modulate.r;
@@ -1301,7 +1320,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
state_buffer.canvas_modulate[2] = p_modulate.b;
state_buffer.canvas_modulate[3] = p_modulate.a;
- Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
+ Size2 render_target_size = texture_storage->render_target_get_size(p_to_render_target);
state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
@@ -1318,7 +1337,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
- Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_to_render_target);
Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
@@ -1348,6 +1367,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
bool update_skeletons = false;
bool time_used = false;
+ bool backbuffer_cleared = false;
+
while (ci) {
if (ci->copy_back_buffer && canvas_group_owner == nullptr) {
backbuffer_copy = true;
@@ -1362,7 +1383,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (material.is_valid()) {
- MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+ CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::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) {
@@ -1387,7 +1408,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c);
if (cm->mesh_instance.is_valid()) {
- storage->mesh_instance_check_for_update(cm->mesh_instance);
+ mesh_storage->mesh_instance_check_for_update(cm->mesh_instance);
update_skeletons = true;
}
}
@@ -1397,20 +1418,22 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (ci->canvas_group_owner != nullptr) {
if (canvas_group_owner == nullptr) {
- //Canvas group begins here, render until before this item
+ // Canvas group begins here, render until before this item
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
+
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
- storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
- } else {
- storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+ } else if (!backbuffer_cleared) {
+ texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
+ backbuffer_cleared = true;
}
backbuffer_copy = false;
@@ -1420,9 +1443,14 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
ci->canvas_group_owner = nullptr; //must be cleared
}
+ if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) {
+ texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
+ backbuffer_cleared = true;
+ }
+
if (ci == canvas_group_owner) {
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
@@ -1430,7 +1458,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
item_count = 0;
if (ci->canvas_group->blur_mipmaps) {
- storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
+ texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
}
canvas_group_owner = nullptr;
@@ -1439,13 +1467,14 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (backbuffer_copy) {
//render anything pending, including clearing if no items
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
+
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
@@ -1455,7 +1484,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
@@ -1478,18 +1507,20 @@ RID RendererCanvasRenderRD::light_create() {
}
void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND(!cl);
if (cl->texture == p_texture) {
return;
}
if (cl->texture.is_valid()) {
- storage->texture_remove_from_decal_atlas(cl->texture);
+ texture_storage->texture_remove_from_decal_atlas(cl->texture);
}
cl->texture = p_texture;
if (cl->texture.is_valid()) {
- storage->texture_add_to_decal_atlas(cl->texture);
+ texture_storage->texture_add_to_decal_atlas(cl->texture);
}
}
@@ -1614,7 +1645,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
_update_shadow_atlas();
- Vector2 light_dir = p_light_xform.elements[1].normalized();
+ Vector2 light_dir = p_light_xform.columns[1].normalized();
Vector2 center = p_clip_rect.get_center();
@@ -1682,25 +1713,27 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
RD::get_singleton()->draw_list_end();
Transform2D to_shadow;
- to_shadow.elements[0].x = 1.0 / -(half_size * 2.0);
- to_shadow.elements[2].x = 0.5;
+ to_shadow.columns[0].x = 1.0 / -(half_size * 2.0);
+ to_shadow.columns[2].x = 0.5;
cl->shadow.directional_xform = to_shadow * to_light_xform;
}
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);
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ RID fb = texture_storage->render_target_get_sdf_framebuffer(p_render_target);
+ Rect2i rect = texture_storage->render_target_get_sdf_rect(p_render_target);
Transform2D to_sdf;
- to_sdf.elements[0] *= rect.size.width;
- to_sdf.elements[1] *= rect.size.height;
- to_sdf.elements[2] = rect.position;
+ to_sdf.columns[0] *= rect.size.width;
+ to_sdf.columns[1] *= rect.size.height;
+ to_sdf.columns[2] = rect.position;
Transform2D to_clip;
- to_clip.elements[0] *= 2.0;
- to_clip.elements[1] *= 2.0;
- to_clip.elements[2] = -Vector2(1.0, 1.0);
+ to_clip.columns[0] *= 2.0;
+ to_clip.columns[1] *= 2.0;
+ to_clip.columns[2] = -Vector2(1.0, 1.0);
to_clip = to_clip * to_sdf.affine_inverse();
@@ -1747,7 +1780,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
RD::get_singleton()->draw_list_end();
- storage->render_target_sdf_process(p_render_target); //done rendering, process it
+ texture_storage->render_target_sdf_process(p_render_target); //done rendering, process it
}
RID RendererCanvasRenderRD::occluder_polygon_create() {
@@ -1810,7 +1843,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve
{
uint8_t *vw = geometry.ptrw();
- float *vwptr = (float *)vw;
+ float *vwptr = reinterpret_cast<float *>(vw);
uint8_t *iw = indices.ptrw();
uint16_t *iwptr = (uint16_t *)iw;
@@ -1934,7 +1967,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
-void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
+void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -1972,7 +2005,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
@@ -2116,7 +2149,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -2127,14 +2160,14 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN
}
} else {
if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
+ default_texture_params[p_name] = HashMap<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
-void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
+void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
@@ -2154,13 +2187,13 @@ void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_pa
}
}
-void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -2169,7 +2202,7 @@ void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererSt
}
}
-bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -2177,15 +2210,15 @@ bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_pa
return uniforms[p_param].texture_order >= 0;
}
-bool RendererCanvasRenderRD::ShaderData::is_animated() const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
return false;
}
-bool RendererCanvasRenderRD::ShaderData::casts_shadows() const {
+bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
return false;
}
-Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant RendererCanvasRenderRD::CanvasShaderData::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;
@@ -2194,19 +2227,13 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
return Variant();
}
-RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const {
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<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;
-}
-
-RendererCanvasRenderRD::ShaderData::~ShaderData() {
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
ERR_FAIL_COND(!canvas_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -2214,23 +2241,23 @@ RendererCanvasRenderRD::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
- ShaderData *shader_data = memnew(ShaderData);
+RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
+ CanvasShaderData *shader_data = memnew(CanvasShaderData);
return shader_data;
}
-bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
}
-RendererCanvasRenderRD::MaterialData::~MaterialData() {
+RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
- MaterialData *material_data = memnew(MaterialData);
+RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
+ CanvasMaterialData *material_data = memnew(CanvasMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
@@ -2244,6 +2271,8 @@ void RendererCanvasRenderRD::update() {
}
RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{ //create default samplers
@@ -2256,7 +2285,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
String global_defines;
- uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
+ uint64_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
if (uniform_max_size < 65536) {
//Yes, you guessed right, ARM again
state.max_lights_per_render = 64;
@@ -2358,7 +2387,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.renames["UV"] = "uv";
actions.renames["POINT_SIZE"] = "gl_PointSize";
- actions.renames["WORLD_MATRIX"] = "world_matrix";
+ actions.renames["MODEL_MATRIX"] = "model_matrix";
actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform";
actions.renames["SCREEN_MATRIX"] = "canvas_data.screen_transform";
actions.renames["TIME"] = "canvas_data.time";
@@ -2567,29 +2596,29 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.ids.push_back(storage->get_default_rd_storage_buffer());
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
uniforms.push_back(u);
}
state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
}
- default_canvas_texture = storage->canvas_texture_allocate();
- storage->canvas_texture_initialize(default_canvas_texture);
+ default_canvas_texture = texture_storage->canvas_texture_allocate();
+ texture_storage->canvas_texture_initialize(default_canvas_texture);
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
//create functions for shader and material
- 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);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs);
state.time = 0;
{
- default_canvas_group_shader = storage->shader_allocate();
- storage->shader_initialize(default_canvas_group_shader);
+ default_canvas_group_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_canvas_group_shader);
- storage->shader_set_code(default_canvas_group_shader, R"(
+ material_storage->shader_set_code(default_canvas_group_shader, R"(
// Default CanvasGroup shader.
shader_type canvas_item;
@@ -2604,10 +2633,10 @@ void fragment() {
COLOR *= c;
}
)");
- default_canvas_group_material = storage->material_allocate();
- storage->material_initialize(default_canvas_group_material);
+ default_canvas_group_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_canvas_group_material);
- storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+ material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
static_assert(sizeof(PushConstant) == 128);
@@ -2655,10 +2684,11 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
}
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//canvas state
- storage->free(default_canvas_group_material);
- storage->free(default_canvas_group_shader);
+ material_storage->material_free(default_canvas_group_material);
+ material_storage->shader_free(default_canvas_group_shader);
{
if (state.canvas_state_buffer.is_valid()) {
@@ -2695,6 +2725,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
}
RD::get_singleton()->free(state.shadow_texture);
- storage->free(default_canvas_texture);
+ RendererRD::TextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 84f64b6fda..04881ce7e6 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -41,7 +41,7 @@
#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
enum {
BASE_UNIFORM_SET = 0,
@@ -151,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
ShaderCompiler compiler;
} shader;
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct CanvasShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -161,19 +161,19 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
BLEND_MODE_DISABLED,
};
- bool valid;
+ bool valid = false;
RID version;
PipelineVariants pipeline_variants;
String path;
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String code;
- Map<StringName, Map<int, RID>> default_texture_params;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_sdf = false;
@@ -182,7 +182,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -190,28 +190,28 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- ShaderData();
- virtual ~ShaderData();
+ CanvasShaderData() {}
+ virtual ~CanvasShaderData();
};
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct CanvasMaterialData : public RendererRD::MaterialData {
+ CanvasShaderData *shader_data = nullptr;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~MaterialData();
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~CanvasMaterialData();
};
- 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));
+ RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader));
}
/**************************/
@@ -361,7 +361,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t pad2;
};
- LightUniform *light_uniforms;
+ LightUniform *light_uniforms = nullptr;
RID lights_uniform_buffer;
RID canvas_state_buffer;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 606527ed24..759b8690eb 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -44,9 +44,9 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
}
for (int i = 0; i < p_amount; i++) {
- RID texture = storage->render_target_get_texture(p_render_targets[i].render_target);
+ RID texture = texture_storage->render_target_get_texture(p_render_targets[i].render_target);
ERR_CONTINUE(texture.is_null());
- RID rd_texture = storage->texture_get_rd_texture(texture);
+ RID rd_texture = texture_storage->texture_get_rd_texture(texture);
ERR_CONTINUE(rd_texture.is_null());
// TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in.
@@ -56,8 +56,8 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.ids.push_back(blit.sampler);
- u.ids.push_back(rd_texture);
+ u.append_id(blit.sampler);
+ u.append_id(rd_texture);
uniforms.push_back(u);
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0);
@@ -155,6 +155,11 @@ void RendererCompositorRD::finalize() {
memdelete(scene);
memdelete(canvas);
memdelete(storage);
+ memdelete(particles_storage);
+ memdelete(light_storage);
+ memdelete(mesh_storage);
+ memdelete(material_storage);
+ memdelete(texture_storage);
//only need to erase these, the rest are erased by cascade
blit.shader.version_free(blit.shader_version);
@@ -165,9 +170,9 @@ void RendererCompositorRD::finalize() {
void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
RD::get_singleton()->prepare_screen_for_drawing();
- RID texture = storage->texture_allocate();
- storage->texture_2d_initialize(texture, p_image);
- RID rd_texture = storage->texture_get_rd_texture(texture);
+ RID texture = texture_storage->texture_allocate();
+ texture_storage->texture_2d_initialize(texture, p_image);
+ RID rd_texture = texture_storage->texture_get_rd_texture(texture);
RID uset;
{
@@ -175,8 +180,8 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.ids.push_back(blit.sampler);
- u.ids.push_back(rd_texture);
+ u.append_id(blit.sampler);
+ u.append_id(rd_texture);
uniforms.push_back(u);
uset = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0);
}
@@ -235,19 +240,21 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RD::get_singleton()->swap_buffers();
- storage->free(texture);
+ texture_storage->texture_free(texture);
}
RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
+ uniform_set_cache = memnew(UniformSetCacheRD);
+
{
String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
if (shader_cache_dir.is_empty()) {
shader_cache_dir = "user://";
}
- DirAccessRef da = DirAccess::open(shader_cache_dir);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::open(shader_cache_dir);
+ if (da.is_null()) {
ERR_PRINT("Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir);
} else {
Error err = da->change_dir("shader_cache");
@@ -279,13 +286,17 @@ RendererCompositorRD::RendererCompositorRD() {
}
singleton = this;
- time = 0;
+ texture_storage = memnew(RendererRD::TextureStorage);
+ material_storage = memnew(RendererRD::MaterialStorage);
+ mesh_storage = memnew(RendererRD::MeshStorage);
+ light_storage = memnew(RendererRD::LightStorage);
+ particles_storage = memnew(RendererRD::ParticlesStorage);
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
- uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
+ uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
if (back_end || textures_per_stage < 48) {
scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
@@ -301,5 +312,6 @@ RendererCompositorRD::RendererCompositorRD() {
}
RendererCompositorRD::~RendererCompositorRD() {
+ memdelete(uniform_set_cache);
ShaderRD::set_shader_cache_dir(String());
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 9a992d5819..aefc189f68 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -39,12 +39,24 @@
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
class RendererCompositorRD : public RendererCompositor {
protected:
- RendererCanvasRenderRD *canvas;
- RendererStorageRD *storage;
- RendererSceneRenderRD *scene;
+ UniformSetCacheRD *uniform_set_cache = nullptr;
+ RendererCanvasRenderRD *canvas = nullptr;
+ RendererRD::LightStorage *light_storage = nullptr;
+ RendererRD::MaterialStorage *material_storage = nullptr;
+ RendererRD::MeshStorage *mesh_storage = nullptr;
+ RendererRD::ParticlesStorage *particles_storage = nullptr;
+ RendererRD::TextureStorage *texture_storage = nullptr;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneRenderRD *scene = nullptr;
enum BlitMode {
BLIT_MODE_NORMAL,
@@ -78,14 +90,19 @@ protected:
RID sampler;
} blit;
- Map<RID, RID> render_target_descriptors;
+ HashMap<RID, RID> render_target_descriptors;
- double time;
- double delta;
+ double time = 0.0;
+ double delta = 0.0;
static uint64_t frame;
public:
+ RendererLightStorage *get_light_storage() { return light_storage; };
+ RendererMaterialStorage *get_material_storage() { return material_storage; };
+ RendererMeshStorage *get_mesh_storage() { return mesh_storage; };
+ RendererParticlesStorage *get_particles_storage() { return particles_storage; };
+ RendererTextureStorage *get_texture_storage() { return texture_storage; };
RendererStorage *get_storage() { return storage; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
@@ -114,6 +131,7 @@ public:
static void make_current() {
_create_func = _create_current;
+ low_end = false;
}
static RendererCompositorRD *singleton;
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index 1a84bafbd0..7aede6bb48 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -32,6 +32,8 @@
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
@@ -40,6 +42,9 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF
// SDFGI
void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
storage = p_gi->storage;
gi = p_gi;
num_cascades = p_env->sdfgi_cascades;
@@ -221,14 +226,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1
+ u.append_id(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.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_albedo);
+ u.append_id(render_albedo);
uniforms.push_back(u);
}
{
@@ -236,7 +241,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 3;
for (int j = 0; j < 8; j++) {
- u.ids.push_back(render_occlusion[j]);
+ u.append_id(render_occlusion[j]);
}
uniforms.push_back(u);
}
@@ -244,21 +249,21 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 4;
- u.ids.push_back(render_emission);
+ u.append_id(render_emission);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 5;
- u.ids.push_back(render_emission_aniso);
+ u.append_id(render_emission_aniso);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 6;
- u.ids.push_back(render_geom_facing);
+ u.append_id(render_geom_facing);
uniforms.push_back(u);
}
@@ -266,28 +271,28 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 7;
- u.ids.push_back(cascade.sdf_tex);
+ u.append_id(cascade.sdf_tex);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 8;
- u.ids.push_back(occlusion_data);
+ u.append_id(occlusion_data);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 10;
- u.ids.push_back(cascade.solid_cell_dispatch_buffer);
+ u.append_id(cascade.solid_cell_dispatch_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 11;
- u.ids.push_back(cascade.solid_cell_buffer);
+ u.append_id(cascade.solid_cell_buffer);
uniforms.push_back(u);
}
@@ -300,42 +305,42 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_albedo);
+ u.append_id(render_albedo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_geom_facing);
+ u.append_id(render_geom_facing);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 3;
- u.ids.push_back(render_emission);
+ u.append_id(render_emission);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 4;
- u.ids.push_back(render_emission_aniso);
+ u.append_id(render_emission_aniso);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 5;
- u.ids.push_back(cascade.solid_cell_dispatch_buffer);
+ u.append_id(cascade.solid_cell_dispatch_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 6;
- u.ids.push_back(cascade.solid_cell_buffer);
+ u.append_id(cascade.solid_cell_buffer);
uniforms.push_back(u);
}
@@ -348,7 +353,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
for (int j = 0; j < 8; j++) {
- u.ids.push_back(render_occlusion[j]);
+ u.append_id(render_occlusion[j]);
}
uniforms.push_back(u);
}
@@ -356,7 +361,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(occlusion_data);
+ u.append_id(occlusion_data);
uniforms.push_back(u);
}
@@ -375,9 +380,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (j < cascades.size()) {
- u.ids.push_back(cascades[j].sdf_tex);
+ u.append_id(cascades[j].sdf_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -386,70 +391,70 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.binding = 2;
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));
+ u.append_id(material_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.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(cascade.solid_cell_dispatch_buffer);
+ u.append_id(cascade.solid_cell_dispatch_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(cascade.solid_cell_buffer);
+ u.append_id(cascade.solid_cell_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(cascade.light_data);
+ u.append_id(cascade.light_data);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(cascade.light_aniso_0_tex);
+ u.append_id(cascade.light_aniso_0_tex);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(cascade.light_aniso_1_tex);
+ u.append_id(cascade.light_aniso_1_tex);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(cascades_ubo);
+ u.append_id(cascades_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(cascade.lights_buffer);
+ u.append_id(cascade.lights_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(lightprobe_texture);
+ u.append_id(lightprobe_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(occlusion_texture);
+ u.append_id(occlusion_texture);
uniforms.push_back(u);
}
@@ -463,14 +468,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_albedo);
+ u.append_id(render_albedo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_sdf[0]);
+ u.append_id(render_sdf[0]);
uniforms.push_back(u);
}
@@ -483,14 +488,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_albedo);
+ u.append_id(render_albedo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_sdf_half[0]);
+ u.append_id(render_sdf_half[0]);
uniforms.push_back(u);
}
@@ -504,19 +509,22 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_sdf[0]);
+ u.append_id(render_sdf[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_sdf[1]);
+ u.append_id(render_sdf[1]);
uniforms.push_back(u);
}
jump_flood_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
- SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]);
+ RID aux0 = uniforms.write[0].get_id(0);
+ RID aux1 = uniforms.write[1].get_id(0);
+ uniforms.write[0].set_id(0, aux1);
+ uniforms.write[1].set_id(0, aux0);
jump_flood_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
}
//jump flood half uniform set
@@ -526,19 +534,22 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_sdf_half[0]);
+ u.append_id(render_sdf_half[0]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_sdf_half[1]);
+ u.append_id(render_sdf_half[1]);
uniforms.push_back(u);
}
jump_flood_half_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
- SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]);
+ RID aux0 = uniforms.write[0].get_id(0);
+ RID aux1 = uniforms.write[1].get_id(0);
+ uniforms.write[0].set_id(0, aux1);
+ uniforms.write[1].set_id(0, aux0);
jump_flood_half_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.preprocess.version_get_shader(gi->sdfgi_shader.preprocess_shader, SDFGIShader::PRE_PROCESS_JUMP_FLOOD), 0);
}
@@ -549,21 +560,21 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_albedo);
+ u.append_id(render_albedo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size
+ u.append_id(render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 3;
- u.ids.push_back(render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass
+ u.append_id(render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass
uniforms.push_back(u);
}
@@ -578,7 +589,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(render_albedo);
+ u.append_id(render_albedo);
uniforms.push_back(u);
}
{
@@ -586,7 +597,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
for (int i = 0; i < 8; i++) {
- u.ids.push_back(render_occlusion[i]);
+ u.append_id(render_occlusion[i]);
}
uniforms.push_back(u);
}
@@ -594,7 +605,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 3;
- u.ids.push_back(render_geom_facing);
+ u.append_id(render_geom_facing);
uniforms.push_back(u);
}
@@ -612,9 +623,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (j < cascades.size()) {
- u.ids.push_back(cascades[j].sdf_tex);
+ u.append_id(cascades[j].sdf_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -625,9 +636,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (j < cascades.size()) {
- u.ids.push_back(cascades[j].light_tex);
+ u.append_id(cascades[j].light_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -638,9 +649,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (j < cascades.size()) {
- u.ids.push_back(cascades[j].light_aniso_0_tex);
+ u.append_id(cascades[j].light_aniso_0_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -651,9 +662,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (j < cascades.size()) {
- u.ids.push_back(cascades[j].light_aniso_1_tex);
+ u.append_id(cascades[j].light_aniso_1_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -662,7 +673,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -670,14 +681,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 7;
- u.ids.push_back(cascades_ubo);
+ u.append_id(cascades_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 8;
- u.ids.push_back(lightprobe_data);
+ u.append_id(lightprobe_data);
uniforms.push_back(u);
}
@@ -685,14 +696,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.ids.push_back(cascades[i].lightprobe_history_tex);
+ u.append_id(cascades[i].lightprobe_history_tex);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
- u.ids.push_back(cascades[i].lightprobe_average_tex);
+ u.append_id(cascades[i].lightprobe_average_tex);
uniforms.push_back(u);
}
@@ -700,14 +711,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 11;
- u.ids.push_back(lightprobe_history_scroll);
+ u.append_id(lightprobe_history_scroll);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 12;
- u.ids.push_back(lightprobe_average_scroll);
+ u.append_id(lightprobe_average_scroll);
uniforms.push_back(u);
}
{
@@ -723,14 +734,14 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
} else {
parent_average = cascades[i - 1].lightprobe_average_tex; //to use something, but it won't be used
}
- u.ids.push_back(parent_average);
+ u.append_id(parent_average);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 14;
- u.ids.push_back(ambient_texture);
+ u.append_id(ambient_texture);
uniforms.push_back(u);
}
@@ -868,7 +879,7 @@ void RendererSceneGIRD::SDFGI::update_light() {
push_constant.process_offset = 0;
push_constant.process_increment = 1;
} else {
- static uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = {
+ static const uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = {
1, 2, 4, 8, 16
};
@@ -914,7 +925,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = storage->get_default_clear_color().to_linear();
+ Color c = storage->get_default_clear_color().srgb_to_linear();
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
@@ -934,7 +945,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
- u.ids.push_back(p_sky->radiance);
+ u.append_id(p_sky->radiance);
uniforms.push_back(u);
}
@@ -942,7 +953,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
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));
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -1002,7 +1013,7 @@ void RendererSceneGIRD::SDFGI::store_probes() {
push_constant.y_mult = y_mult;
// Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces
- RENDER_TIMESTAMP("Average Probes");
+ RENDER_TIMESTAMP("Average SDFGI Probes");
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE]);
@@ -1102,6 +1113,10 @@ void RendererSceneGIRD::SDFGI::update_cascades() {
}
void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+
if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
Vector<RD::Uniform> uniforms;
{
@@ -1110,9 +1125,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
if (i < cascades.size()) {
- u.ids.push_back(cascades[i].sdf_tex);
+ u.append_id(cascades[i].sdf_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1123,9 +1138,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
if (i < cascades.size()) {
- u.ids.push_back(cascades[i].light_tex);
+ u.append_id(cascades[i].light_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1136,9 +1151,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
if (i < cascades.size()) {
- u.ids.push_back(cascades[i].light_aniso_0_tex);
+ u.append_id(cascades[i].light_aniso_0_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1149,9 +1164,9 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
if (i < cascades.size()) {
- u.ids.push_back(cascades[i].light_aniso_1_tex);
+ u.append_id(cascades[i].light_aniso_1_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1160,35 +1175,35 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(occlusion_texture);
+ u.append_id(occlusion_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
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));
+ u.append_id(material_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.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(cascades_ubo);
+ u.append_id(cascades_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.ids.push_back(p_texture);
+ u.append_id(p_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(lightprobe_texture);
+ u.append_id(lightprobe_texture);
uniforms.push_back(u);
}
debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0);
@@ -1214,17 +1229,17 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
push_constant.cam_extent[1] = vp_half.y;
push_constant.cam_extent[2] = -p_projection.get_z_near();
- push_constant.cam_transform[0] = p_transform.basis.elements[0][0];
- push_constant.cam_transform[1] = p_transform.basis.elements[1][0];
- push_constant.cam_transform[2] = p_transform.basis.elements[2][0];
+ push_constant.cam_transform[0] = p_transform.basis.rows[0][0];
+ push_constant.cam_transform[1] = p_transform.basis.rows[1][0];
+ push_constant.cam_transform[2] = p_transform.basis.rows[2][0];
push_constant.cam_transform[3] = 0;
- push_constant.cam_transform[4] = p_transform.basis.elements[0][1];
- push_constant.cam_transform[5] = p_transform.basis.elements[1][1];
- push_constant.cam_transform[6] = p_transform.basis.elements[2][1];
+ push_constant.cam_transform[4] = p_transform.basis.rows[0][1];
+ push_constant.cam_transform[5] = p_transform.basis.rows[1][1];
+ push_constant.cam_transform[6] = p_transform.basis.rows[2][1];
push_constant.cam_transform[7] = 0;
- push_constant.cam_transform[8] = p_transform.basis.elements[0][2];
- push_constant.cam_transform[9] = p_transform.basis.elements[1][2];
- push_constant.cam_transform[10] = p_transform.basis.elements[2][2];
+ push_constant.cam_transform[8] = p_transform.basis.rows[0][2];
+ push_constant.cam_transform[9] = p_transform.basis.rows[1][2];
+ push_constant.cam_transform[10] = p_transform.basis.rows[2][2];
push_constant.cam_transform[11] = 0;
push_constant.cam_transform[12] = p_transform.origin.x;
push_constant.cam_transform[13] = p_transform.origin.y;
@@ -1236,11 +1251,13 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1);
RD::get_singleton()->compute_list_end();
- Size2 rtsize = storage->render_target_get_size(p_render_target);
- storage->get_effects()->copy_to_fb_rect(p_texture, storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
+ Size2 rtsize = texture_storage->render_target_get_size(p_render_target);
+ copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
}
void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
SDFGIShader::DebugProbesPushConstant push_constant;
for (int i = 0; i < 4; i++) {
@@ -1273,28 +1290,28 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
RD::Uniform u;
u.binding = 1;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(cascades_ubo);
+ u.append_id(cascades_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(lightprobe_texture);
+ u.append_id(lightprobe_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 3;
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));
+ u.append_id(material_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.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(occlusion_texture);
+ u.append_id(occlusion_texture);
uniforms.push_back(u);
}
@@ -1449,24 +1466,24 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
ERR_CONTINUE(!li);
- if (storage->light_directional_is_sky_only(li->light)) {
+ if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
continue;
}
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
dir.y *= y_mult;
dir.normalize();
lights[idx].direction[0] = dir.x;
lights[idx].direction[1] = dir.y;
lights[idx].direction[2] = dir.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
+ Color color = RSG::light_storage->light_get_color(li->light);
+ color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].type = RS::LIGHT_DIRECTIONAL;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
+ lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
idx++;
}
@@ -1483,7 +1500,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
ERR_CONTINUE(!li);
- uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
if (i > max_sdfgi_cascade) {
continue;
}
@@ -1492,7 +1509,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
continue;
}
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
//faster to not do this here
//dir.y *= y_mult;
//dir.normalize();
@@ -1504,18 +1521,18 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
lights[idx].position[0] = pos.x;
lights[idx].position[1] = pos.y;
lights[idx].position[2] = pos.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
+ Color color = RSG::light_storage->light_get_color(li->light);
+ color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].type = storage->light_get_type(li->light);
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
- lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lights[idx].type = RSG::light_storage->light_get_type(li->light);
+ lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+ lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -1555,14 +1572,14 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
if (cascade_next != cascade) {
RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade");
- RENDER_TIMESTAMP(">SDFGI Update SDF");
+ RENDER_TIMESTAMP("> SDFGI Update SDF");
//done rendering! must update SDF
//clear dispatch indirect data
SDFGIShader::PreprocessPushConstant push_constant;
memset(&push_constant, 0, sizeof(SDFGIShader::PreprocessPushConstant));
- RENDER_TIMESTAMP("Scroll SDF");
+ RENDER_TIMESTAMP("SDFGI Scroll SDF");
//scroll
if (cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) {
@@ -1701,7 +1718,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
push_constant.half_size = true;
{
- RENDER_TIMESTAMP("SDFGI Jump Flood (Half Size)");
+ RENDER_TIMESTAMP("SDFGI Jump Flood (Half-Size)");
uint32_t s = cascade_half_size;
@@ -1723,7 +1740,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
}
}
- RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half Size)");
+ RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half-Size)");
//continue with optimized jump flood for smaller reads
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
@@ -1759,7 +1776,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
} else {
//full size jumpflood
- RENDER_TIMESTAMP("SDFGI Jump Flood");
+ RENDER_TIMESTAMP("SDFGI Jump Flood (Full-Size)");
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_initialize_uniform_set, 0);
@@ -1790,7 +1807,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
}
}
- RENDER_TIMESTAMP("SDFGI Jump Flood Optimized");
+ RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Full-Size)");
//continue with optimized jump flood for smaller reads
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
@@ -1882,7 +1899,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
//finalize render and update sdf
#endif
- RENDER_TIMESTAMP("<SDFGI Update SDF");
+ RENDER_TIMESTAMP("< SDFGI Update SDF");
RD::get_singleton()->draw_command_end_label();
}
}
@@ -1891,7 +1908,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
- RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lighs");
+ RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights");
update_cascades();
@@ -1919,7 +1936,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]);
ERR_CONTINUE(!li);
- uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
if (p_cascade_indices[i] > max_sdfgi_cascade) {
continue;
}
@@ -1928,9 +1945,9 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
continue;
}
- lights[idx].type = storage->light_get_type(li->light);
+ lights[idx].type = RSG::light_storage->light_get_type(li->light);
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
dir.y *= y_mult; //only makes sense for directional
dir.normalize();
@@ -1943,17 +1960,17 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
lights[idx].position[0] = pos.x;
lights[idx].position[1] = pos.y;
lights[idx].position[2] = pos.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
+ Color color = RSG::light_storage->light_get_color(li->light);
+ color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
- lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+ lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -2010,6 +2027,8 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
// VoxelGIInstance
void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
uint32_t data_version = storage->voxel_gi_get_data_version(probe);
// (RE)CREATE IF NEEDED
@@ -2073,14 +2092,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(storage->voxel_gi_get_octree_buffer(probe));
+ u.append_id(storage->voxel_gi_get_octree_buffer(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(storage->voxel_gi_get_data_buffer(probe));
+ u.append_id(storage->voxel_gi_get_data_buffer(probe));
uniforms.push_back(u);
}
@@ -2088,21 +2107,21 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 4;
- u.ids.push_back(write_buffer);
+ u.append_id(write_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe));
+ u.append_id(storage->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -2113,7 +2132,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
- u.ids.push_back(gi->voxel_gi_lights_uniform);
+ u.append_id(gi->voxel_gi_lights_uniform);
copy_uniforms.push_back(u);
}
@@ -2125,7 +2144,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
- u.ids.push_back(texture);
+ u.append_id(texture);
copy_uniforms.push_back(u);
}
mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, gi->voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0);
@@ -2138,7 +2157,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 5;
- u.ids.push_back(mipmap.texture);
+ u.append_id(mipmap.texture);
uniforms.push_back(u);
}
@@ -2213,7 +2232,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
- u.ids.push_back(gi->voxel_gi_lights_uniform);
+ u.append_id(gi->voxel_gi_lights_uniform);
uniforms.push_back(u);
}
@@ -2221,56 +2240,56 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 5;
- u.ids.push_back(dmap.albedo);
+ u.append_id(dmap.albedo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 6;
- u.ids.push_back(dmap.normal);
+ u.append_id(dmap.normal);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 7;
- u.ids.push_back(dmap.orm);
+ u.append_id(dmap.orm);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 8;
- u.ids.push_back(dmap.fb_depth);
+ u.append_id(dmap.fb_depth);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe));
+ u.append_id(storage->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
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));
+ u.append_id(material_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.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 11;
- u.ids.push_back(dmap.texture);
+ u.append_id(dmap.texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 12;
- u.ids.push_back(dmap.depth);
+ u.append_id(dmap.depth);
uniforms.push_back(u);
}
@@ -2286,14 +2305,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 5;
- u.ids.push_back(dynamic_maps[dynamic_maps.size() - 1].texture);
+ u.append_id(dynamic_maps[dynamic_maps.size() - 1].texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 6;
- u.ids.push_back(dynamic_maps[dynamic_maps.size() - 1].depth);
+ u.append_id(dynamic_maps[dynamic_maps.size() - 1].depth);
uniforms.push_back(u);
}
@@ -2302,14 +2321,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 7;
- u.ids.push_back(dmap.texture);
+ u.append_id(dmap.texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 8;
- u.ids.push_back(dmap.depth);
+ u.append_id(dmap.depth);
uniforms.push_back(u);
}
}
@@ -2318,14 +2337,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.ids.push_back(storage->voxel_gi_get_sdf_texture(probe));
+ u.append_id(storage->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -2334,7 +2353,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 11;
- u.ids.push_back(mipmaps[dmap.mipmap].texture);
+ u.append_id(mipmaps[dmap.mipmap].texture);
uniforms.push_back(u);
}
}
@@ -2378,27 +2397,27 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RID light_instance = p_light_instances[i];
RID light = p_scene_render->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)) {
+ l.type = RSG::light_storage->light_get_type(light);
+ if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
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();
- Color color = storage->light_get_color(light).to_linear();
+ l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
+ l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
+ Color color = RSG::light_storage->light_get_color(light).srgb_to_linear();
l.color[0] = color.r;
l.color[1] = color.g;
l.color[2] = color.b;
- l.cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- l.inv_spot_attenuation = 1.0f / storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
Vector3 pos = to_probe_xform.xform(xform.origin);
- Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
+ Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_column(2)).normalized();
l.position[0] = pos.x;
l.position[1] = pos.y;
@@ -2408,7 +2427,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
l.direction[1] = dir.y;
l.direction[2] = dir.z;
- l.has_shadow = storage->light_has_shadow(light);
+ l.has_shadow = RSG::light_storage->light_has_shadow(light);
}
RD::get_singleton()->buffer_update(gi->voxel_gi_lights_uniform, 0, sizeof(VoxelGILight) * light_count, gi->voxel_gi_lights);
@@ -2447,7 +2466,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
passes = 1; //only re-blitting is necessary
}
int wg_size = 64;
- int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
+ int64_t wg_limit_x = (int64_t)RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
for (int pass = 0; pass < passes; pass++) {
if (p_update_light_instances) {
@@ -2470,9 +2489,9 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
push_constant.cell_offset = mipmaps[i].cell_offset;
push_constant.cell_count = mipmaps[i].cell_count;
- int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
+ int64_t wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
while (wg_todo) {
- int wg_count = MIN(wg_todo, wg_limit_x);
+ int64_t wg_count = MIN(wg_todo, wg_limit_x);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
wg_todo -= wg_count;
@@ -2491,9 +2510,9 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
push_constant.cell_offset = mipmaps[i].cell_offset;
push_constant.cell_count = mipmaps[i].cell_count;
- int wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
+ int64_t wg_todo = (mipmaps[i].cell_count - 1) / wg_size + 1;
while (wg_todo) {
- int wg_count = MIN(wg_todo, wg_limit_x);
+ int64_t wg_count = MIN(wg_todo, wg_limit_x);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1);
wg_todo -= wg_count;
@@ -2575,17 +2594,17 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
Transform3D xform;
xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir);
- Vector3 x_dir = xform.basis.get_axis(0).abs();
+ Vector3 x_dir = xform.basis.get_column(0).abs();
int x_axis = int(Vector3(0, 1, 2).dot(x_dir));
- Vector3 y_dir = xform.basis.get_axis(1).abs();
+ Vector3 y_dir = xform.basis.get_column(1).abs();
int y_axis = int(Vector3(0, 1, 2).dot(y_dir));
- Vector3 z_dir = -xform.basis.get_axis(2);
+ Vector3 z_dir = -xform.basis.get_column(2);
int z_axis = int(Vector3(0, 1, 2).dot(z_dir.abs()));
Rect2i rect(aabb.position[x_axis], aabb.position[y_axis], aabb.size[x_axis], aabb.size[y_axis]);
- bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(0)) < 0);
- bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(1)) < 0);
- bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(2)) > 0);
+ bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(0)) < 0);
+ bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0);
+ bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0);
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]);
@@ -2713,6 +2732,8 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
}
void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
if (mipmaps.size() == 0) {
return;
}
@@ -2747,21 +2768,21 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(storage->voxel_gi_get_data_buffer(probe));
+ u.append_id(storage->voxel_gi_get_data_buffer(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- u.ids.push_back(texture);
+ u.append_id(texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -2801,6 +2822,9 @@ RendererSceneGIRD::~RendererSceneGIRD() {
}
void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
storage = p_storage;
/* GI */
@@ -2918,14 +2942,14 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
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));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -3017,6 +3041,8 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme
}
void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
r_voxel_gi_instances_used = 0;
// feels a little dirty to use our container this way but....
@@ -3045,17 +3071,17 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
- gipd.xform[0] = to_cell.basis.elements[0][0];
- gipd.xform[1] = to_cell.basis.elements[1][0];
- gipd.xform[2] = to_cell.basis.elements[2][0];
+ gipd.xform[0] = to_cell.basis.rows[0][0];
+ gipd.xform[1] = to_cell.basis.rows[1][0];
+ gipd.xform[2] = to_cell.basis.rows[2][0];
gipd.xform[3] = 0;
- gipd.xform[4] = to_cell.basis.elements[0][1];
- gipd.xform[5] = to_cell.basis.elements[1][1];
- gipd.xform[6] = to_cell.basis.elements[2][1];
+ gipd.xform[4] = to_cell.basis.rows[0][1];
+ gipd.xform[5] = to_cell.basis.rows[1][1];
+ gipd.xform[6] = to_cell.basis.rows[2][1];
gipd.xform[7] = 0;
- gipd.xform[8] = to_cell.basis.elements[0][2];
- gipd.xform[9] = to_cell.basis.elements[1][2];
- gipd.xform[10] = to_cell.basis.elements[2][2];
+ gipd.xform[8] = to_cell.basis.rows[0][2];
+ gipd.xform[9] = to_cell.basis.rows[1][2];
+ gipd.xform[10] = to_cell.basis.rows[2][2];
gipd.xform[11] = 0;
gipd.xform[12] = to_cell.origin.x;
gipd.xform[13] = to_cell.origin.y;
@@ -3079,7 +3105,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
}
if (texture == RID()) {
- texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
}
if (texture != rb->gi.voxel_gi_textures[i]) {
@@ -3115,6 +3141,9 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
}
void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->draw_command_begin_label("GI Render");
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
@@ -3178,9 +3207,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
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);
+ u.append_id(rb->sdfgi->cascades[j].sdf_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3191,9 +3220,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
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);
+ u.append_id(rb->sdfgi->cascades[j].light_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3204,9 +3233,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
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);
+ u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3217,9 +3246,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
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);
+ u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3229,9 +3258,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
if (rb->sdfgi) {
- u.ids.push_back(rb->sdfgi->occlusion_texture);
+ u.append_id(rb->sdfgi->occlusion_texture);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
}
uniforms.push_back(u);
}
@@ -3239,14 +3268,14 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
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));
+ u.append_id(material_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.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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -3254,7 +3283,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.ids.push_back(rb->ambient_buffer);
+ u.append_id(rb->ambient_buffer);
uniforms.push_back(u);
}
@@ -3262,7 +3291,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
- u.ids.push_back(rb->reflection_buffer);
+ u.append_id(rb->reflection_buffer);
uniforms.push_back(u);
}
@@ -3271,9 +3300,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 11;
if (rb->sdfgi) {
- u.ids.push_back(rb->sdfgi->lightprobe_texture);
+ u.append_id(rb->sdfgi->lightprobe_texture);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
}
uniforms.push_back(u);
}
@@ -3281,36 +3310,36 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 12;
- u.ids.push_back(rb->depth_texture);
+ u.append_id(rb->depth_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 13;
- u.ids.push_back(p_normal_roughness_buffer);
+ u.append_id(p_normal_roughness_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 14;
- RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- u.ids.push_back(buffer);
+ RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 15;
- u.ids.push_back(sdfgi_ubo);
+ u.append_id(sdfgi_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 16;
- u.ids.push_back(rb->gi.voxel_gi_buffer);
+ u.append_id(rb->gi.voxel_gi_buffer);
uniforms.push_back(u);
}
{
@@ -3318,7 +3347,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 17;
for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
- u.ids.push_back(rb->gi.voxel_gi_textures[i]);
+ u.append_id(rb->gi.voxel_gi_textures[i]);
}
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 25f0dca3b7..122644498b 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -54,7 +54,7 @@ class RendererSceneRenderRD;
class RendererSceneGIRD {
private:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
/* VOXEL_GI INSTANCE */
@@ -250,8 +250,6 @@ private:
float cos_spot_angle;
float inv_spot_attenuation;
float radius;
-
- float shadow_color[4];
};
struct DirectLightPushConstant {
@@ -332,8 +330,8 @@ public:
struct VoxelGIInstance {
// access to our containers
- RendererStorageRD *storage;
- RendererSceneGIRD *gi;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneGIRD *gi = nullptr;
RID probe;
RID texture;
@@ -456,8 +454,8 @@ public:
};
// access to our containers
- RendererStorageRD *storage;
- RendererSceneGIRD *gi;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneGIRD *gi = nullptr;
// used for rendering (voxelization)
RID render_albedo;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index db8f5461cf..ef959bc3c6 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -33,6 +33,8 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
void get_vogel_disk(float *r_kernel, int p_sample_count) {
@@ -514,7 +516,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
ambient_color_sky_mix = env->ambient_sky_contribution;
const float ambient_energy = env->ambient_light_energy;
ambient_color = env->ambient_light;
- ambient_color = ambient_color.to_linear();
+ ambient_color = ambient_color.srgb_to_linear();
ambient_color.r *= ambient_energy;
ambient_color.g *= ambient_energy;
ambient_color.b *= ambient_energy;
@@ -533,7 +535,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
} else {
const float bg_energy = env->bg_energy;
Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color);
- panorama_color = panorama_color.to_linear();
+ panorama_color = panorama_color.srgb_to_linear();
panorama_color.r *= bg_energy;
panorama_color.g *= bg_energy;
panorama_color.b *= bg_energy;
@@ -687,7 +689,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instanc
return true;
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
return true;
}
@@ -711,12 +713,12 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
RD::get_singleton()->draw_command_begin_label("Reflection probe render");
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
// Invalidate reflection atlas, need to regenerate
RD::get_singleton()->free(atlas->reflection);
atlas->reflection = RID();
@@ -733,7 +735,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
if (atlas->reflection.is_null()) {
int mipmaps = MIN(sky.roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
- mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
+ mipmaps = RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
{
//reflection atlas was unused, create:
RD::TextureFormat tf;
@@ -757,7 +759,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
atlas->reflections.resize(atlas->count);
for (int i = 0; i < atlas->count; i++) {
- atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
+ atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
for (int j = 0; j < 6; j++) {
atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
}
@@ -825,7 +827,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
return false;
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
// Using real time reflections, all roughness is done in one step
atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false);
rpi->rendering = false;
@@ -1343,7 +1345,7 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance);
ERR_FAIL_COND_V(!light_instance, 0);
- switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
+ switch (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light)) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
@@ -1405,7 +1407,7 @@ RID RendererSceneRenderRD::light_instance_create(RID p_light) {
light_instance->self = li;
light_instance->light = p_light;
- light_instance->light_type = storage->light_get_type(p_light);
+ light_instance->light_type = RSG::light_storage->light_get_type(p_light);
if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
light_instance->forward_id = _allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT);
}
@@ -1554,8 +1556,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH);
- // TODO make sure texture_create_shared_from_slice works for multiview
-
RD::TextureFormat tf;
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->internal_width;
@@ -1581,55 +1581,63 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.mipmaps--;
rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- int base_width = rb->internal_width;
- int base_height = rb->internal_height;
+ for (uint32_t l = 0; l < rb->view_count; l++) {
+ RenderBuffers::Blur::Layer ll[2];
+ int base_width = rb->internal_width;
+ int base_height = rb->internal_height;
- for (uint32_t i = 0; i < mipmaps_required; i++) {
- RenderBuffers::Blur::Mipmap mm;
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i);
+ for (uint32_t i = 0; i < mipmaps_required; i++) {
+ RenderBuffers::Blur::Mipmap mm;
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, l, i);
- mm.width = base_width;
- mm.height = base_height;
+ mm.width = base_width;
+ mm.height = base_height;
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(mm.texture);
-
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
- }
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
- if (!_render_buffers_can_be_storage()) {
- // and half texture, this is an intermediate result so just allocate a texture, is this good enough?
- tf.width = MAX(1, base_width >> 1);
- tf.height = base_height;
- tf.mipmaps = 1; // 1 or 0?
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ }
- mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (!_render_buffers_can_be_storage()) {
+ // and half texture, this is an intermediate result so just allocate a texture, is this good enough?
+ tf.width = MAX(1, base_width >> 1);
+ tf.height = base_height;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.mipmaps = 1;
+
+ mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> half_fb;
+ half_fb.push_back(mm.half_texture);
+ mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
+ }
- Vector<RID> half_fb;
- half_fb.push_back(mm.half_texture);
- mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
- }
+ ll[0].mipmaps.push_back(mm);
- rb->blur[0].mipmaps.push_back(mm);
+ if (i > 0) {
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, l, i - 1);
- if (i > 0) {
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(mm.texture);
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ // We can re-use the half texture here as it is an intermediate result
+ }
- // We can re-use the half texture here as it is an intermediate result
+ ll[1].mipmaps.push_back(mm);
}
- rb->blur[1].mipmaps.push_back(mm);
+ base_width = MAX(1, base_width >> 1);
+ base_height = MAX(1, base_height >> 1);
}
- base_width = MAX(1, base_width >> 1);
- base_height = MAX(1, base_height >> 1);
+ rb->blur[0].layers.push_back(ll[0]);
+ rb->blur[1].layers.push_back(ll[1]);
}
if (!_render_buffers_can_be_storage()) {
@@ -1638,21 +1646,19 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
tf.width = rb->internal_width;
tf.height = rb->internal_height;
- tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
- tf.array_layers = rb->view_count;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1; // Our DOF effect handles one eye per turn
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
tf.mipmaps = 1;
for (uint32_t i = 0; i < 4; i++) {
// associated blur texture
RID texture;
- if (i == 0) {
- texture = rb->texture;
- } else if (i == 1) {
- texture = rb->blur[0].mipmaps[0].texture;
+ if (i == 1) {
+ texture = rb->blur[0].layers[0].mipmaps[0].texture;
} else if (i == 2) {
- texture = rb->blur[1].mipmaps[0].texture;
+ texture = rb->blur[1].layers[0].mipmaps[0].texture;
} else if (i == 3) {
- texture = rb->blur[0].mipmaps[1].texture;
+ texture = rb->blur[0].layers[0].mipmaps[1].texture;
}
// create weight texture
@@ -1660,23 +1666,18 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
// create frame buffer
Vector<RID> fb;
- fb.push_back(texture);
+ if (i != 0) {
+ fb.push_back(texture);
+ }
fb.push_back(rb->weight_buffers[i].weight);
rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
if (i == 1) {
// next 2 are half size
- tf.width = MAX(1, tf.width >> 1);
- tf.height = MAX(1, tf.height >> 1);
+ tf.width = MAX(1u, tf.width >> 1);
+ tf.height = MAX(1u, tf.height >> 1);
}
}
-
- {
- // and finally an FB for just our base weights
- Vector<RID> fb;
- fb.push_back(rb->weight_buffers[0].weight);
- rb->base_weight_fb = RD::get_singleton()->framebuffer_create(fb);
- }
}
}
@@ -1763,6 +1764,21 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
}
void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
+ if (rb->views.size() > 1) { // if 1 these are copies ofs rb->internal_texture, rb->depth_texture and rb->texture_fb
+ for (int i = 0; i < rb->views.size(); i++) {
+ if (rb->views[i].view_fb.is_valid()) {
+ RD::get_singleton()->free(rb->views[i].view_fb);
+ }
+ if (rb->views[i].view_texture.is_valid()) {
+ RD::get_singleton()->free(rb->views[i].view_texture);
+ }
+ if (rb->views[i].view_depth.is_valid()) {
+ RD::get_singleton()->free(rb->views[i].view_depth);
+ }
+ }
+ }
+ rb->views.clear();
+
if (rb->texture_fb.is_valid()) {
RD::get_singleton()->free(rb->texture_fb);
rb->texture_fb = RID();
@@ -1811,24 +1827,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
}
for (int i = 0; i < 2; i++) {
- for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
- // do we free the texture slice here? or is it enough to free the main texture?
+ for (int l = 0; l < rb->blur[i].layers.size(); l++) {
+ for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) {
+ // do we free the texture slice here? or is it enough to free the main texture?
- // do free the mobile extra stuff
- if (rb->blur[i].mipmaps[m].fb.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb);
- }
- // texture and framebuffer in both blur mipmaps are shared, so only free from the first one
- if (i == 0) {
- if (rb->blur[i].mipmaps[m].half_fb.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb);
+ // do free the mobile extra stuff
+ if (rb->blur[i].layers[l].mipmaps[m].fb.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].fb);
}
- if (rb->blur[i].mipmaps[m].half_texture.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture);
+ // texture and framebuffer in both blur mipmaps are shared, so only free from the first one
+ if (i == 0) {
+ if (rb->blur[i].layers[l].mipmaps[m].half_fb.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_fb);
+ }
+ if (rb->blur[i].layers[l].mipmaps[m].half_texture.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_texture);
+ }
}
}
}
- rb->blur[i].mipmaps.clear();
+ rb->blur[i].layers.clear();
if (rb->blur[i].texture.is_valid()) {
RD::get_singleton()->free(rb->blur[i].texture);
@@ -1917,6 +1935,21 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->ssr.normal_scaled = RID();
}
+ if (rb->taa.history.is_valid()) {
+ RD::get_singleton()->free(rb->taa.history);
+ rb->taa.history = RID();
+ }
+
+ if (rb->taa.temp.is_valid()) {
+ RD::get_singleton()->free(rb->taa.temp);
+ rb->taa.temp = RID();
+ }
+
+ if (rb->taa.prev_velocity.is_valid()) {
+ RD::get_singleton()->free(rb->taa.prev_velocity);
+ rb->taa.prev_velocity = RID();
+ }
+
if (rb->ambient_buffer.is_valid()) {
RD::get_singleton()->free(rb->ambient_buffer);
RD::get_singleton()->free(rb->reflection_buffer);
@@ -1996,8 +2029,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
_allocate_blur_textures(rb);
}
- storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture);
+ storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture);
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
@@ -2293,18 +2326,53 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) {
ERR_FAIL_COND(!rb);
if (rb->ss_effects.last_frame.is_valid()) {
- storage->get_effects()->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
+ copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
int width = rb->width;
int height = rb->height;
for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) {
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
- storage->get_effects()->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
+ copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
}
}
}
+void RendererSceneRenderRD::_process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far) {
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ bool just_allocated = false;
+ if (rb->taa.history.is_null()) {
+ RD::TextureFormat tf;
+ if (rb->view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
+ tf.format = _render_buffers_get_color_format();
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
+ tf.array_layers = rb->view_count; // create a layer for every view
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
+
+ rb->taa.history = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->taa.temp = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.format = RD::DATA_FORMAT_R16G16_SFLOAT;
+ rb->taa.prev_velocity = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ just_allocated = true;
+ }
+
+ RD::get_singleton()->draw_command_begin_label("TAA");
+ if (!just_allocated) {
+ storage->get_effects()->taa_resolve(rb->internal_texture, rb->taa.temp, rb->depth_texture, p_velocity_buffer, rb->taa.prev_velocity, rb->taa.history, Size2(rb->internal_width, rb->internal_height), p_z_near, p_z_far);
+ copy_effects->copy_to_rect(rb->taa.temp, rb->internal_texture, Rect2(0, 0, rb->internal_width, rb->internal_height));
+ }
+
+ copy_effects->copy_to_rect(rb->internal_texture, rb->taa.history, Rect2(0, 0, rb->internal_width, rb->internal_height));
+ copy_effects->copy_to_rect(p_velocity_buffer, rb->taa.prev_velocity, Rect2(0, 0, rb->width, rb->height));
+ RD::get_singleton()->draw_command_end_label();
+}
+
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -2315,19 +2383,19 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
_allocate_blur_textures(rb);
}
- // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
-
bool can_use_storage = _render_buffers_can_be_storage();
- if (can_use_storage) {
- storage->get_effects()->copy_to_rect(rb->texture, rb->blur[0].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height));
- for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) {
- storage->get_effects()->make_mipmap(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].texture, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height));
- }
- } else {
- storage->get_effects()->copy_to_fb_rect(rb->texture, rb->blur[0].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height));
- for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) {
- storage->get_effects()->make_mipmap_raster(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].fb, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height));
+ for (uint32_t v = 0; v < rb->view_count; v++) {
+ if (can_use_storage) {
+ copy_effects->copy_to_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height));
+ for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) {
+ copy_effects->make_mipmap(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].texture, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height));
+ }
+ } else {
+ copy_effects->copy_to_fb_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height));
+ for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) {
+ copy_effects->make_mipmap_raster(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].fb, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height));
+ }
}
}
@@ -2349,15 +2417,16 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
bool can_use_storage = _render_buffers_can_be_storage();
if (can_use_storage) {
- storage->get_effects()->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height));
+ copy_effects->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height));
} else {
- storage->get_effects()->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height));
+ copy_effects->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height));
}
RD::get_singleton()->draw_command_end_label();
}
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -2368,30 +2437,34 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
bool can_use_storage = _render_buffers_can_be_storage();
- // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
-
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
+ RENDER_TIMESTAMP("Depth of Field");
RD::get_singleton()->draw_command_begin_label("DOF");
if (rb->blur[0].texture.is_null()) {
_allocate_blur_textures(rb);
}
- EffectsRD::BokehBuffers buffers;
+ RendererRD::BokehDOF::BokehBuffers buffers;
// Textures we use
buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
- buffers.base_texture = rb->internal_texture;
- buffers.depth_texture = rb->depth_texture;
- buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
- buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
- buffers.half_texture[1] = rb->blur[0].mipmaps[1].texture;
+ buffers.secondary_texture = rb->blur[0].layers[0].mipmaps[0].texture;
+ buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture;
+ buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture;
float bokeh_size = camfx->dof_blur_amount * 64.0;
if (can_use_storage) {
- storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ for (uint32_t i = 0; i < rb->view_count; i++) {
+ buffers.base_texture = rb->views[i].view_texture;
+ buffers.depth_texture = rb->views[i].view_depth;
+
+ // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
+ float z_near = p_render_data->view_projection[i].get_z_near();
+ float z_far = p_render_data->view_projection[i].get_z_far();
+ bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal);
+ };
} else {
// Set framebuffers.
- buffers.base_fb = rb->texture_fb;
buffers.secondary_fb = rb->weight_buffers[1].fb;
buffers.half_fb[0] = rb->weight_buffers[2].fb;
buffers.half_fb[1] = rb->weight_buffers[3].fb;
@@ -2401,14 +2474,24 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.weight_texture[3] = rb->weight_buffers[3].weight;
// Set weight buffers.
- buffers.base_weight_fb = rb->base_weight_fb;
+ buffers.base_weight_fb = rb->weight_buffers[0].fb;
+
+ for (uint32_t i = 0; i < rb->view_count; i++) {
+ buffers.base_texture = rb->views[i].view_texture;
+ buffers.depth_texture = rb->views[i].view_depth;
+ buffers.base_fb = rb->views[i].view_fb;
- storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
+ float z_near = p_render_data->view_projection[i].get_z_near();
+ float z_far = p_render_data->view_projection[i].get_z_far();
+ bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal);
+ }
}
RD::get_singleton()->draw_command_end_label();
}
if (can_use_effects && env && env->auto_exposure) {
+ RENDER_TIMESTAMP("Auto exposure");
RD::get_singleton()->draw_command_begin_label("Auto exposure");
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
@@ -2436,6 +2519,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
int max_glow_level = -1;
if (can_use_effects && env && env->glow_enabled) {
+ RENDER_TIMESTAMP("Glow");
RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
/* see that blur textures are allocated */
@@ -2446,33 +2530,36 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
if (env->glow_levels[i] > 0.0) {
- if (i >= rb->blur[1].mipmaps.size()) {
- max_glow_level = rb->blur[1].mipmaps.size() - 1;
+ if (i >= rb->blur[1].layers[0].mipmaps.size()) {
+ max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1;
} else {
max_glow_level = i;
}
}
}
- for (int i = 0; i < (max_glow_level + 1); i++) {
- int vp_w = rb->blur[1].mipmaps[i].width;
- int vp_h = rb->blur[1].mipmaps[i].height;
+ float luminance_multiplier = _render_buffers_get_luminance_multiplier();
+ for (uint32_t l = 0; l < rb->view_count; l++) {
+ for (int i = 0; i < (max_glow_level + 1); i++) {
+ int vp_w = rb->blur[1].layers[l].mipmaps[i].width;
+ int vp_h = rb->blur[1].layers[l].mipmaps[i].height;
- if (i == 0) {
- RID luminance_texture;
- if (env->auto_exposure && rb->luminance.current.is_valid()) {
- luminance_texture = rb->luminance.current;
- }
- if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
- } else {
- storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
- }
- } else {
- if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ if (i == 0) {
+ RID luminance_texture;
+ if (env->auto_exposure && rb->luminance.current.is_valid()) {
+ luminance_texture = rb->luminance.current;
+ }
+ if (can_use_storage) {
+ copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ } else {
+ copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ }
} else {
- storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality);
+ if (can_use_storage) {
+ copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ } else {
+ copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ }
}
}
}
@@ -2481,40 +2568,41 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
{
+ RENDER_TIMESTAMP("Tonemap");
RD::get_singleton()->draw_command_begin_label("Tonemap");
- EffectsRD::TonemapSettings tonemap;
+ RendererRD::ToneMapper::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(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
if (can_use_effects && env && env->glow_enabled) {
tonemap.use_glow = true;
- tonemap.glow_mode = EffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode);
+ tonemap.glow_mode = RendererRD::ToneMapper::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];
}
- tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width;
- tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height;
+ tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width;
+ tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
tonemap.glow_texture = rb->blur[1].texture;
if (env->glow_map.is_valid()) {
tonemap.glow_map_strength = env->glow_map_strength;
- tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map);
+ tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map);
} else {
tonemap.glow_map_strength = 0.0f;
- tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
} else {
- tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
@@ -2536,7 +2624,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
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);
+ tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
if (can_use_effects && env) {
tonemap.use_bcs = env->adjustments_enabled;
@@ -2546,30 +2634,31 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
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);
+ tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
}
}
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
- storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+ tone_mapper->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
RD::get_singleton()->draw_command_end_label();
}
if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
- RD::get_singleton()->draw_command_begin_label("FSR Upscale");
+ RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
RD::get_singleton()->draw_command_end_label();
}
- storage->render_target_disable_clear_request(rb->render_target);
+ texture_storage->render_target_disable_clear_request(rb->render_target);
}
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -2583,7 +2672,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
- EffectsRD::TonemapSettings tonemap;
+ RendererRD::ToneMapper::TonemapSettings tonemap;
if (env) {
tonemap.tonemap_mode = env->tone_mapper;
@@ -2606,14 +2695,14 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
}
tonemap.use_glow = false;
- tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
- tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
tonemap.use_auto_exposure = false;
- tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
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);
+ tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
if (can_use_effects && env) {
tonemap.use_bcs = env->adjustments_enabled;
@@ -2623,7 +2712,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
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);
+ tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
}
}
@@ -2633,7 +2722,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
- storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
+ tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
RD::get_singleton()->draw_command_end_label();
}
@@ -2642,11 +2731,12 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- storage->render_target_disable_clear_request(rb->render_target);
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ texture_storage->render_target_disable_clear_request(rb->render_target);
}
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
- EffectsRD *effects = storage->get_effects();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -2656,69 +2746,74 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
if (shadow_atlas_texture.is_null()) {
- shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
}
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
if (directional_shadow_get_texture().is_valid()) {
RID shadow_atlas_texture = directional_shadow_get_texture();
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) {
- RID decal_atlas = storage->decal_atlas_get_texture();
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
if (decal_atlas.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(decal_atlas, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
+ copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
if (rb->luminance.current.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+ copy_effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ copy_effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ copy_effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
RID ambient_texture = rb->ambient_buffer;
RID reflection_texture = rb->reflection_buffer;
- effects->copy_to_fb_rect(ambient_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
+ copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
if (p_occlusion_buffer.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
}
}
+
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(p_render_buffers).is_valid()) {
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ }
}
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) {
@@ -2936,7 +3031,10 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
if (!_render_buffers_can_be_storage()) {
@@ -2946,7 +3044,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (p_width != p_internal_width) {
float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
- storage->sampler_rd_configure_custom(fsr_mipmap_bias);
+ material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);
update_uniform_sets();
}
@@ -2961,6 +3059,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->render_target = p_render_target;
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
+ rb->use_taa = p_use_taa;
rb->use_debanding = p_use_debanding;
rb->view_count = p_view_count;
@@ -3026,19 +3125,45 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
- if (!_render_buffers_can_be_storage()) {
- // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
- Vector<RID> fb;
- fb.push_back(rb->internal_texture);
+ {
+ if (!_render_buffers_can_be_storage()) {
+ // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
+ Vector<RID> fb;
+ fb.push_back(rb->internal_texture);
+
+ rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
+ }
+
+ rb->views.clear(); // JIC
+ if (rb->view_count == 1) {
+ // copy as a convenience
+ RenderBuffers::View view;
+ view.view_texture = rb->internal_texture;
+ view.view_depth = rb->depth_texture;
+ view.view_fb = rb->texture_fb;
+ rb->views.push_back(view);
+ } else {
+ for (uint32_t i = 0; i < rb->view_count; i++) {
+ RenderBuffers::View view;
+ view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->internal_texture, i, 0);
+ view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0);
+
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(view.view_texture);
+ view.view_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, 1);
+ }
- rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
+ rb->views.push_back(view);
+ }
+ }
}
- RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
+ RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
+ rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count);
if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
+ rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
}
}
@@ -3183,6 +3308,7 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
}
void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
cluster.reflection_count = 0;
for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
@@ -3217,30 +3343,30 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
Cluster::ReflectionData &reflection_ubo = cluster.reflections[i];
- Vector3 extents = storage->reflection_probe_get_extents(base_probe);
+ Vector3 extents = light_storage->reflection_probe_get_extents(base_probe);
- rpi->cull_mask = storage->reflection_probe_get_cull_mask(base_probe);
+ rpi->cull_mask = light_storage->reflection_probe_get_cull_mask(base_probe);
reflection_ubo.box_extents[0] = extents.x;
reflection_ubo.box_extents[1] = extents.y;
reflection_ubo.box_extents[2] = extents.z;
reflection_ubo.index = rpi->atlas_index;
- Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
+ Vector3 origin_offset = light_storage->reflection_probe_get_origin_offset(base_probe);
reflection_ubo.box_offset[0] = origin_offset.x;
reflection_ubo.box_offset[1] = origin_offset.y;
reflection_ubo.box_offset[2] = origin_offset.z;
- reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
+ reflection_ubo.mask = light_storage->reflection_probe_get_cull_mask(base_probe);
- reflection_ubo.intensity = storage->reflection_probe_get_intensity(base_probe);
- reflection_ubo.ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
+ reflection_ubo.intensity = light_storage->reflection_probe_get_intensity(base_probe);
+ reflection_ubo.ambient_mode = light_storage->reflection_probe_get_ambient_mode(base_probe);
- reflection_ubo.exterior = !storage->reflection_probe_is_interior(base_probe);
- reflection_ubo.box_project = storage->reflection_probe_is_box_projection(base_probe);
+ reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe);
+ reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe);
- Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear();
- float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
+ Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
+ float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe);
reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
@@ -3262,12 +3388,15 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
}
void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
Transform3D inverse_transform = p_camera_transform.affine_inverse();
r_directional_light_count = 0;
r_positional_light_count = 0;
- Plane camera_plane(-p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
+ Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
cluster.omni_light_count = 0;
cluster.spot_light_count = 0;
@@ -3283,10 +3412,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
ERR_CONTINUE(base.is_null());
- RS::LightType type = storage->light_get_type(base);
+ RS::LightType type = light_storage->light_get_type(base);
switch (type) {
case RS::LIGHT_DIRECTIONAL: {
- if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) {
+ if (r_directional_light_count >= cluster.max_directional_lights || light_storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
continue;
}
@@ -3300,70 +3429,37 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
- float sign = storage->light_is_negative(base) ? -1 : 1;
+ float sign = light_storage->light_is_negative(base) ? -1 : 1;
- light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+ light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
- Color linear_col = storage->light_get_color(base).to_linear();
+ Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
light_data.color[0] = linear_col.r;
light_data.color[1] = linear_col.g;
light_data.color[2] = linear_col.b;
- light_data.specular = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
- light_data.mask = storage->light_get_cull_mask(base);
+ light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
+ light_data.mask = light_storage->light_get_cull_mask(base);
- float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
- Color shadow_col = storage->light_get_shadow_color(base).to_linear();
-
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
- light_data.shadow_color1[0] = 1.0;
- light_data.shadow_color1[1] = 0.0;
- light_data.shadow_color1[2] = 0.0;
- light_data.shadow_color1[3] = 1.0;
- light_data.shadow_color2[0] = 0.0;
- light_data.shadow_color2[1] = 1.0;
- light_data.shadow_color2[2] = 0.0;
- light_data.shadow_color2[3] = 1.0;
- light_data.shadow_color3[0] = 0.0;
- light_data.shadow_color3[1] = 0.0;
- light_data.shadow_color3[2] = 1.0;
- light_data.shadow_color3[3] = 1.0;
- light_data.shadow_color4[0] = 1.0;
- light_data.shadow_color4[1] = 1.0;
- light_data.shadow_color4[2] = 0.0;
- light_data.shadow_color4[3] = 1.0;
-
- } else {
- light_data.shadow_color1[0] = shadow_col.r;
- light_data.shadow_color1[1] = shadow_col.g;
- light_data.shadow_color1[2] = shadow_col.b;
- light_data.shadow_color1[3] = 1.0;
- light_data.shadow_color2[0] = shadow_col.r;
- light_data.shadow_color2[1] = shadow_col.g;
- light_data.shadow_color2[2] = shadow_col.b;
- light_data.shadow_color2[3] = 1.0;
- light_data.shadow_color3[0] = shadow_col.r;
- light_data.shadow_color3[1] = shadow_col.g;
- light_data.shadow_color3[2] = shadow_col.b;
- light_data.shadow_color3[3] = 1.0;
- light_data.shadow_color4[0] = shadow_col.r;
- light_data.shadow_color4[1] = shadow_col.g;
- light_data.shadow_color4[2] = shadow_col.b;
- light_data.shadow_color4[3] = 1.0;
+ WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
}
- light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
+ light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
- float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float angular_diameter = light_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));
- if (storage->light_has_shadow(base)) {
+ if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
r_directional_light_soft_shadows = true;
}
} else {
@@ -3371,10 +3467,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
if (light_data.shadow_enabled) {
- RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
+ RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
- light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && storage->light_directional_get_blend_splits(base);
+ light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
CameraMatrix matrix = li->shadow_transform[j].camera;
@@ -3390,9 +3486,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
float bias_scale = li->shadow_transform[j].bias_scale;
- light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
- light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
- light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
+ light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
+ light_data.shadow_normal_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
+ light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale;
light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin;
RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
@@ -3419,14 +3515,14 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
- float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
+ float fade_start = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
light_data.fade_to = -light_data.shadow_split_offsets[3];
- light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+ light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
- light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
light_data.softshadow_angle = angular_diameter;
- light_data.bake_mode = storage->light_get_bake_mode(base);
+ light_data.bake_mode = light_storage->light_get_bake_mode(base);
if (angular_diameter <= 0.0) {
light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
@@ -3440,8 +3536,22 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
continue;
}
+ const real_t distance = camera_plane.distance_to(li->transform.origin);
+
+ if (light_storage->light_is_distance_fade_enabled(li->light)) {
+ const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ const float fade_length = light_storage->light_get_distance_fade_length(li->light);
+
+ if (distance > fade_begin) {
+ if (distance > fade_begin + fade_length) {
+ // Out of range, don't draw this light to improve performance.
+ continue;
+ }
+ }
+ }
+
cluster.omni_light_sort[cluster.omni_light_count].instance = li;
- cluster.omni_light_sort[cluster.omni_light_count].depth = camera_plane.distance_to(li->transform.origin);
+ cluster.omni_light_sort[cluster.omni_light_count].depth = distance;
cluster.omni_light_count++;
} break;
case RS::LIGHT_SPOT: {
@@ -3449,8 +3559,22 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
continue;
}
+ const real_t distance = camera_plane.distance_to(li->transform.origin);
+
+ if (light_storage->light_is_distance_fade_enabled(li->light)) {
+ const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ const float fade_length = light_storage->light_get_distance_fade_length(li->light);
+
+ if (distance > fade_begin) {
+ if (distance > fade_begin + fade_length) {
+ // Out of range, don't draw this light to improve performance.
+ continue;
+ }
+ }
+ }
+
cluster.spot_light_sort[cluster.spot_light_count].instance = li;
- cluster.spot_light_sort[cluster.spot_light_count].depth = camera_plane.distance_to(li->transform.origin);
+ cluster.spot_light_sort[cluster.spot_light_count].depth = distance;
cluster.spot_light_count++;
} break;
}
@@ -3489,20 +3613,37 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
Transform3D light_transform = li->transform;
- float sign = storage->light_is_negative(base) ? -1 : 1;
- Color linear_col = storage->light_get_color(base).to_linear();
+ float sign = light_storage->light_is_negative(base) ? -1 : 1;
+ Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
- light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
+ light_data.attenuation = light_storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
- float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+ // Reuse fade begin, fade length and distance for shadow LOD determination later.
+ float fade_begin = 0.0;
+ float fade_length = 0.0;
+ real_t distance = 0.0;
+
+ float fade = 1.0;
+ if (light_storage->light_is_distance_fade_enabled(li->light)) {
+ fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ fade_length = light_storage->light_get_distance_fade_length(li->light);
+ distance = camera_plane.distance_to(li->transform.origin);
+
+ if (distance > fade_begin) {
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
+ fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
+ }
+ }
+
+ float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
light_data.color[0] = linear_col.r * energy;
light_data.color[1] = linear_col.g * energy;
light_data.color[2] = linear_col.b * energy;
- light_data.specular_amount = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
- light_data.bake_mode = storage->light_get_bake_mode(base);
+ light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
+ light_data.bake_mode = light_storage->light_get_bake_mode(base);
- float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
+ float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
light_data.inv_radius = 1.0 / radius;
Vector3 pos = inverse_transform.xform(light_transform.origin);
@@ -3517,25 +3658,25 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
- float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
light_data.size = size;
- light_data.inv_spot_attenuation = 1.0f / storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
- float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
- light_data.mask = storage->light_get_cull_mask(base);
+ light_data.mask = light_storage->light_get_cull_mask(base);
light_data.atlas_rect[0] = 0;
light_data.atlas_rect[1] = 0;
light_data.atlas_rect[2] = 0;
light_data.atlas_rect[3] = 0;
- RID projector = storage->light_get_projector(base);
+ RID projector = light_storage->light_get_projector(base);
if (projector.is_valid()) {
- Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector);
if (type == RS::LIGHT_SPOT) {
light_data.projector_rect[0] = rect.position.x;
@@ -3555,21 +3696,31 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.projector_rect[3] = 0;
}
- if (shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
+ const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
+
+ bool in_shadow_range = true;
+ if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
+ if (distance > light_storage->light_get_distance_fade_shadow(li->light)) {
+ // Out of range, don't draw shadows to improve performance.
+ in_shadow_range = false;
+ }
+ }
+
+ if (needs_shadow && in_shadow_range) {
// fill in the shadow information
light_data.shadow_enabled = true;
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
- light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
+ light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
if (type == RS::LIGHT_SPOT) {
- light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
+ light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
} else { //omni
- light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
+ light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
}
- light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
+ light_data.transmittance_bias = light_storage->light_get_transmittance_bias(base);
Vector2i omni_offset;
Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset);
@@ -3579,15 +3730,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.atlas_rect[2] = rect.size.width;
light_data.atlas_rect[3] = rect.size.height;
- light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
- light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+ light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
if (type == RS::LIGHT_OMNI) {
Transform3D proj = (inverse_transform * light_transform).inverse();
RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
- if (size > 0.0) {
+ if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
light_data.soft_shadow_size = size;
} else {
light_data.soft_shadow_size = 0.0;
@@ -3604,7 +3757,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
- if (size > 0.0) {
+ if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
CameraMatrix cm = li->shadow_transform[0].camera;
float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
@@ -3617,7 +3772,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.shadow_enabled = false;
}
- li->cull_mask = storage->light_get_cull_mask(base);
+ li->cull_mask = light_storage->light_get_cull_mask(base);
if (current_cluster_builder != nullptr) {
current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
@@ -3641,6 +3796,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
Transform3D uv_xform;
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
@@ -3664,9 +3821,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
- if (storage->decal_is_distance_fade_enabled(decal)) {
- float fade_begin = storage->decal_get_distance_fade_begin(decal);
- float fade_length = storage->decal_get_distance_fade_length(decal);
+ if (texture_storage->decal_is_distance_fade_enabled(decal)) {
+ float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+ float fade_length = texture_storage->decal_get_distance_fade_length(decal);
if (distance > fade_begin) {
if (distance > fade_begin + fade_length) {
@@ -3694,42 +3851,43 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
_map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i);
}
- di->cull_mask = storage->decal_get_cull_mask(decal);
+ di->cull_mask = texture_storage->decal_get_cull_mask(decal);
Transform3D xform = di->transform;
float fade = 1.0;
- if (storage->decal_is_distance_fade_enabled(decal)) {
- real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
- float fade_begin = storage->decal_get_distance_fade_begin(decal);
- float fade_length = storage->decal_get_distance_fade_length(decal);
+ if (texture_storage->decal_is_distance_fade_enabled(decal)) {
+ const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ const float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+ const float fade_length = texture_storage->decal_get_distance_fade_length(decal);
if (distance > fade_begin) {
- fade = 1.0 - (distance - fade_begin) / fade_length;
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
+ fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
}
}
Cluster::DecalData &dd = cluster.decals[i];
- Vector3 decal_extents = storage->decal_get_extents(decal);
+ Vector3 decal_extents = texture_storage->decal_get_extents(decal);
Transform3D scale_xform;
scale_xform.basis.scale(decal_extents);
Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
RendererStorageRD::store_transform(to_decal_xform, dd.xform);
- Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
+ Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
dd.normal[0] = normal.x;
dd.normal[1] = normal.y;
dd.normal[2] = normal.z;
- dd.normal_fade = storage->decal_get_normal_fade(decal);
+ dd.normal_fade = texture_storage->decal_get_normal_fade(decal);
- RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
- RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
+ RID albedo_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
+ RID emission_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
if (albedo_tex.is_valid()) {
- Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(albedo_tex);
dd.albedo_rect[0] = rect.position.x;
dd.albedo_rect[1] = rect.position.y;
dd.albedo_rect[2] = rect.size.x;
@@ -3744,10 +3902,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.albedo_rect[3] = 0;
}
- RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
+ RID normal_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
if (normal_tex.is_valid()) {
- Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(normal_tex);
dd.normal_rect[0] = rect.position.x;
dd.normal_rect[1] = rect.position.y;
dd.normal_rect[2] = rect.size.x;
@@ -3762,9 +3920,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.normal_rect[3] = 0;
}
- RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
+ RID orm_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
if (orm_tex.is_valid()) {
- Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(orm_tex);
dd.orm_rect[0] = rect.position.x;
dd.orm_rect[1] = rect.position.y;
dd.orm_rect[2] = rect.size.x;
@@ -3777,7 +3935,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
if (emission_tex.is_valid()) {
- Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(emission_tex);
dd.emission_rect[0] = rect.position.x;
dd.emission_rect[1] = rect.position.y;
dd.emission_rect[2] = rect.size.x;
@@ -3789,16 +3947,16 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.emission_rect[3] = 0;
}
- Color modulate = storage->decal_get_modulate(decal);
+ Color modulate = texture_storage->decal_get_modulate(decal);
dd.modulate[0] = modulate.r;
dd.modulate[1] = modulate.g;
dd.modulate[2] = modulate.b;
dd.modulate[3] = modulate.a * fade;
- dd.emission_energy = storage->decal_get_emission_energy(decal) * fade;
- dd.albedo_mix = storage->decal_get_albedo_mix(decal);
- dd.mask = storage->decal_get_cull_mask(decal);
- dd.upper_fade = storage->decal_get_upper_fade(decal);
- dd.lower_fade = storage->decal_get_lower_fade(decal);
+ dd.emission_energy = texture_storage->decal_get_emission_energy(decal) * fade;
+ dd.albedo_mix = texture_storage->decal_get_albedo_mix(decal);
+ dd.mask = texture_storage->decal_get_cull_mask(decal);
+ dd.upper_fade = texture_storage->decal_get_upper_fade(decal);
+ dd.lower_fade = texture_storage->decal_get_lower_fade(decal);
if (current_cluster_builder != nullptr) {
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
@@ -3835,7 +3993,7 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
@@ -3867,45 +4025,45 @@ void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const Strin
}
} else {
if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
+ default_texture_params[p_name] = HashMap<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
+ RBMap<int, StringName> order;
- for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
} else {
- order[E->get().order] = E->key();
+ order[E.value.order] = E.key;
}
}
- for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
- pi.name = E->get();
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
p_param_list->push_back(pi);
}
}
-void RendererSceneRenderRD::FogShaderData::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) {
+void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- 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;
- p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().array_size, E->get().hint);
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
@@ -3936,17 +4094,13 @@ Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const String
}
RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
}
-RendererSceneRenderRD::FogShaderData::FogShaderData() {
- valid = false;
-}
-
RendererSceneRenderRD::FogShaderData::~FogShaderData() {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -3957,8 +4111,8 @@ RendererSceneRenderRD::FogShaderData::~FogShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Fog material
-bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
@@ -3969,23 +4123,23 @@ RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
FogShaderData *shader_data = memnew(FogShaderData);
return shader_data;
}
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
};
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
FogMaterialData *material_data = memnew(FogMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
};
@@ -4042,7 +4196,10 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto
return Vector3i(fog_position);
}
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -4064,7 +4221,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
return;
}
- RENDER_TIMESTAMP(">Volumetric Fog");
+ RENDER_TIMESTAMP("> Volumetric Fog");
RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
@@ -4126,7 +4283,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(rb->volumetric_fog->fog_map);
+ u.append_id(rb->volumetric_fog->fog_map);
uniforms.push_back(u);
}
@@ -4136,7 +4293,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (p_fog_volumes.size() > 0) {
RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
- RENDER_TIMESTAMP("Render Fog Volumes");
+ RENDER_TIMESTAMP("Render FogVolumes");
VolumetricFogShader::VolumeUBO params;
@@ -4174,7 +4331,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.detail_spread = env->volumetric_fog_detail_spread;
params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
- Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
storage->store_transform(to_prev_cam_view, params.to_prev_view);
storage->store_transform(p_cam_transform, params.transform);
@@ -4191,7 +4348,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 1;
- u.ids.push_back(rb->volumetric_fog->emissive_map);
+ u.append_id(rb->volumetric_fog->emissive_map);
uniforms.push_back(u);
}
@@ -4199,7 +4356,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 2;
- u.ids.push_back(volumetric_fog.volume_ubo);
+ u.append_id(volumetric_fog.volume_ubo);
uniforms.push_back(u);
}
@@ -4211,7 +4368,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 3;
- u.ids.push_back(rb->volumetric_fog->density_map);
+ u.append_id(rb->volumetric_fog->density_map);
uniforms.push_back(u);
}
@@ -4223,7 +4380,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 4;
- u.ids.push_back(rb->volumetric_fog->light_map);
+ u.append_id(rb->volumetric_fog->light_map);
uniforms.push_back(u);
}
@@ -4243,7 +4400,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
FogMaterialData *material = nullptr;
if (fog_material.is_valid()) {
- material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -4251,7 +4408,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (!material) {
fog_material = volumetric_fog.default_material;
- material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
}
ERR_FAIL_COND(!material);
@@ -4270,7 +4427,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RS::FogVolumeShape volume_type = storage->fog_volume_get_shape(fog_volume);
Vector3 extents = storage->fog_volume_get_extents(fog_volume);
- if (volume_type == RS::FOG_VOLUME_SHAPE_BOX || volume_type == RS::FOG_VOLUME_SHAPE_ELLIPSOID) {
+ if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
+ // Local fog volume.
Vector3i points[8];
points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
@@ -4344,9 +4502,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 1;
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
} else {
- u.ids.push_back(shadow_atlas->depth);
+ u.append_id(shadow_atlas->depth);
}
uniforms.push_back(u);
@@ -4358,9 +4516,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
if (directional_shadow.depth.is_valid()) {
- u.ids.push_back(directional_shadow.depth);
+ u.append_id(directional_shadow.depth);
} else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
}
uniforms.push_back(u);
copy_uniforms.push_back(u);
@@ -4370,7 +4528,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 3;
- u.ids.push_back(get_omni_light_buffer());
+ u.append_id(get_omni_light_buffer());
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4378,7 +4536,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 4;
- u.ids.push_back(get_spot_light_buffer());
+ u.append_id(get_spot_light_buffer());
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4387,7 +4545,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 5;
- u.ids.push_back(get_directional_light_buffer());
+ u.append_id(get_directional_light_buffer());
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4396,7 +4554,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 6;
- u.ids.push_back(rb->cluster_builder->get_cluster_buffer());
+ u.append_id(rb->cluster_builder->get_cluster_buffer());
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4405,7 +4563,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4414,7 +4572,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 8;
- u.ids.push_back(rb->volumetric_fog->light_density_map);
+ u.append_id(rb->volumetric_fog->light_density_map);
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4423,7 +4581,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.ids.push_back(rb->volumetric_fog->fog_map);
+ u.append_id(rb->volumetric_fog->fog_map);
uniforms.push_back(u);
}
@@ -4431,7 +4589,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+ u.append_id(rb->volumetric_fog->prev_light_density_map);
copy_uniforms.push_back(u);
}
@@ -4439,7 +4597,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 10;
- u.ids.push_back(shadow_sampler);
+ u.append_id(shadow_sampler);
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4448,7 +4606,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 11;
- u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers));
+ u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers));
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4458,7 +4616,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 12;
for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) {
- u.ids.push_back(rb->gi.voxel_gi_textures[i]);
+ u.append_id(rb->gi.voxel_gi_textures[i]);
}
uniforms.push_back(u);
copy_uniforms.push_back(u);
@@ -4467,7 +4625,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
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));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4475,7 +4633,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 14;
- u.ids.push_back(volumetric_fog.params_ubo);
+ u.append_id(volumetric_fog.params_ubo);
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4483,7 +4641,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 15;
- u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+ u.append_id(rb->volumetric_fog->prev_light_density_map);
uniforms.push_back(u);
}
{
@@ -4494,7 +4652,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 16;
- u.ids.push_back(rb->volumetric_fog->density_map);
+ u.append_id(rb->volumetric_fog->density_map);
uniforms.push_back(u);
}
{
@@ -4505,7 +4663,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 17;
- u.ids.push_back(rb->volumetric_fog->light_map);
+ u.append_id(rb->volumetric_fog->light_map);
uniforms.push_back(u);
}
@@ -4517,7 +4675,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 18;
- u.ids.push_back(rb->volumetric_fog->emissive_map);
+ u.append_id(rb->volumetric_fog->emissive_map);
uniforms.push_back(u);
}
@@ -4525,9 +4683,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 19;
- 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);
+ RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
- u.ids.push_back(sky_texture.is_valid() ? sky_texture : radiance_texture);
+ u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
uniforms.push_back(u);
}
@@ -4535,7 +4693,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
- SWAP(uniforms.write[7].ids.write[0], uniforms.write[8].ids.write[0]);
+ RID aux7 = uniforms.write[7].get_id(0);
+ RID aux8 = uniforms.write[8].get_id(0);
+
+ uniforms.write[7].set_id(0, aux8);
+ uniforms.write[8].set_id(0, aux7);
rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0);
}
@@ -4550,7 +4712,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 0;
- u.ids.push_back(gi.sdfgi_ubo);
+ u.append_id(gi.sdfgi_ubo);
uniforms.push_back(u);
}
@@ -4558,7 +4720,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- u.ids.push_back(rb->sdfgi->ambient_texture);
+ u.append_id(rb->sdfgi->ambient_texture);
uniforms.push_back(u);
}
@@ -4566,7 +4728,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- u.ids.push_back(rb->sdfgi->occlusion_texture);
+ u.append_id(rb->sdfgi->occlusion_texture);
uniforms.push_back(u);
}
@@ -4604,7 +4766,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.fog_frustum_end = fog_end;
- Color ambient_color = env->ambient_light.to_linear();
+ Color ambient_color = env->ambient_light.srgb_to_linear();
params.ambient_color[0] = ambient_color.r;
params.ambient_color[1] = ambient_color.g;
params.ambient_color[2] = ambient_color.b;
@@ -4616,13 +4778,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.directional_light_count = p_directional_light_count;
- Color emission = env->volumetric_fog_emission.to_linear();
+ Color emission = env->volumetric_fog_emission.srgb_to_linear();
params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
params.base_density = env->volumetric_fog_density;
- Color base_scattering = env->volumetric_fog_scattering.to_linear();
+ Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear();
params.base_scattering[0] = base_scattering.r;
params.base_scattering[1] = base_scattering.g;
params.base_scattering[2] = base_scattering.b;
@@ -4647,7 +4809,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0;
params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
- Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
storage->store_transform(to_prev_cam_view, params.to_prev_view);
params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
@@ -4730,11 +4892,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
- RENDER_TIMESTAMP("<Volumetric Fog");
+ RENDER_TIMESTAMP("< Volumetric Fog");
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_command_end_label();
-
- rb->volumetric_fog->prev_cam_transform = p_cam_transform;
}
bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
@@ -4772,6 +4932,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
if (p_render_data->render_buffers.is_valid() && p_use_gi) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -4785,15 +4946,15 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
render_state.shadows.clear();
render_state.directional_shadows.clear();
- Plane camera_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
+ Plane camera_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < render_state.render_shadow_count; i++) {
LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light);
- if (storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
+ if (light_storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
render_state.directional_shadows.push_back(i);
- } else if (storage->light_get_type(li->light) == RS::LIGHT_OMNI && storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ } else if (light_storage->light_get_type(li->light) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
render_state.cube_shadows.push_back(i);
} else {
render_state.shadows.push_back(i);
@@ -4819,7 +4980,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
bool render_gi = p_render_data->render_buffers.is_valid() && p_use_gi;
if (render_shadows && render_gi) {
- RENDER_TIMESTAMP("Render GI + Render Shadows (parallel)");
+ RENDER_TIMESTAMP("Render GI + Render Shadows (Parallel)");
} else if (render_shadows) {
RENDER_TIMESTAMP("Render Shadows");
} else if (render_gi) {
@@ -4903,7 +5064,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
bool using_shadows = true;
if (p_render_data->reflection_probe.is_valid()) {
- if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (!RSG::light_storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
using_shadows = false;
}
} else {
@@ -4931,12 +5092,14 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
if (is_volumetric_supported()) {
- _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes);
+ _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes);
}
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -4953,13 +5116,22 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.cam_transform = p_camera_data->main_transform;
render_data.cam_projection = p_camera_data->main_projection;
render_data.view_projection[0] = p_camera_data->main_projection;
- render_data.cam_ortogonal = p_camera_data->is_ortogonal;
+ render_data.cam_orthogonal = p_camera_data->is_orthogonal;
+ render_data.taa_jitter = p_camera_data->taa_jitter;
render_data.view_count = p_camera_data->view_count;
for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
render_data.view_projection[v] = p_camera_data->view_projection[v];
}
+ render_data.prev_cam_transform = p_prev_camera_data->main_transform;
+ render_data.prev_cam_projection = p_prev_camera_data->main_projection;
+ render_data.prev_taa_jitter = p_prev_camera_data->taa_jitter;
+
+ for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
+ render_data.prev_view_projection[v] = p_prev_camera_data->view_projection[v];
+ }
+
render_data.z_near = p_camera_data->main_projection.get_z_near();
render_data.z_far = p_camera_data->main_projection.get_z_far();
@@ -4979,7 +5151,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// this should be the same for all cameras..
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
+ render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_column(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
render_data.screen_mesh_lod_threshold = 0.0;
@@ -5015,7 +5187,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
Color clear_color;
if (p_render_buffers.is_valid()) {
- clear_color = storage->render_target_get_clear_request_color(rb->render_target);
+ clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target);
} else {
clear_color = storage->get_default_clear_color();
}
@@ -5072,7 +5244,6 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
if (p_render_buffers.is_valid()) {
/*
_debug_draw_cluster(p_render_buffers);
- RENDER_TIMESTAMP("Tonemap");
_render_buffers_post_process_and_tonemap(&render_data);
*/
@@ -5134,7 +5305,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
CameraMatrix light_projection;
Transform3D light_transform;
- if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
+ if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
//set pssm stuff
if (light_instance->last_scene_shadow_pass != scene_pass) {
light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
@@ -5142,13 +5313,13 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
light_instance->last_scene_shadow_pass = scene_pass;
}
- use_pancake = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
+ use_pancake = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
light_projection = light_instance->shadow_transform[p_pass].camera;
light_transform = light_instance->shadow_transform[p_pass].transform;
atlas_rect = light_instance->directional_rect;
- if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+ if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
atlas_rect.size.width /= 2;
atlas_rect.size.height /= 2;
@@ -5159,7 +5330,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
} else if (p_pass == 3) {
atlas_rect.position += atlas_rect.size;
}
- } else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+ } else if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
atlas_rect.size.height /= 2;
if (p_pass == 0) {
@@ -5173,7 +5344,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
- zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
+ zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
render_fb = directional_shadow.fb;
render_texture = RID();
@@ -5207,13 +5378,13 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
atlas_rect.size.width = shadow_size;
atlas_rect.size.height = shadow_size;
- zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
+ zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
- if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
+ if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
bool wrap = (shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision == 0;
dual_paraboloid_offset = wrap ? Vector2i(1 - shadow_atlas->quadrants[quadrant].subdivision, 1) : Vector2i(1, 0);
- if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ if (RSG::light_storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2);
render_fb = cubemap->side_fb[p_pass];
@@ -5248,7 +5419,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
flip_y = true;
}
- } else if (storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
+ } else if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
@@ -5282,13 +5453,15 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
}
}
-void RendererSceneRenderRD::render_material(const Transform3D &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 RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+ _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region);
}
void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &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();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
+
+ ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
+ Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
CameraMatrix cm;
cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
@@ -5296,9 +5469,9 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
cam_pos.y += extents.y;
Transform3D cam_xform;
- cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_axis(Vector3::AXIS_Y), -p_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
+ cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_column(Vector3::AXIS_Y), -p_transform.basis.get_column(Vector3::AXIS_Z).normalized());
- RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
+ RID fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);
_render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);
}
@@ -5364,8 +5537,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
//remove from shadow atlases..
- for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E->get());
+ for (const RID &E : light_instance->shadow_atlases) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E);
ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
uint32_t key = shadow_atlas->shadow_owners[p_rid];
uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
@@ -5464,7 +5637,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
GeometryInstance *gi = geometry_instance_create(p_base);
- uint32_t sc = RSG::storage->mesh_get_surface_count(p_base);
+ uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base);
Vector<RID> materials;
materials.resize(sc);
@@ -5581,6 +5754,8 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
}
void RendererSceneRenderRD::init() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
max_cluster_elements = get_max_elements();
directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
@@ -5637,8 +5812,8 @@ void RendererSceneRenderRD::init() {
volumetric_fog_modes.push_back("");
volumetric_fog.shader.initialize(volumetric_fog_modes);
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
}
@@ -5677,9 +5852,9 @@ void RendererSceneRenderRD::init() {
{
// default material and shader for fog shader
- volumetric_fog.default_shader = storage->shader_allocate();
- storage->shader_initialize(volumetric_fog.default_shader);
- storage->shader_set_code(volumetric_fog.default_shader, R"(
+ volumetric_fog.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(volumetric_fog.default_shader);
+ material_storage->shader_set_code(volumetric_fog.default_shader, R"(
// Default fog shader.
shader_type fog;
@@ -5689,33 +5864,33 @@ void fog() {
ALBEDO = vec3(1.0);
}
)");
- volumetric_fog.default_material = storage->material_allocate();
- storage->material_initialize(volumetric_fog.default_material);
- storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+ volumetric_fog.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(volumetric_fog.default_material);
+ material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
- FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG);
+ FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG));
volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
{
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 1;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
uniforms.push_back(u);
}
@@ -5723,7 +5898,7 @@ void fog() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -5789,9 +5964,26 @@ void fog() {
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
cull_argument.set_page_pool(&cull_argument_pool);
+
+ bool can_use_storage = _render_buffers_can_be_storage();
+ bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
+ copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
+ tone_mapper = memnew(RendererRD::ToneMapper);
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ if (bokeh_dof) {
+ memdelete(bokeh_dof);
+ }
+ if (copy_effects) {
+ memdelete(copy_effects);
+ }
+ if (tone_mapper) {
+ memdelete(tone_mapper);
+ }
+
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
RD::get_singleton()->free(E.value.cubemap);
}
@@ -5808,20 +6000,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
RD::get_singleton()->free(volumetric_fog.volume_ubo);
RD::get_singleton()->free(volumetric_fog.params_ubo);
- storage->free(volumetric_fog.default_shader);
- storage->free(volumetric_fog.default_material);
- }
-
- RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
- sky.sky_shader.shader.version_free(md->shader_data->version);
- RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer);
- RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer);
- memdelete_arr(sky.sky_scene_state.directional_lights);
- memdelete_arr(sky.sky_scene_state.last_frame_directional_lights);
- storage->free(sky.sky_shader.default_shader);
- storage->free(sky.sky_shader.default_material);
- storage->free(sky.sky_scene_state.fog_shader);
- storage->free(sky.sky_scene_state.fog_material);
+ material_storage->shader_free(volumetric_fog.default_shader);
+ material_storage->material_free(volumetric_fog.default_material);
+ }
+
memdelete_arr(directional_penumbra_shadow_kernel);
memdelete_arr(directional_soft_shadow_kernel);
memdelete_arr(penumbra_shadow_kernel);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 47bc0af1db..1b1df6469e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -35,6 +35,9 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
@@ -46,16 +49,22 @@
#include "servers/rendering/rendering_device.h"
struct RenderDataRD {
- RID render_buffers = RID();
+ RID render_buffers;
- Transform3D cam_transform = Transform3D();
- CameraMatrix cam_projection = CameraMatrix();
- bool cam_ortogonal = false;
+ Transform3D cam_transform;
+ CameraMatrix cam_projection;
+ Vector2 taa_jitter;
+ bool cam_orthogonal = false;
// For stereo rendering
uint32_t view_count = 1;
CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Transform3D prev_cam_transform;
+ CameraMatrix prev_cam_projection;
+ Vector2 prev_taa_jitter;
+ CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
float z_near = 0.0;
float z_far = 0.0;
@@ -66,18 +75,18 @@ struct RenderDataRD {
const PagedArray<RID> *decals = nullptr;
const PagedArray<RID> *lightmaps = nullptr;
const PagedArray<RID> *fog_volumes = nullptr;
- RID environment = RID();
- RID camera_effects = RID();
- RID shadow_atlas = RID();
- RID reflection_atlas = RID();
- RID reflection_probe = RID();
+ RID environment;
+ RID camera_effects;
+ RID shadow_atlas;
+ RID reflection_atlas;
+ RID reflection_probe;
int reflection_probe_pass = 0;
float lod_distance_multiplier = 0.0;
- Plane lod_camera_plane = Plane();
+ Plane lod_camera_plane;
float screen_mesh_lod_threshold = 0.0;
- RID cluster_buffer = RID();
+ RID cluster_buffer;
uint32_t cluster_size = 0;
uint32_t cluster_max_elements = 0;
@@ -92,12 +101,15 @@ class RendererSceneRenderRD : public RendererSceneRender {
friend RendererSceneGIRD;
protected:
- RendererStorageRD *storage;
- double time;
- double time_step = 0;
+ RendererStorageRD *storage = nullptr;
+ RendererRD::BokehDOF *bokeh_dof = nullptr;
+ RendererRD::CopyEffects *copy_effects = nullptr;
+ RendererRD::ToneMapper *tone_mapper = nullptr;
+ double time = 0.0;
+ double time_step = 0.0;
struct RenderBufferData {
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
@@ -113,7 +125,7 @@ protected:
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
- virtual void _render_material(const Transform3D &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_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, 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 Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
@@ -125,13 +137,14 @@ protected:
virtual void _base_uniforms_changed() = 0;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
+ virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
void _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 _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform);
void _copy_framebuffer_to_ssil(RID p_render_buffers);
- void _ensure_ss_effects(RID p_render_buffers, bool p_using_ssil);
+ void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
@@ -234,7 +247,7 @@ private:
struct DecalInstance {
RID decal;
Transform3D transform;
- uint32_t cull_mask;
+ uint32_t cull_mask = 0;
ForwardID forward_id = -1;
};
@@ -254,7 +267,7 @@ private:
struct ShadowShrinkStage {
RID texture;
RID filter_texture;
- uint32_t size;
+ uint32_t size = 0;
};
struct ShadowAtlas {
@@ -266,27 +279,20 @@ private:
};
struct Quadrant {
- uint32_t subdivision;
+ uint32_t subdivision = 0;
struct Shadow {
RID owner;
- uint64_t version;
- uint64_t fog_version; // used for fog
- uint64_t alloc_tick;
-
- Shadow() {
- version = 0;
- fog_version = 0;
- alloc_tick = 0;
- }
+ uint64_t version = 0;
+ uint64_t fog_version = 0; // used for fog
+ uint64_t alloc_tick = 0;
+
+ Shadow() {}
};
Vector<Shadow> shadows;
- Quadrant() {
- subdivision = 0; //not in use
- }
-
+ Quadrant() {}
} quadrants[4];
int size_order[4] = { 0, 1, 2, 3 };
@@ -298,7 +304,7 @@ private:
RID depth;
RID fb; //for copying
- Map<RID, uint32_t> shadow_owners;
+ HashMap<RID, uint32_t> shadow_owners;
};
RID_Owner<ShadowAtlas> shadow_atlas_owner;
@@ -314,10 +320,10 @@ private:
float shadows_quality_radius = 1.0;
float directional_shadow_quality_radius = 1.0;
- float *directional_penumbra_shadow_kernel;
- float *directional_soft_shadow_kernel;
- float *penumbra_shadow_kernel;
- float *soft_shadow_kernel;
+ float *directional_penumbra_shadow_kernel = nullptr;
+ float *directional_soft_shadow_kernel = nullptr;
+ float *penumbra_shadow_kernel = nullptr;
+ float *soft_shadow_kernel = nullptr;
int directional_penumbra_shadow_samples = 0;
int directional_soft_shadow_samples = 0;
int penumbra_shadow_samples = 0;
@@ -335,7 +341,6 @@ private:
int size = 0;
bool use_16_bits = true;
int current_light = 0;
-
} directional_shadow;
void _update_directional_shadow_atlas();
@@ -347,7 +352,7 @@ private:
RID side_fb[6];
};
- Map<int, ShadowCubemap> shadow_cubemaps;
+ HashMap<int, ShadowCubemap> shadow_cubemaps;
ShadowCubemap *_get_shadow_cubemap(int p_size);
void _create_shadow_cubemaps();
@@ -389,7 +394,7 @@ private:
Rect2 directional_rect;
- Set<RID> shadow_atlases; //shadow atlases where this light is registered
+ HashSet<RID> shadow_atlases; //shadow atlases where this light is registered
ForwardID forward_id = -1;
@@ -474,6 +479,7 @@ private:
float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+ bool use_taa = false;
bool use_debanding = false;
uint32_t view_count = 1;
@@ -488,6 +494,14 @@ private:
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
+ // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
+ struct View {
+ RID view_texture; // texture slice for this view/layer
+ RID view_depth; // depth slice for this view/layer
+ RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
+ };
+ Vector<View> views;
+
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
RendererSceneGIRD::RenderBuffersGI gi;
@@ -509,19 +523,22 @@ private:
RID half_fb;
};
- Vector<Mipmap> mipmaps;
+ struct Layer {
+ Vector<Mipmap> mipmaps;
+ };
+
+ Vector<Layer> layers;
};
Blur blur[2]; //the second one starts from the first mipmap
struct WeightBuffers {
RID weight;
- RID fb; // FB with both texture and weight
+ RID fb; // FB with both texture and weight writing into one level lower
};
// 2 full size, 2 half size
WeightBuffers weight_buffers[4]; // Only used in raster
- RID base_weight_fb; // base buffer for weight
RID depth_back_texture;
RID depth_back_fb; // only used on mobile
@@ -583,6 +600,12 @@ private:
RID blur_radius[2];
} ssr;
+ struct TAA {
+ RID history;
+ RID temp;
+ RID prev_velocity; // Last frame velocity buffer
+ } taa;
+
RID ambient_buffer;
RID reflection_buffer;
};
@@ -678,10 +701,6 @@ private:
float shadow_range_begin[4];
float shadow_split_offsets[4];
float shadow_matrices[4][16];
- float shadow_color1[4];
- float shadow_color2[4];
- float shadow_color3[4];
- float shadow_color4[4];
float uv_scale1[2];
float uv_scale2[2];
float uv_scale3[2];
@@ -709,27 +728,27 @@ private:
template <class T>
struct InstanceSort {
float depth;
- T *instance;
+ T *instance = nullptr;
bool operator<(const InstanceSort &p_sort) const {
return depth < p_sort.depth;
}
};
- ReflectionData *reflections;
+ ReflectionData *reflections = nullptr;
InstanceSort<ReflectionProbeInstance> *reflection_sort;
uint32_t max_reflections;
RID reflection_buffer;
uint32_t max_reflection_probes_per_instance;
uint32_t reflection_count = 0;
- DecalData *decals;
+ DecalData *decals = nullptr;
InstanceSort<DecalInstance> *decal_sort;
uint32_t max_decals;
RID decal_buffer;
uint32_t decal_count;
- LightData *omni_lights;
- LightData *spot_lights;
+ LightData *omni_lights = nullptr;
+ LightData *spot_lights = nullptr;
InstanceSort<LightInstance> *omni_light_sort;
InstanceSort<LightInstance> *spot_light_sort;
@@ -739,7 +758,7 @@ private:
uint32_t omni_light_count = 0;
uint32_t spot_light_count = 0;
- DirectionalLightData *directional_lights;
+ DirectionalLightData *directional_lights = nullptr;
uint32_t max_directional_lights;
RID directional_light_buffer;
@@ -788,8 +807,6 @@ private:
RID sky_uniform_set;
int last_shadow_filter = -1;
-
- Transform3D prev_cam_transform;
};
struct VolumetricFogShader {
@@ -909,54 +926,55 @@ private:
Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+ void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
- struct FogShaderData : public RendererStorageRD::ShaderData {
- bool valid;
+ struct FogShaderData : public RendererRD::ShaderData {
+ bool valid = false;
RID version;
RID pipeline;
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String path;
String code;
- Map<StringName, Map<int, RID>> default_texture_params;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
- bool uses_time;
+ bool uses_time = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- FogShaderData();
+
+ FogShaderData() {}
virtual ~FogShaderData();
};
- struct FogMaterialData : public RendererStorageRD::MaterialData {
- FogShaderData *shader_data;
+ struct FogMaterialData : public RendererRD::MaterialData {
+ FogShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~FogMaterialData();
};
- RendererStorageRD::ShaderData *_create_fog_shader_func();
- static RendererStorageRD::ShaderData *_create_fog_shader_funcs();
+ RendererRD::ShaderData *_create_fog_shader_func();
+ static RendererRD::ShaderData *_create_fog_shader_funcs();
- RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader);
+ RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
RID shadow_sampler;
@@ -1379,7 +1397,7 @@ public:
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
@@ -1413,9 +1431,9 @@ public:
virtual void update_uniform_sets(){};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index b44ae6cf8d..3a237dbd8c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -32,7 +32,10 @@
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
#include "renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
////////////////////////////////////////////////////////////////////////////////
@@ -89,7 +92,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
// !BAS! Contemplate making `SkyShader sky` accessible from this struct or even part of this struct.
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
Error err = scene_singleton->sky.sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
@@ -148,14 +151,14 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa
}
} else {
if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
+ default_texture_params[p_name] = HashMap<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
+ HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
@@ -176,13 +179,13 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
}
}
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -217,17 +220,13 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam
}
RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
}
-RendererSceneSkyRD::SkyShaderData::SkyShaderData() {
- valid = false;
-}
-
RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
@@ -238,8 +237,8 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Sky material
-bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
@@ -254,17 +253,17 @@ RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
// Render sky
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
- p_array[0] = p_basis.elements[0][0];
- p_array[1] = p_basis.elements[1][0];
- p_array[2] = p_basis.elements[2][0];
+ p_array[0] = p_basis.rows[0][0];
+ p_array[1] = p_basis.rows[1][0];
+ p_array[2] = p_basis.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_basis.elements[0][1];
- p_array[5] = p_basis.elements[1][1];
- p_array[6] = p_basis.elements[2][1];
+ p_array[4] = p_basis.rows[0][1];
+ p_array[5] = p_basis.rows[1][1];
+ p_array[6] = p_basis.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_basis.elements[0][2];
- p_array[9] = p_basis.elements[1][2];
- p_array[10] = p_basis.elements[2][2];
+ p_array[8] = p_basis.rows[0][2];
+ p_array[9] = p_basis.rows[1][2];
+ p_array[10] = p_basis.rows[2][2];
p_array[11] = 0;
}
@@ -362,8 +361,8 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, 1, RD::TEXTURE_SLICE_CUBEMAP);
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
+ mmw = MAX(1u, mmw >> 1);
+ mmh = MAX(1u, mmh >> 1);
}
layers.push_back(layer);
@@ -390,8 +389,8 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, 1, RD::TEXTURE_SLICE_CUBEMAP);
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
+ mmw = MAX(1u, mmw >> 1);
+ mmh = MAX(1u, mmh >> 1);
}
layers.push_back(layer);
@@ -432,8 +431,8 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
}
}
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
+ mmw = MAX(1u, mmw >> 1);
+ mmh = MAX(1u, mmh >> 1);
}
}
}
@@ -621,6 +620,8 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
}
RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) {
return texture_uniform_sets[p_version];
}
@@ -630,9 +631,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
- u.ids.push_back(radiance);
+ u.append_id(radiance);
} else {
- u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
uniforms.push_back(u);
}
@@ -642,15 +643,15 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
u.binding = 1; // half res
if (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) {
- u.ids.push_back(reflection.layers[0].views[1]);
+ u.append_id(reflection.layers[0].views[1]);
} else {
- u.ids.push_back(half_res_pass);
+ u.append_id(half_res_pass);
}
} else {
if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
} else {
- u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
}
uniforms.push_back(u);
@@ -661,15 +662,15 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
u.binding = 2; // quarter res
if (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) {
- u.ids.push_back(reflection.layers[0].views[2]);
+ u.append_id(reflection.layers[0].views[2]);
} else {
- u.ids.push_back(quarter_res_pass);
+ u.append_id(quarter_res_pass);
}
} else {
if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
} else {
- u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
}
uniforms.push_back(u);
@@ -730,8 +731,10 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
return true;
}
-Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size) {
+Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
if (radiance.is_valid()) {
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
tf.width = p_size.width;
@@ -739,7 +742,7 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
- p_storage->get_effects()->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1);
+ copy_effects->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1);
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);
RD::get_singleton()->free(rad_tex);
@@ -764,24 +767,24 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
////////////////////////////////////////////////////////////////////////////////
// RendererSceneSkyRD
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
// !BAS! Why isn't _create_sky_shader_func not just static too?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
};
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
// !BAS! same here, we could just make _create_sky_material_func static?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
@@ -793,6 +796,8 @@ RendererSceneSkyRD::RendererSceneSkyRD() {
}
void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{
@@ -829,8 +834,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
}
// register our shader funds
- 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);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -841,6 +846,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
actions.renames["POSITION"] = "params.position_multiplier.xyz";
actions.renames["SKY_COORDS"] = "panorama_coords";
actions.renames["SCREEN_UV"] = "uv";
+ actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["TIME"] = "params.time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
@@ -892,10 +898,10 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
{
// default material and shader for sky shader
- sky_shader.default_shader = storage->shader_allocate();
- storage->shader_initialize(sky_shader.default_shader);
+ sky_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(sky_shader.default_shader);
- storage->shader_set_code(sky_shader.default_shader, R"(
+ material_storage->shader_set_code(sky_shader.default_shader, R"(
// Default sky shader.
shader_type sky;
@@ -905,12 +911,12 @@ void sky() {
}
)");
- sky_shader.default_material = storage->material_allocate();
- storage->material_initialize(sky_shader.default_material);
+ sky_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(sky_shader.default_material);
- storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
+ material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
- SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::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));
@@ -918,23 +924,24 @@ void sky() {
Vector<RD::Uniform> uniforms;
{
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 0;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids);
+
uniforms.push_back(u);
}
@@ -942,7 +949,7 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -950,7 +957,7 @@ void sky() {
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(sky_scene_state.uniform_buffer);
+ u.append_id(sky_scene_state.uniform_buffer);
uniforms.push_back(u);
}
@@ -958,7 +965,7 @@ void sky() {
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.ids.push_back(sky_scene_state.directional_light_buffer);
+ u.append_id(sky_scene_state.directional_light_buffer);
uniforms.push_back(u);
}
@@ -971,8 +978,8 @@ void sky() {
RD::Uniform u;
u.binding = 0;
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);
+ RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ u.append_id(vfog);
uniforms.push_back(u);
}
@@ -981,10 +988,10 @@ void sky() {
{
// Need defaults for using fog with clear color
- sky_scene_state.fog_shader = storage->shader_allocate();
- storage->shader_initialize(sky_scene_state.fog_shader);
+ sky_scene_state.fog_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(sky_scene_state.fog_shader);
- storage->shader_set_code(sky_scene_state.fog_shader, R"(
+ material_storage->shader_set_code(sky_scene_state.fog_shader, R"(
// Default clear color sky shader.
shader_type sky;
@@ -995,31 +1002,31 @@ void sky() {
COLOR = clear_color.rgb;
}
)");
- sky_scene_state.fog_material = storage->material_allocate();
- storage->material_initialize(sky_scene_state.fog_material);
+ sky_scene_state.fog_material = material_storage->material_allocate();
+ material_storage->material_initialize(sky_scene_state.fog_material);
- storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
+ material_storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
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_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
@@ -1049,7 +1056,19 @@ void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
}
RendererSceneSkyRD::~RendererSceneSkyRD() {
- // TODO cleanup anything created in init...
+ // cleanup anything created in init...
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::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);
+ memdelete_arr(sky_scene_state.directional_lights);
+ memdelete_arr(sky_scene_state.last_frame_directional_lights);
+ material_storage->shader_free(sky_shader.default_shader);
+ material_storage->material_free(sky_shader.default_material);
+ material_storage->shader_free(sky_scene_state.fog_shader);
+ material_storage->material_free(sky_scene_state.fog_material);
if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
RD::get_singleton()->free(sky_scene_state.uniform_set);
@@ -1067,6 +1086,8 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
}
void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
SkyMaterialData *material = nullptr;
@@ -1080,7 +1101,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1088,7 +1109,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1161,27 +1182,27 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
ERR_CONTINUE(base.is_null());
- RS::LightType type = storage->light_get_type(base);
- if (type == RS::LIGHT_DIRECTIONAL) {
+ RS::LightType type = light_storage->light_get_type(base);
+ if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count];
Transform3D light_transform = li->transform;
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.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);
+ float sign = light_storage->light_is_negative(base) ? -1 : 1;
+ sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
- Color linear_col = storage->light_get_color(base).to_linear();
+ Color linear_col = light_storage->light_get_color(base).srgb_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);
+ float angular_diameter = light_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
@@ -1266,7 +1287,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_scene_state.ubo.fog_enabled = p_env->fog_enabled;
sky_scene_state.ubo.fog_density = p_env->fog_density;
sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective;
- Color fog_color = p_env->fog_light_color.to_linear();
+ Color fog_color = p_env->fog_light_color.srgb_to_linear();
float fog_energy = p_env->fog_light_energy;
sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
@@ -1277,6 +1298,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
}
void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@@ -1287,7 +1309,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1295,7 +1317,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1445,6 +1467,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1462,7 +1485,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1470,13 +1493,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::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, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1508,7 +1531,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
projections = &camera;
}
- sky_transform = p_transform.basis * sky_transform;
+ sky_transform = sky_transform * p_transform.basis;
if (shader_data->uses_quarter_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
@@ -1551,6 +1574,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1565,7 +1589,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1573,7 +1597,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1635,6 +1659,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
}
void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1652,7 +1677,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1660,13 +1685,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::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, RendererStorageRD::SHADER_TYPE_SKY);
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1884,7 +1909,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool
update_dirty_skys();
- return sky->bake_panorama(storage, p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
+ return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
}
RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 13d24e2508..83a8fe6e77 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -63,7 +63,7 @@ public:
};
private:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
@@ -105,37 +105,38 @@ private:
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
- struct SkyShaderData : public RendererStorageRD::ShaderData {
- bool valid;
+ struct SkyShaderData : public RendererRD::ShaderData {
+ bool valid = false;
RID version;
PipelineCacheRD pipelines[SKY_VERSION_MAX];
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String path;
String code;
- Map<StringName, Map<int, RID>> default_texture_params;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
- bool uses_time;
- bool uses_position;
- bool uses_half_res;
- bool uses_quarter_res;
- bool uses_light;
+ bool uses_time = false;
+ bool uses_position = false;
+ bool uses_half_res = false;
+ bool uses_quarter_res = false;
+ bool uses_light = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- SkyShaderData();
+
+ SkyShaderData() {}
virtual ~SkyShaderData();
};
@@ -162,8 +163,8 @@ public:
UBO ubo;
- SkyDirectionalLightData *directional_lights;
- SkyDirectionalLightData *last_frame_directional_lights;
+ SkyDirectionalLightData *directional_lights = nullptr;
+ SkyDirectionalLightData *last_frame_directional_lights = nullptr;
uint32_t max_directional_lights;
uint32_t last_frame_directional_light_count;
RID directional_light_buffer;
@@ -227,14 +228,14 @@ public:
RID default_shader_rd;
} sky_shader;
- struct SkyMaterialData : public RendererStorageRD::MaterialData {
- SkyShaderData *shader_data;
+ struct SkyMaterialData : public RendererRD::MaterialData {
+ SkyShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~SkyMaterialData();
};
@@ -262,7 +263,7 @@ public:
Sky *dirty_list = nullptr;
//State to track when radiance cubemap needs updating
- SkyMaterialData *prev_material;
+ SkyMaterialData *prev_material = nullptr;
Vector3 prev_position;
float prev_time;
@@ -272,7 +273,7 @@ public:
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
- Ref<Image> bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size);
+ Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size);
};
uint32_t sky_ggx_samples_quality;
@@ -281,11 +282,11 @@ public:
mutable RID_Owner<Sky, true> sky_owner;
int roughness_layers;
- RendererStorageRD::ShaderData *_create_sky_shader_func();
- static RendererStorageRD::ShaderData *_create_sky_shader_funcs();
+ RendererRD::ShaderData *_create_sky_shader_func();
+ static RendererRD::ShaderData *_create_sky_shader_funcs();
- RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
+ RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
RendererSceneSkyRD();
void init(RendererStorageRD *p_storage);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 1473a92a1a..d5166c6905 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -35,6107 +35,13 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
-bool RendererStorageRD::can_create_resources_async() const {
- return true;
-}
-
-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()) {
- case Image::FORMAT_L8: {
- r_format.format = RD::DATA_FORMAT_R8_UNORM;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break; //luminance
- case Image::FORMAT_LA8: {
- r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G;
- } break; //luminance-alpha
- case Image::FORMAT_R8: {
- r_format.format = RD::DATA_FORMAT_R8_UNORM;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_RG8: {
- r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_RGB8: {
- //this format is not mandatory for specification, check if supported first
- if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break;
- case Image::FORMAT_RGBA8: {
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
- case Image::FORMAT_RGBA4444: {
- r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
- case Image::FORMAT_RGB565: {
- r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
- case Image::FORMAT_RF: {
- r_format.format = RD::DATA_FORMAT_R32_SFLOAT;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break; //float
- case Image::FORMAT_RGF: {
- r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_RGBF: {
- //this format is not mandatory for specification, check if supported first
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- image->convert(Image::FORMAT_RGBAF);
- }
-
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_RGBAF: {
- r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
-
- } break;
- case Image::FORMAT_RH: {
- r_format.format = RD::DATA_FORMAT_R16_SFLOAT;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break; //half float
- case Image::FORMAT_RGH: {
- r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break;
- case Image::FORMAT_RGBH: {
- //this format is not mandatory for specification, check if supported first
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- image->convert(Image::FORMAT_RGBAH);
- }
-
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_RGBAH: {
- r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
-
- } break;
- case Image::FORMAT_RGBE9995: {
- r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
-#ifndef _MSC_VER
-#warning TODO need to make a function in Image to swap bits for this
-#endif
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY;
- } break;
- case Image::FORMAT_DXT1: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break; //s3tc bc1
- case Image::FORMAT_DXT3: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
-
- } break; //bc2
- case Image::FORMAT_DXT5: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break; //bc3
- case Image::FORMAT_RGTC_R: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8_UNORM;
- image->decompress();
- image->convert(Image::FORMAT_R8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break;
- case Image::FORMAT_RGTC_RG: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
- image->decompress();
- image->convert(Image::FORMAT_RG8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break;
- case Image::FORMAT_BPTC_RGBA: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
-
- } break; //btpc bc7
- case Image::FORMAT_BPTC_RGBF: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- image->decompress();
- image->convert(Image::FORMAT_RGBAH);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break; //float bc6h
- case Image::FORMAT_BPTC_RGBFU: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- image->decompress();
- image->convert(Image::FORMAT_RGBAH);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break; //unsigned float bc6hu
- case Image::FORMAT_ETC2_R11: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8_UNORM;
- image->decompress();
- image->convert(Image::FORMAT_R8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break; //etc2
- case Image::FORMAT_ETC2_R11S: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8_SNORM;
- image->decompress();
- image->convert(Image::FORMAT_R8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break; //signed: {} break; NOT srgb.
- case Image::FORMAT_ETC2_RG11: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
- image->decompress();
- image->convert(Image::FORMAT_RG8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_ETC2_RG11S: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8_SNORM;
- image->decompress();
- image->convert(Image::FORMAT_RG8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_ETC:
- case Image::FORMAT_ETC2_RGB8: {
- //ETC2 is backwards compatible with ETC1, and all modern platforms support it
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break;
- case Image::FORMAT_ETC2_RGBA8: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
- case Image::FORMAT_ETC2_RGB8A1: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
- case Image::FORMAT_ETC2_RA_AS_RG: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_DXT5_RA_AS_RG: {
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
- r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
-
- default: {
- }
- }
-
- return image;
-}
-
-RID RendererStorageRD::texture_allocate() {
- return texture_owner.allocate_rid();
-}
-
-void RendererStorageRD::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
- ERR_FAIL_COND(p_image.is_null());
- ERR_FAIL_COND(p_image->is_empty());
-
- TextureToRDFormat ret_format;
- Ref<Image> image = _validate_texture_format(p_image, ret_format);
-
- Texture texture;
-
- texture.type = Texture::TYPE_2D;
-
- texture.width = p_image->get_width();
- texture.height = p_image->get_height();
- texture.layers = 1;
- texture.mipmaps = p_image->get_mipmap_count() + 1;
- texture.depth = 1;
- texture.format = p_image->get_format();
- texture.validated_format = image->get_format();
-
- texture.rd_type = RD::TEXTURE_TYPE_2D;
- texture.rd_format = ret_format.format;
- texture.rd_format_srgb = ret_format.format_srgb;
-
- RD::TextureFormat rd_format;
- RD::TextureView rd_view;
- { //attempt register
- rd_format.format = texture.rd_format;
- rd_format.width = texture.width;
- rd_format.height = texture.height;
- rd_format.depth = 1;
- rd_format.array_layers = 1;
- rd_format.mipmaps = texture.mipmaps;
- 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) {
- rd_format.shareable_formats.push_back(texture.rd_format);
- rd_format.shareable_formats.push_back(texture.rd_format_srgb);
- }
- }
- {
- rd_view.swizzle_r = ret_format.swizzle_r;
- rd_view.swizzle_g = ret_format.swizzle_g;
- rd_view.swizzle_b = ret_format.swizzle_b;
- rd_view.swizzle_a = ret_format.swizzle_a;
- }
- Vector<uint8_t> data = image->get_data(); //use image data
- Vector<Vector<uint8_t>> data_slices;
- data_slices.push_back(data);
- texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
- ERR_FAIL_COND(texture.rd_texture.is_null());
- if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
- rd_view.format_override = texture.rd_format_srgb;
- texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
- if (texture.rd_texture_srgb.is_null()) {
- RD::get_singleton()->free(texture.rd_texture);
- ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
- }
- }
-
- //used for 2D, overridable
- texture.width_2d = texture.width;
- texture.height_2d = texture.height;
- texture.is_render_target = false;
- texture.rd_view = rd_view;
- texture.is_proxy = false;
-
- texture_owner.initialize_rid(p_texture, texture);
-}
-
-void RendererStorageRD::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
- ERR_FAIL_COND(p_layers.size() == 0);
-
- ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
- ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0));
-
- TextureToRDFormat ret_format;
- Vector<Ref<Image>> images;
- {
- int valid_width = 0;
- int valid_height = 0;
- bool valid_mipmaps = false;
- Image::Format valid_format = Image::FORMAT_MAX;
-
- for (int i = 0; i < p_layers.size(); i++) {
- ERR_FAIL_COND(p_layers[i]->is_empty());
-
- if (i == 0) {
- valid_width = p_layers[i]->get_width();
- valid_height = p_layers[i]->get_height();
- valid_format = p_layers[i]->get_format();
- valid_mipmaps = p_layers[i]->has_mipmaps();
- } else {
- ERR_FAIL_COND(p_layers[i]->get_width() != valid_width);
- ERR_FAIL_COND(p_layers[i]->get_height() != valid_height);
- ERR_FAIL_COND(p_layers[i]->get_format() != valid_format);
- ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps);
- }
-
- images.push_back(_validate_texture_format(p_layers[i], ret_format));
- }
- }
-
- Texture texture;
-
- texture.type = Texture::TYPE_LAYERED;
- texture.layered_type = p_layered_type;
-
- texture.width = p_layers[0]->get_width();
- texture.height = p_layers[0]->get_height();
- texture.layers = p_layers.size();
- texture.mipmaps = p_layers[0]->get_mipmap_count() + 1;
- texture.depth = 1;
- texture.format = p_layers[0]->get_format();
- texture.validated_format = images[0]->get_format();
-
- switch (p_layered_type) {
- case RS::TEXTURE_LAYERED_2D_ARRAY: {
- texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY;
- } break;
- case RS::TEXTURE_LAYERED_CUBEMAP: {
- texture.rd_type = RD::TEXTURE_TYPE_CUBE;
- } break;
- case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: {
- texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
- } break;
- }
-
- texture.rd_format = ret_format.format;
- texture.rd_format_srgb = ret_format.format_srgb;
-
- RD::TextureFormat rd_format;
- RD::TextureView rd_view;
- { //attempt register
- rd_format.format = texture.rd_format;
- rd_format.width = texture.width;
- rd_format.height = texture.height;
- rd_format.depth = 1;
- rd_format.array_layers = texture.layers;
- rd_format.mipmaps = texture.mipmaps;
- 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) {
- rd_format.shareable_formats.push_back(texture.rd_format);
- rd_format.shareable_formats.push_back(texture.rd_format_srgb);
- }
- }
- {
- rd_view.swizzle_r = ret_format.swizzle_r;
- rd_view.swizzle_g = ret_format.swizzle_g;
- rd_view.swizzle_b = ret_format.swizzle_b;
- rd_view.swizzle_a = ret_format.swizzle_a;
- }
- Vector<Vector<uint8_t>> data_slices;
- for (int i = 0; i < images.size(); i++) {
- Vector<uint8_t> data = images[i]->get_data(); //use image data
- data_slices.push_back(data);
- }
- texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
- ERR_FAIL_COND(texture.rd_texture.is_null());
- if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
- rd_view.format_override = texture.rd_format_srgb;
- texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
- if (texture.rd_texture_srgb.is_null()) {
- RD::get_singleton()->free(texture.rd_texture);
- ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
- }
- }
-
- //used for 2D, overridable
- texture.width_2d = texture.width;
- texture.height_2d = texture.height;
- texture.is_render_target = false;
- texture.rd_view = rd_view;
- texture.is_proxy = false;
-
- texture_owner.initialize_rid(p_texture, texture);
-}
-
-void RendererStorageRD::texture_3d_initialize(RID p_texture, 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(p_data.size() == 0);
- 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) {
- ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
- }
-
- TextureToRDFormat ret_format;
- Image::Format validated_format = Image::FORMAT_MAX;
- Vector<uint8_t> all_data;
- uint32_t mipmap_count = 0;
- Vector<Texture::BufferSlice3D> slices;
- {
- Vector<Ref<Image>> images;
- uint32_t all_data_size = 0;
- images.resize(p_data.size());
- for (int i = 0; i < p_data.size(); i++) {
- TextureToRDFormat f;
- images.write[i] = _validate_texture_format(p_data[i], f);
- if (i == 0) {
- ret_format = f;
- validated_format = images[0]->get_format();
- }
-
- all_data_size += images[i]->get_data().size();
- }
-
- all_data.resize(all_data_size); //consolidate all data here
- uint32_t offset = 0;
- Size2i prev_size;
- for (int i = 0; i < p_data.size(); i++) {
- uint32_t s = images[i]->get_data().size();
-
- memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s);
- {
- Texture::BufferSlice3D slice;
- slice.size.width = images[i]->get_width();
- slice.size.height = images[i]->get_height();
- slice.offset = offset;
- slice.buffer_size = s;
- slices.push_back(slice);
- }
- offset += s;
-
- Size2i img_size(images[i]->get_width(), images[i]->get_height());
- if (img_size != prev_size) {
- mipmap_count++;
- }
- prev_size = img_size;
- }
- }
-
- Texture texture;
-
- texture.type = Texture::TYPE_3D;
- texture.width = p_width;
- texture.height = p_height;
- texture.depth = p_depth;
- texture.mipmaps = mipmap_count;
- texture.format = p_data[0]->get_format();
- texture.validated_format = validated_format;
-
- texture.buffer_size_3d = all_data.size();
- texture.buffer_slices_3d = slices;
-
- texture.rd_type = RD::TEXTURE_TYPE_3D;
- texture.rd_format = ret_format.format;
- texture.rd_format_srgb = ret_format.format_srgb;
-
- RD::TextureFormat rd_format;
- RD::TextureView rd_view;
- { //attempt register
- rd_format.format = texture.rd_format;
- rd_format.width = texture.width;
- rd_format.height = texture.height;
- rd_format.depth = texture.depth;
- rd_format.array_layers = 1;
- rd_format.mipmaps = texture.mipmaps;
- 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) {
- rd_format.shareable_formats.push_back(texture.rd_format);
- rd_format.shareable_formats.push_back(texture.rd_format_srgb);
- }
- }
- {
- rd_view.swizzle_r = ret_format.swizzle_r;
- rd_view.swizzle_g = ret_format.swizzle_g;
- rd_view.swizzle_b = ret_format.swizzle_b;
- rd_view.swizzle_a = ret_format.swizzle_a;
- }
- Vector<Vector<uint8_t>> data_slices;
- data_slices.push_back(all_data); //one slice
-
- texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
- ERR_FAIL_COND(texture.rd_texture.is_null());
- if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
- rd_view.format_override = texture.rd_format_srgb;
- texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
- if (texture.rd_texture_srgb.is_null()) {
- RD::get_singleton()->free(texture.rd_texture);
- ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
- }
- }
-
- //used for 2D, overridable
- texture.width_2d = texture.width;
- texture.height_2d = texture.height;
- texture.is_render_target = false;
- texture.rd_view = rd_view;
- texture.is_proxy = false;
-
- texture_owner.initialize_rid(p_texture, texture);
-}
-
-void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) {
- Texture *tex = texture_owner.get_or_null(p_base);
- ERR_FAIL_COND(!tex);
- Texture proxy_tex = *tex;
-
- proxy_tex.rd_view.format_override = tex->rd_format;
- proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture);
- if (proxy_tex.rd_texture_srgb.is_valid()) {
- proxy_tex.rd_view.format_override = tex->rd_format_srgb;
- proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture);
- }
- proxy_tex.proxy_to = p_base;
- proxy_tex.is_render_target = false;
- proxy_tex.is_proxy = true;
- proxy_tex.proxies.clear();
-
- texture_owner.initialize_rid(p_texture, proxy_tex);
-
- tex->proxies.push_back(p_texture);
-}
-
-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.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->is_render_target);
- ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height);
- ERR_FAIL_COND(p_image->get_format() != tex->format);
-
- if (tex->type == Texture::TYPE_LAYERED) {
- ERR_FAIL_INDEX(p_layer, tex->layers);
- }
-
-#ifdef TOOLS_ENABLED
- tex->image_cache_2d.unref();
-#endif
- TextureToRDFormat f;
- Ref<Image> validated = _validate_texture_format(p_image, f);
-
- RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data());
-}
-
-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 RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->type != Texture::TYPE_3D);
- Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data);
- if (verr != Image::VALIDATE_3D_OK) {
- ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
- }
-
- Vector<uint8_t> all_data;
- {
- Vector<Ref<Image>> images;
- uint32_t all_data_size = 0;
- images.resize(p_data.size());
- for (int i = 0; i < p_data.size(); i++) {
- Ref<Image> image = p_data[i];
- if (image->get_format() != tex->validated_format) {
- image = image->duplicate();
- image->convert(tex->validated_format);
- }
- all_data_size += images[i]->get_data().size();
- images.push_back(image);
- }
-
- all_data.resize(all_data_size); //consolidate all data here
- uint32_t offset = 0;
-
- for (int i = 0; i < p_data.size(); i++) {
- uint32_t s = images[i]->get_data().size();
- memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s);
- offset += s;
- }
- }
-
- RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data);
-}
-
-void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(!tex->is_proxy);
- Texture *proxy_to = texture_owner.get_or_null(p_proxy_to);
- ERR_FAIL_COND(!proxy_to);
- ERR_FAIL_COND(proxy_to->is_proxy);
-
- if (tex->proxy_to.is_valid()) {
- //unlink proxy
- if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
- RD::get_singleton()->free(tex->rd_texture);
- tex->rd_texture = RID();
- }
- if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
- RD::get_singleton()->free(tex->rd_texture_srgb);
- tex->rd_texture_srgb = RID();
- }
- Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to);
- ERR_FAIL_COND(!prev_tex);
- prev_tex->proxies.erase(p_texture);
- }
-
- *tex = *proxy_to;
-
- tex->proxy_to = p_proxy_to;
- tex->is_render_target = false;
- tex->is_proxy = true;
- tex->proxies.clear();
- proxy_to->proxies.push_back(p_texture);
-
- tex->rd_view.format_override = tex->rd_format;
- tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
- if (tex->rd_texture_srgb.is_valid()) {
- tex->rd_view.format_override = tex->rd_format_srgb;
- tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
- }
-}
-
-//these two APIs can be used together or in combination with the others.
-void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) {
- //this could be better optimized to reuse an existing image , done this way
- //for now to get it working
- Ref<Image> image;
- image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
- image->fill(Color(1, 0, 1, 1));
-
- texture_2d_initialize(p_texture, image);
-}
-
-void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture, 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;
- image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
- image->fill(Color(1, 0, 1, 1));
-
- Vector<Ref<Image>> images;
- if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
- images.push_back(image);
- } else {
- //cube
- for (int i = 0; i < 6; i++) {
- images.push_back(image);
- }
- }
-
- texture_2d_layered_initialize(p_texture, images, p_layered_type);
-}
-
-void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) {
- //this could be better optimized to reuse an existing image , done this way
- //for now to get it working
- Ref<Image> image;
- image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
- image->fill(Color(1, 0, 1, 1));
-
- Vector<Ref<Image>> images;
- //cube
- for (int i = 0; i < 4; i++) {
- images.push_back(image);
- }
-
- texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
-}
-
-Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!tex, Ref<Image>());
-
-#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
- return tex->image_cache_2d;
- }
-#endif
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
- ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
- Ref<Image> image;
- image.instantiate();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
- if (tex->format != tex->validated_format) {
- image->convert(tex->format);
- }
-
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
- tex->image_cache_2d = image;
- }
-#endif
-
- return image;
-}
-
-Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!tex, Ref<Image>());
-
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer);
- ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
- Ref<Image> image;
- image.instantiate();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
- if (tex->format != tex->validated_format) {
- image->convert(tex->format);
- }
-
- return image;
-}
-
-Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>());
- ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>());
-
- Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
-
- ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>());
-
- Vector<Ref<Image>> ret;
-
- for (int i = 0; i < tex->buffer_slices_3d.size(); i++) {
- const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i];
- ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>());
- ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>());
- Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size);
-
- Ref<Image> img;
- img.instantiate();
- img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
- ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
- if (tex->format != tex->validated_format) {
- img->convert(tex->format);
- }
-
- ret.push_back(img);
- }
-
- return ret;
-}
-
-void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy
- Texture *by_tex = texture_owner.get_or_null(p_by_texture);
- ERR_FAIL_COND(!by_tex);
- ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy
-
- if (tex == by_tex) {
- return;
- }
-
- if (tex->rd_texture_srgb.is_valid()) {
- RD::get_singleton()->free(tex->rd_texture_srgb);
- }
- RD::get_singleton()->free(tex->rd_texture);
-
- if (tex->canvas_texture) {
- memdelete(tex->canvas_texture);
- tex->canvas_texture = nullptr;
- }
-
- Vector<RID> proxies_to_update = tex->proxies;
- Vector<RID> proxies_to_redirect = by_tex->proxies;
-
- *tex = *by_tex;
-
- tex->proxies = proxies_to_update; //restore proxies, so they can be updated
-
- if (tex->canvas_texture) {
- tex->canvas_texture->diffuse = p_texture; //update
- }
-
- for (int i = 0; i < proxies_to_update.size(); i++) {
- texture_proxy_update(proxies_to_update[i], p_texture);
- }
- for (int i = 0; i < proxies_to_redirect.size(); i++) {
- texture_proxy_update(proxies_to_redirect[i], p_texture);
- }
- //delete last, so proxies can be updated
- texture_owner.free(p_by_texture);
-
- if (decal_atlas.textures.has(p_texture)) {
- //belongs to decal atlas..
-
- decal_atlas.dirty = true; //mark it dirty since it was most likely modified
- }
-}
-
-void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
- tex->width_2d = p_width;
- tex->height_2d = p_height;
-}
-
-void RendererStorageRD::texture_set_path(RID p_texture, const String &p_path) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- tex->path = p_path;
-}
-
-String RendererStorageRD::texture_get_path(RID p_texture) const {
- return String();
-}
-
-void RendererStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- tex->detect_3d_callback_ud = p_userdata;
- tex->detect_3d_callback = p_callback;
-}
-
-void RendererStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- tex->detect_normal_callback_ud = p_userdata;
- tex->detect_normal_callback = p_callback;
-}
-
-void RendererStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
- tex->detect_roughness_callback_ud = p_userdata;
- tex->detect_roughness_callback = p_callback;
-}
-
-void RendererStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) {
-}
-
-void RendererStorageRD::texture_set_proxy(RID p_proxy, RID p_base) {
-}
-
-void RendererStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
-}
-
-Size2 RendererStorageRD::texture_size_with_proxy(RID p_proxy) {
- return texture_2d_get_size(p_proxy);
-}
-
-/* CANVAS TEXTURE */
-
-void RendererStorageRD::CanvasTexture::clear_sets() {
- if (cleared_cache) {
- return;
- }
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
- RD::get_singleton()->free(uniform_sets[i][j]);
- uniform_sets[i][j] = RID();
- }
- }
- }
- cleared_cache = true;
-}
-
-RendererStorageRD::CanvasTexture::~CanvasTexture() {
- clear_sets();
-}
-
-void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- RD::SamplerState sampler_state;
- switch (i) {
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
-
- } break;
- default: {
- }
- }
- switch (j) {
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- } break;
- default: {
- }
- }
-
- if (custom_rd_samplers[i][j].is_valid()) {
- RD::get_singleton()->free(custom_rd_samplers[i][j]);
- }
-
- custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
- }
- }
-}
-
-RID RendererStorageRD::canvas_texture_allocate() {
- return canvas_texture_owner.allocate_rid();
-}
-void RendererStorageRD::canvas_texture_initialize(RID p_rid) {
- canvas_texture_owner.initialize_rid(p_rid);
-}
-
-void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- switch (p_channel) {
- case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
- ct->diffuse = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
- ct->normal_map = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
- ct->specular = p_texture;
- } break;
- }
-
- ct->clear_sets();
-}
-
-void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->specular_color.r = p_specular_color.r;
- ct->specular_color.g = p_specular_color.g;
- ct->specular_color.b = p_specular_color.b;
- ct->specular_color.a = p_shininess;
- ct->clear_sets();
-}
-
-void RendererStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->texture_filter = p_filter;
- ct->clear_sets();
-}
-
-void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->texture_repeat = p_repeat;
- ct->clear_sets();
-}
-
-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.get_or_null(p_texture);
-
- if (t) {
- //regular texture
- if (!t->canvas_texture) {
- t->canvas_texture = memnew(CanvasTexture);
- t->canvas_texture->diffuse = p_texture;
- }
-
- ct = t->canvas_texture;
- } else {
- ct = canvas_texture_owner.get_or_null(p_texture);
- }
-
- if (!ct) {
- return false; //invalid texture RID
- }
-
- RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
- ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
-
- RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
- ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
-
- RID uniform_set = ct->uniform_sets[filter][repeat];
- if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //create and update
- Vector<RD::Uniform> uniforms;
- { //diffuse
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
-
- t = texture_owner.get_or_null(ct->diffuse);
- if (!t) {
- u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
- ct->size_cache = Size2i(1, 1);
- } else {
- u.ids.push_back(t->rd_texture);
- ct->size_cache = Size2i(t->width_2d, t->height_2d);
- }
- uniforms.push_back(u);
- }
- { //normal
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
-
- t = texture_owner.get_or_null(ct->normal_map);
- if (!t) {
- u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
- ct->use_normal_cache = false;
- } else {
- u.ids.push_back(t->rd_texture);
- ct->use_normal_cache = true;
- }
- uniforms.push_back(u);
- }
- { //specular
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
-
- t = texture_owner.get_or_null(ct->specular);
- if (!t) {
- u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
- ct->use_specular_cache = false;
- } else {
- u.ids.push_back(t->rd_texture);
- ct->use_specular_cache = true;
- }
- uniforms.push_back(u);
- }
- { //sampler
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 3;
- u.ids.push_back(sampler_rd_get_default(filter, repeat));
- uniforms.push_back(u);
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
- ct->uniform_sets[filter][repeat] = uniform_set;
- ct->cleared_cache = false;
- }
-
- r_uniform_set = uniform_set;
- r_size = ct->size_cache;
- r_specular_shininess = ct->specular_color;
- r_use_normal = ct->use_normal_cache;
- r_use_specular = ct->use_specular_cache;
-
- return true;
-}
-
-/* SHADER API */
-
-RID RendererStorageRD::shader_allocate() {
- return shader_owner.allocate_rid();
-}
-void RendererStorageRD::shader_initialize(RID p_rid) {
- Shader shader;
- shader.data = nullptr;
- shader.type = SHADER_TYPE_MAX;
-
- shader_owner.initialize_rid(p_rid, shader);
-}
-
-void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
-
- shader->code = p_code;
- String mode_string = ShaderLanguage::get_shader_type(p_code);
-
- ShaderType new_type;
- if (mode_string == "canvas_item") {
- new_type = SHADER_TYPE_2D;
- } else if (mode_string == "particles") {
- new_type = SHADER_TYPE_PARTICLES;
- } else if (mode_string == "spatial") {
- new_type = SHADER_TYPE_3D;
- } else if (mode_string == "sky") {
- new_type = SHADER_TYPE_SKY;
- } else if (mode_string == "fog") {
- new_type = SHADER_TYPE_FOG;
- } else {
- new_type = SHADER_TYPE_MAX;
- }
-
- if (new_type != shader->type) {
- if (shader->data) {
- memdelete(shader->data);
- shader->data = nullptr;
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- material->shader_type = new_type;
- if (material->data) {
- memdelete(material->data);
- material->data = nullptr;
- }
- }
-
- shader->type = new_type;
-
- if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
- shader->data = shader_data_request_func[new_type]();
- } else {
- shader->type = SHADER_TYPE_MAX; //invalid
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- if (shader->data) {
- material->data = material_data_request_func[new_type](shader->data);
- material->data->self = material->self;
- material->data->set_next_pass(material->next_pass);
- material->data->set_render_priority(material->priority);
- }
- material->shader_type = new_type;
- }
-
- if (shader->data) {
- for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
- for (const KeyValue<int, RID> &E2 : E.value) {
- shader->data->set_default_texture_param(E.key, E2.value, E2.key);
- }
- }
- }
- }
-
- if (shader->data) {
- shader->data->set_code(p_code);
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- _material_queue_update(material, true, true);
- }
-}
-
-String RendererStorageRD::shader_get_code(RID p_shader) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, String());
- return shader->code;
-}
-
-void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
- if (shader->data) {
- return shader->data->get_param_list(p_param_list);
- }
-}
-
-void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
-
- if (p_texture.is_valid() && texture_owner.owns(p_texture)) {
- if (!shader->default_texture_parameter.has(p_name)) {
- shader->default_texture_parameter[p_name] = Map<int, RID>();
- }
- shader->default_texture_parameter[p_name][p_index] = p_texture;
- } else {
- if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
- shader->default_texture_parameter[p_name].erase(p_index);
-
- if (shader->default_texture_parameter[p_name].is_empty()) {
- shader->default_texture_parameter.erase(p_name);
- }
- }
- }
- if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture, p_index);
- }
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- _material_queue_update(material, false, true);
- }
-}
-
-RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, RID());
- if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
- return shader->default_texture_parameter[p_name][p_index];
- }
-
- return RID();
-}
-
-Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, Variant());
- if (shader->data) {
- return shader->data->get_default_parameter(p_param);
- }
- return Variant();
-}
-
-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.get_or_null(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 RendererStorageRD::material_allocate() {
- return material_owner.allocate_rid();
-}
-void RendererStorageRD::material_initialize(RID p_rid) {
- material_owner.initialize_rid(p_rid);
- Material *material = material_owner.get_or_null(p_rid);
- material->self = p_rid;
-}
-
-void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
- material->uniform_dirty = material->uniform_dirty || p_uniform;
- material->texture_dirty = material->texture_dirty || p_texture;
-
- if (material->update_element.in_list()) {
- return;
- }
-
- material_update_list.add(&material->update_element);
-}
-
-void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (material->data) {
- memdelete(material->data);
- material->data = nullptr;
- }
-
- if (material->shader) {
- material->shader->owners.erase(material);
- material->shader = nullptr;
- material->shader_type = SHADER_TYPE_MAX;
- }
-
- if (p_shader.is_null()) {
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- material->shader_id = 0;
- return;
- }
-
- Shader *shader = shader_owner.get_or_null(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) {
- return;
- }
-
- ERR_FAIL_COND(shader->data == nullptr);
-
- material->data = material_data_request_func[shader->type](shader->data);
- material->data->self = p_material;
- material->data->set_next_pass(material->next_pass);
- material->data->set_render_priority(material->priority);
- //updating happens later
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- _material_queue_update(material, true, true);
-}
-
-void RendererStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (p_value.get_type() == Variant::NIL) {
- material->params.erase(p_param);
- } else {
- ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
- material->params[p_param] = p_value;
- }
-
- if (material->shader && material->shader->data) { //shader is valid
- bool is_texture = material->shader->data->is_param_texture(p_param);
- _material_queue_update(material, !is_texture, is_texture);
- } else {
- _material_queue_update(material, true, true);
- }
-}
-
-Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, Variant());
- if (material->params.has(p_param)) {
- return material->params[p_param];
- } else {
- return Variant();
- }
-}
-
-void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (material->next_pass == p_next_material) {
- return;
- }
-
- material->next_pass = p_next_material;
- if (material->data) {
- material->data->set_next_pass(p_next_material);
- }
-
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
-}
-
-void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- material->priority = priority;
- if (material->data) {
- material->data->set_render_priority(priority);
- }
-}
-
-bool RendererStorageRD::material_is_animated(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->shader && material->shader->data) {
- if (material->shader->data->is_animated()) {
- return true;
- } else if (material->next_pass.is_valid()) {
- return material_is_animated(material->next_pass);
- }
- }
- return false; //by default nothing is animated
-}
-
-bool RendererStorageRD::material_casts_shadows(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, true);
- if (material->shader && material->shader->data) {
- if (material->shader->data->casts_shadows()) {
- return true;
- } else if (material->next_pass.is_valid()) {
- return material_casts_shadows(material->next_pass);
- }
- }
- return true; //by default everything casts shadows
-}
-
-void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- if (material->shader && material->shader->data) {
- material->shader->data->get_instance_param_list(r_parameters);
-
- if (material->next_pass.is_valid()) {
- material_get_instance_shader_parameters(material->next_pass, r_parameters);
- }
- }
-}
-
-void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- p_instance->update_dependency(&material->dependency);
- if (material->next_pass.is_valid()) {
- material_update_dependency(material->next_pass, p_instance);
- }
-}
-
-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;
-}
-
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = (r[i] != 0) ? 1 : 0;
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- bool v = value;
- gui[0] = v ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 2 * p_array_size;
-
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i] ? 1 : 0;
- gui[j + 1] = r[i + 1] ? 1 : 0;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v & 1 ? 1 : 0;
- gui[1] = v & 2 ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 3 * p_array_size;
-
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i] ? 1 : 0;
- gui[j + 1] = r[i + 1] ? 1 : 0;
- gui[j + 2] = r[i + 2] ? 1 : 0;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 4 * p_array_size;
-
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i] ? 1 : 0;
- gui[i + 1] = r[i + 1] ? 1 : 0;
- gui[i + 2] = r[i + 2] ? 1 : 0;
- gui[i + 3] = r[i + 3] ? 1 : 0;
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } else {
- int v = value;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- gui[3] = (v & 8) ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_INT: {
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size > 0) {
- Vector<int> iv = value;
- int s = iv.size();
- const int *r = iv.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } break;
- case ShaderLanguage::TYPE_UINT: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- Vector<int> iv = value;
- int s = iv.size();
- const int *r = iv.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- float v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedVector2Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i].x;
- gui[j + 1] = a[i].y;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- Vector2 v = value;
- gui[0] = v.x;
- gui[1] = v.y;
- }
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedVector3Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i].x;
- gui[j + 1] = a[i].y;
- gui[j + 2] = a[i].z;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } else {
- Vector3 v = value;
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- }
- } break;
- case ShaderLanguage::TYPE_VEC4: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
- const PackedColorArray &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- Color color = a[i];
- if (p_linear_color) {
- color = color.to_linear();
- }
- gui[j] = color.r;
- gui[j + 1] = color.g;
- gui[j + 2] = color.b;
- gui[j + 3] = color.a;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- gui[j + 3] = 0;
- }
- }
- } else {
- const PackedFloat32Array &a = value;
- int s = a.size();
- int count = 4 * p_array_size;
-
- for (int i = 0; i < count; i += 4) {
- if (i + 3 < s) {
- gui[i] = a[i];
- gui[i + 1] = a[i + 1];
- gui[i + 2] = a[i + 2];
- gui[i + 3] = a[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- }
- } else {
- if (value.get_type() == Variant::COLOR) {
- Color v = value;
-
- if (p_linear_color) {
- v = v.to_linear();
- }
-
- gui[0] = v.r;
- gui[1] = v.g;
- gui[2] = v.b;
- gui[3] = v.a;
- } else if (value.get_type() == Variant::RECT2) {
- Rect2 v = value;
-
- gui[0] = v.position.x;
- gui[1] = v.position.y;
- gui[2] = v.size.x;
- gui[3] = v.size.y;
- } else if (value.get_type() == Variant::QUATERNION) {
- Quaternion v = value;
-
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- gui[3] = v.w;
- } else {
- Plane v = value;
-
- gui[0] = v.normal.x;
- gui[1] = v.normal.y;
- gui[2] = v.normal.z;
- gui[3] = v.d;
- }
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
- if (i + 3 < s) {
- gui[j] = a[i];
- gui[j + 1] = a[i + 1];
-
- gui[j + 4] = a[i + 2];
- gui[j + 5] = a[i + 3];
- } else {
- gui[j] = 1;
- gui[j + 1] = 0;
-
- gui[j + 4] = 0;
- gui[j + 5] = 1;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- gui[j + 6] = 0; // ignored
- gui[j + 7] = 0; // ignored
- }
- } else {
- Transform2D v = value;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[0][1];
- gui[2] = 0; // ignored
- gui[3] = 0; // ignored
-
- gui[4] = v.elements[1][0];
- gui[5] = v.elements[1][1];
- gui[6] = 0; // ignored
- gui[7] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
- if (i + 8 < s) {
- gui[j] = a[i];
- gui[j + 1] = a[i + 1];
- gui[j + 2] = a[i + 2];
-
- gui[j + 4] = a[i + 3];
- gui[j + 5] = a[i + 4];
- gui[j + 6] = a[i + 5];
-
- gui[j + 8] = a[i + 6];
- gui[j + 9] = a[i + 7];
- gui[j + 10] = a[i + 8];
- } else {
- gui[j] = 1;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
-
- gui[j + 4] = 0;
- gui[j + 5] = 1;
- gui[j + 6] = 0;
-
- gui[j + 8] = 0;
- gui[j + 9] = 0;
- gui[j + 10] = 1;
- }
- gui[j + 3] = 0; // ignored
- gui[j + 7] = 0; // ignored
- gui[j + 11] = 0; // ignored
- }
- } else {
- Basis v = value;
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[1][0];
- gui[2] = v.elements[2][0];
- gui[3] = 0; // ignored
-
- gui[4] = v.elements[0][1];
- gui[5] = v.elements[1][1];
- gui[6] = v.elements[2][1];
- gui[7] = 0; // ignored
-
- gui[8] = v.elements[0][2];
- gui[9] = v.elements[1][2];
- gui[10] = v.elements[2][2];
- gui[11] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0; i < p_array_size * 16; i += 16) {
- if (i + 15 < s) {
- gui[i] = a[i];
- gui[i + 1] = a[i + 1];
- gui[i + 2] = a[i + 2];
- gui[i + 3] = a[i + 3];
-
- gui[i + 4] = a[i + 4];
- gui[i + 5] = a[i + 5];
- gui[i + 6] = a[i + 6];
- gui[i + 7] = a[i + 7];
-
- gui[i + 8] = a[i + 8];
- gui[i + 9] = a[i + 9];
- gui[i + 10] = a[i + 10];
- gui[i + 11] = a[i + 11];
-
- gui[i + 12] = a[i + 12];
- gui[i + 13] = a[i + 13];
- gui[i + 14] = a[i + 14];
- gui[i + 15] = a[i + 15];
- } else {
- gui[i] = 1;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
-
- gui[i + 4] = 0;
- gui[i + 5] = 1;
- gui[i + 6] = 0;
- gui[i + 7] = 0;
-
- gui[i + 8] = 0;
- gui[i + 9] = 0;
- gui[i + 10] = 1;
- gui[i + 11] = 0;
-
- gui[i + 12] = 0;
- gui[i + 13] = 0;
- gui[i + 14] = 0;
- gui[i + 15] = 1;
- }
- }
- } else {
- Transform3D v = value;
- gui[0] = v.basis.elements[0][0];
- gui[1] = v.basis.elements[1][0];
- gui[2] = v.basis.elements[2][0];
- gui[3] = 0;
-
- gui[4] = v.basis.elements[0][1];
- gui[5] = v.basis.elements[1][1];
- gui[6] = v.basis.elements[2][1];
- gui[7] = 0;
-
- gui[8] = v.basis.elements[0][2];
- gui[9] = v.basis.elements[1][2];
- gui[10] = v.basis.elements[2][2];
- gui[11] = 0;
-
- gui[12] = v.origin.x;
- gui[13] = v.origin.y;
- gui[14] = v.origin.z;
- gui[15] = 1;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
- uint32_t *gui = (uint32_t *)data;
- *gui = value[0].boolean ? 1 : 0;
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
- gui[2] = value[2].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
- gui[2] = value[2].boolean ? 1 : 0;
- gui[3] = value[3].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_INT: {
- int32_t *gui = (int32_t *)data;
- gui[0] = value[0].sint;
-
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UINT: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].uint;
-
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].uint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float *gui = (float *)data;
- gui[0] = value[0].real;
-
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC4: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].real;
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- float *gui = (float *)data;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = 0;
- gui[3] = 0;
- gui[4] = value[2].real;
- gui[5] = value[3].real;
- gui[6] = 0;
- gui[7] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- float *gui = (float *)data;
-
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = value[2].real;
- gui[3] = 0;
- gui[4] = value[3].real;
- gui[5] = value[4].real;
- gui[6] = value[5].real;
- gui[7] = 0;
- gui[8] = value[6].real;
- gui[9] = value[7].real;
- gui[10] = value[8].real;
- gui[11] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 16; i++) {
- gui[i] = value[i].real;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
-
- switch (type) {
- case ShaderLanguage::TYPE_BOOL:
- case ShaderLanguage::TYPE_INT:
- case ShaderLanguage::TYPE_UINT:
- case ShaderLanguage::TYPE_FLOAT: {
- memset(data, 0, 4 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_BVEC2:
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_UVEC2:
- case ShaderLanguage::TYPE_VEC2: {
- memset(data, 0, 8 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_BVEC3:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_VEC3:
- case ShaderLanguage::TYPE_BVEC4:
- case ShaderLanguage::TYPE_IVEC4:
- case ShaderLanguage::TYPE_UVEC4:
- case ShaderLanguage::TYPE_VEC4: {
- memset(data, 0, 16 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- memset(data, 0, 32 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- memset(data, 0, 48 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- memset(data, 0, 64 * p_array_size);
- } break;
-
- default: {
- }
- }
-}
-
-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 (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
- if (E.value.order < 0) {
- continue; // texture, does not go here
- }
-
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue; //instance uniforms don't appear in the buffer
- }
-
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
- //this is a global variable, get the index to it
- RendererStorageRD *rs = base_singleton;
-
- GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E.key);
- uint32_t index = 0;
- if (gv) {
- index = gv->buffer_index;
- } else {
- WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
- }
-
- uint32_t offset = p_uniform_offsets[E.value.order];
- uint32_t *intptr = (uint32_t *)&p_buffer[offset];
- *intptr = index;
- uses_global_buffer = true;
- continue;
- }
-
- //regular uniform
- uint32_t offset = p_uniform_offsets[E.value.order];
-#ifdef DEBUG_ENABLED
- uint32_t size = 0U;
- // The following code enforces a 16-byte alignment of uniform arrays.
- if (E.value.array_size > 0) {
- size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
- int m = (16 * E.value.array_size);
- if ((size % m) != 0U) {
- size += m - (size % m);
- }
- } else {
- size = ShaderLanguage::get_datatype_size(E.value.type);
- }
- ERR_CONTINUE(offset + size > p_buffer_size);
-#endif
- uint8_t *data = &p_buffer[offset];
- const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
-
- if (V) {
- //user provided
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
-
- } else if (E.value.default_value.size()) {
- //default value
- _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
- //value=E.value.default_value;
- } else {
- //zero because it was not provided
- if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- //colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
- } else {
- //else just zero it out
- _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
- }
- }
- }
-
- if (uses_global_buffer != (global_buffer_E != nullptr)) {
- RendererStorageRD *rs = base_singleton;
- if (uses_global_buffer) {
- global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self);
- } else {
- rs->global_variables.materials_using_buffer.erase(global_buffer_E);
- global_buffer_E = nullptr;
- }
- }
-}
-
-RendererStorageRD::MaterialData::~MaterialData() {
- if (global_buffer_E) {
- //unregister global buffers
- RendererStorageRD *rs = base_singleton;
- rs->global_variables.materials_using_buffer.erase(global_buffer_E);
- }
-
- if (global_texture_E) {
- //unregister global textures
- RendererStorageRD *rs = base_singleton;
-
- for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E.key);
- if (v) {
- v->texture_materials.erase(self);
- }
- }
- //unregister material from those using global textures
- rs->global_variables.materials_using_texture.erase(global_texture_E);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
-}
-
-void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::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_ROUGHNESS_R;
- Texture *normal_detect_texture = nullptr;
-#endif
-
- bool uses_global_textures = false;
- global_textures_pass++;
-
- for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
- const StringName &uniform_name = p_texture_uniforms[i].name;
- int uniform_array_size = p_texture_uniforms[i].array_size;
-
- Vector<RID> textures;
-
- if (p_texture_uniforms[i].global) {
- RendererStorageRD *rs = base_singleton;
-
- uses_global_textures = true;
-
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name);
- if (v) {
- if (v->buffer_index >= 0) {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
-
- } else {
- Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
- if (!E) {
- E = used_global_textures.insert(uniform_name, global_textures_pass);
- v->texture_materials.insert(self);
- } else {
- E->get() = global_textures_pass;
- }
-
- textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
- }
-
- } else {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
- }
- } else {
- const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
- if (V) {
- if (V->get().is_array()) {
- Array array = (Array)V->get();
- if (uniform_array_size > 0) {
- for (int j = 0; j < array.size(); j++) {
- textures.push_back(array[j]);
- }
- } else {
- if (array.size() > 0) {
- textures.push_back(array[0]);
- }
- }
- } else {
- textures.push_back(V->get());
- }
- }
-
- if (uniform_array_size > 0) {
- if (textures.size() < uniform_array_size) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- for (int j = textures.size(); j < uniform_array_size; j++) {
- if (W && W->get().has(j)) {
- textures.push_back(W->get()[j]);
- } else {
- textures.push_back(RID());
- }
- }
- }
- } else if (textures.is_empty()) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- if (W && W->get().has(0)) {
- textures.push_back(W->get()[0]);
- }
- }
- }
-
- RID rd_texture;
-
- if (textures.is_empty()) {
- //check default usage
- switch (p_texture_uniforms[i].type) {
- case ShaderLanguage::TYPE_ISAMPLER2D:
- case ShaderLanguage::TYPE_USAMPLER2D:
- case ShaderLanguage::TYPE_SAMPLER2D: {
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
- } break;
- default: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
- } break;
- }
- } break;
-
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- } break;
- default: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
- } break;
- }
- } break;
- case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER3D:
- case ShaderLanguage::TYPE_USAMPLER3D:
- case ShaderLanguage::TYPE_SAMPLER3D: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY:
- case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
- } break;
-
- default: {
- }
- }
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
- if (uniform_array_size > 0) {
- for (int j = 0; j < uniform_array_size; j++) {
- p_textures[k++] = rd_texture;
- }
- } else {
- p_textures[k++] = rd_texture;
- }
- } else {
- bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
-
- for (int j = 0; j < textures.size(); j++) {
- Texture *tex = singleton->texture_owner.get_or_null(textures[j]);
-
- if (tex) {
- rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
-#ifdef TOOLS_ENABLED
- if (tex->detect_3d_callback && p_use_linear_color) {
- tex->detect_3d_callback(tex->detect_3d_callback_ud);
- }
- if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
- if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
- normal_detect_texture = tex;
- }
- tex->detect_normal_callback(tex->detect_normal_callback_ud);
- }
- if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
- //find the normal texture
- roughness_detect_texture = tex;
- roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
- }
-#endif
- }
- if (rd_texture.is_null()) {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
- }
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
- p_textures[k++] = rd_texture;
- }
- }
- }
- {
- //for textures no longer used, unregister them
- List<Map<StringName, uint64_t>::Element *> to_delete;
- 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) {
- to_delete.push_back(E);
-
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
- if (v) {
- v->texture_materials.erase(self);
- }
- }
- }
-
- while (to_delete.front()) {
- used_global_textures.erase(to_delete.front()->get());
- to_delete.pop_front();
- }
- //handle registering/unregistering global textures
- if (uses_global_textures != (global_texture_E != nullptr)) {
- if (uses_global_textures) {
- global_texture_E = rs->global_variables.materials_using_texture.push_back(self);
- } else {
- rs->global_variables.materials_using_texture.erase(global_texture_E);
- global_texture_E = nullptr;
- }
- }
- }
-}
-
-void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
- if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(p_uniform_set);
- }
-}
-
-bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
- if ((uint32_t)ubo_data.size() != p_ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(p_ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
- }
-
- uint32_t tex_uniform_count = 0U;
- for (int i = 0; i < p_texture_uniforms.size(); i++) {
- tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
- }
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return false;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return false;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (p_ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
- const int array_size = p_texture_uniforms[i].array_size;
-
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + k;
- if (array_size > 0) {
- for (int j = 0; j < array_size; j++) {
- u.ids.push_back(textures[k++]);
- }
- } else {
- u.ids.push_back(textures[k++]);
- }
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
-
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self);
-
- return true;
-}
-
-void RendererStorageRD::_material_uniform_set_erased(void *p_material) {
- RID rid = *(RID *)p_material;
- Material *material = base_singleton->material_owner.get_or_null(rid);
- if (material) {
- if (material->data) {
- // Uniform set may be gone because a dependency was erased. This happens
- // if a texture is deleted, so re-create it.
- base_singleton->_material_queue_update(material, false, true);
- }
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- }
-}
-
-void RendererStorageRD::_update_queued_materials() {
- while (material_update_list.first()) {
- Material *material = material_update_list.first()->self();
- bool uniforms_changed = false;
-
- if (material->data) {
- uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
- }
- material->texture_dirty = false;
- material->uniform_dirty = false;
-
- material_update_list.remove(&material->update_element);
-
- if (uniforms_changed) {
- //some implementations such as 3D renderer cache the matreial uniform set, so update is required
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- }
- }
-}
-
-/* MESH API */
-
-RID RendererStorageRD::mesh_allocate() {
- return mesh_owner.allocate_rid();
-}
-void RendererStorageRD::mesh_initialize(RID p_rid) {
- mesh_owner.initialize_rid(p_rid, Mesh());
-}
-
-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.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- 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.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
-
-#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))) {
- switch (i) {
- case RS::ARRAY_VERTEX: {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- stride += sizeof(float) * 2;
- } else {
- stride += sizeof(float) * 3;
- }
-
- } break;
- case RS::ARRAY_NORMAL: {
- stride += sizeof(int32_t);
-
- } break;
- case RS::ARRAY_TANGENT: {
- stride += sizeof(int32_t);
-
- } break;
- case RS::ARRAY_COLOR: {
- attrib_stride += sizeof(uint32_t);
- } break;
- case RS::ARRAY_TEX_UV: {
- attrib_stride += sizeof(float) * 2;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- attrib_stride += sizeof(float) * 2;
-
- } break;
- 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 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
-
- Mesh::Surface *s = memnew(Mesh::Surface);
-
- s->format = p_surface.format;
- s->primitive = p_surface.primitive;
-
- 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;
-
- s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
- s->index_count = p_surface.index_count;
- s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
- if (p_surface.lods.size()) {
- s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
- s->lod_count = p_surface.lods.size();
-
- for (int i = 0; i < p_surface.lods.size(); i++) {
- uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
- s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
- s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
- s->lods[i].edge_length = p_surface.lods[i].edge_length;
- s->lods[i].index_count = indices;
- }
- }
- }
-
- s->aabb = p_surface.aabb;
- s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
-
- 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);
- }
-
- 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]);
- }
- mesh->aabb.merge_with(p_surface.aabb);
- }
-
- s->material = p_surface.material;
-
- mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
- mesh->surfaces[mesh->surface_count] = s;
- mesh->surface_count++;
-
- for (MeshInstance *mi : mesh->instances) {
- _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
- }
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
-
- mesh->material_cache.clear();
-}
-
-int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const {
- const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, -1);
- return mesh->blend_shape_count;
-}
-
-void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX((int)p_mode, 2);
-
- mesh->blend_shape_mode = p_mode;
-}
-
-RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
- return mesh->blend_shape_mode;
-}
-
-void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
- Mesh *mesh = mesh_owner.get_or_null(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->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- mesh->material_cache.clear();
-}
-
-RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
- ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
-
- return mesh->surfaces[p_surface]->material;
-}
-
-RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
- ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
-
- Mesh::Surface &s = *mesh->surfaces[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;
-
- if (sd.index_count) {
- sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
- }
- sd.aabb = s.aabb;
- for (uint32_t i = 0; i < s.lod_count; i++) {
- RS::SurfaceData::LOD lod;
- lod.edge_length = s.lods[i].edge_length;
- lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
- sd.lods.push_back(lod);
- }
-
- sd.bone_aabbs = s.bone_aabbs;
-
- if (s.blend_shape_buffer.is_valid()) {
- sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
- }
-
- return sd;
-}
-
-int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
- return mesh->surface_count;
-}
-
-void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- mesh->custom_aabb = p_aabb;
-}
-
-AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
- return mesh->custom_aabb;
-}
-
-AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
-
- if (mesh->custom_aabb != AABB()) {
- return mesh->custom_aabb;
- }
-
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- if (!skeleton || skeleton->size == 0) {
- return mesh->aabb;
- }
-
- AABB aabb;
-
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- AABB laabb;
- if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
- int bs = mesh->surfaces[i]->bone_aabbs.size();
- const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
-
- int sbs = skeleton->size;
- ERR_CONTINUE(bs > sbs);
- const float *baseptr = skeleton->data.ptr();
-
- bool first = true;
-
- if (skeleton->use_2d) {
- for (int j = 0; j < bs; j++) {
- if (skbones[0].size == Vector3()) {
- continue; //bone is unused
- }
-
- const float *dataptr = baseptr + j * 8;
-
- Transform3D mtx;
-
- mtx.basis.elements[0].x = dataptr[0];
- mtx.basis.elements[1].x = dataptr[1];
- mtx.origin.x = dataptr[3];
-
- mtx.basis.elements[0].y = dataptr[4];
- mtx.basis.elements[1].y = dataptr[5];
- mtx.origin.y = dataptr[7];
-
- AABB baabb = mtx.xform(skbones[j]);
-
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- } else {
- for (int j = 0; j < bs; j++) {
- if (skbones[0].size == Vector3()) {
- continue; //bone is unused
- }
-
- const float *dataptr = baseptr + j * 12;
-
- Transform3D mtx;
-
- mtx.basis.elements[0][0] = dataptr[0];
- mtx.basis.elements[0][1] = dataptr[1];
- mtx.basis.elements[0][2] = dataptr[2];
- mtx.origin.x = dataptr[3];
- mtx.basis.elements[1][0] = dataptr[4];
- mtx.basis.elements[1][1] = dataptr[5];
- mtx.basis.elements[1][2] = dataptr[6];
- mtx.origin.y = dataptr[7];
- mtx.basis.elements[2][0] = dataptr[8];
- mtx.basis.elements[2][1] = dataptr[9];
- mtx.basis.elements[2][2] = dataptr[10];
- mtx.origin.z = dataptr[11];
-
- AABB baabb = mtx.xform(skbones[j]);
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- }
-
- if (laabb.size == Vector3()) {
- laabb = mesh->surfaces[i]->aabb;
- }
- } else {
- laabb = mesh->surfaces[i]->aabb;
- }
-
- if (i == 0) {
- aabb = laabb;
- } else {
- aabb.merge_with(laabb);
- }
- }
-
- return aabb;
-}
-
-void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
- if (shadow_mesh) {
- shadow_mesh->shadow_owners.erase(mesh);
- }
- mesh->shadow_mesh = p_shadow_mesh;
-
- shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
-
- if (shadow_mesh) {
- shadow_mesh->shadow_owners.insert(mesh);
- }
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-}
-
-void RendererStorageRD::mesh_clear(RID p_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(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.
- }
-
- if (s.index_buffer.is_valid()) {
- RD::get_singleton()->free(s.index_buffer);
- }
-
- if (s.lod_count) {
- for (uint32_t j = 0; j < s.lod_count; j++) {
- RD::get_singleton()->free(s.lods[j].index_buffer);
- }
- memdelete_arr(s.lods);
- }
-
- if (s.blend_shape_buffer.is_valid()) {
- RD::get_singleton()->free(s.blend_shape_buffer);
- }
-
- memdelete(mesh->surfaces[i]);
- }
- if (mesh->surfaces) {
- memfree(mesh->surfaces);
- }
-
- mesh->surfaces = nullptr;
- mesh->surface_count = 0;
- mesh->material_cache.clear();
- //clear instance data
- for (MeshInstance *mi : mesh->instances) {
- _mesh_instance_clear(mi);
- }
- mesh->has_bone_weights = false;
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
-}
-
-bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
- Mesh *mesh = mesh_owner.get_or_null(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.get_or_null(p_base);
- ERR_FAIL_COND_V(!mesh, RID());
-
- RID rid = mesh_instance_owner.make_rid();
- MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
-
- 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 rid;
-}
-void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(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.get_or_null(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].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);
- }
- if (mi->surfaces[i].vertex_buffer.is_valid()) {
- RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
- }
- }
- 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.get_or_null(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.get_or_null(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 RendererStorageRD::update_mesh_instances() {
- while (dirty_mesh_instance_weights.first()) {
- MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
-
- 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());
- }
- 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.get_or_null(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);
- }
-
- 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_INDEX; i++) {
- RD::VertexAttribute vd;
- RID buffer;
- vd.location = i;
-
- 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;
-
- } break;
- case RS::ARRAY_NORMAL: {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- } break;
- case RS::ARRAY_TANGENT: {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- case RS::ARRAY_COLOR: {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
-
- } break;
- case RS::ARRAY_TEX_UV: {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
-
- } break;
- 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_SFLOAT;
- } break;
- }
- } else {
- //Supplied, use it
-
- 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;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- stride += sizeof(float) * 3;
- }
-
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
-
- } break;
- case RS::ARRAY_NORMAL: {
- vd.offset = stride;
-
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
- } break;
- case RS::ARRAY_TANGENT: {
- vd.offset = stride;
-
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
- } break;
- case RS::ARRAY_COLOR: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- attribute_stride += sizeof(int8_t) * 4;
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_TEX_UV: {
- 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: {
- 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: {
- vd.offset = skin_stride;
-
- 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 (but computing stride was important anyway)
- }
-
- attributes.push_back(vd);
- buffers.push_back(buffer);
- }
-
- //update final stride
- for (int i = 0; i < attributes.size(); i++) {
- 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;
- }
- }
-
- v.input_mask = p_input_mask;
- v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
- v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
-}
-
-////////////////// MULTIMESH
-
-RID RendererStorageRD::multimesh_allocate() {
- return multimesh_owner.allocate_rid();
-}
-void RendererStorageRD::multimesh_initialize(RID p_rid) {
- multimesh_owner.initialize_rid(p_rid, MultiMesh());
-}
-
-void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
- return;
- }
-
- if (multimesh->buffer.is_valid()) {
- RD::get_singleton()->free(multimesh->buffer);
- multimesh->buffer = RID();
- multimesh->uniform_set_2d = RID(); //cleared by dependency
- multimesh->uniform_set_3d = RID(); //cleared by dependency
- }
-
- if (multimesh->data_cache_dirty_regions) {
- memdelete_arr(multimesh->data_cache_dirty_regions);
- multimesh->data_cache_dirty_regions = nullptr;
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- multimesh->instances = p_instances;
- multimesh->xform_format = p_transform_format;
- multimesh->uses_colors = p_use_colors;
- multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
- multimesh->uses_custom_data = p_use_custom_data;
- multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
- multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
- multimesh->buffer_set = false;
-
- //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
- multimesh->data_cache = Vector<float>();
- multimesh->aabb = AABB();
- multimesh->aabb_dirty = false;
- multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
-
- 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 RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
- return multimesh->instances;
-}
-
-void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- if (multimesh->mesh == p_mesh) {
- return;
- }
- multimesh->mesh = p_mesh;
-
- if (multimesh->instances == 0) {
- return;
- }
-
- if (multimesh->data_cache.size()) {
- //we have a data cache, just mark it dirt
- _multimesh_mark_all_dirty(multimesh, false, true);
- } else if (multimesh->instances) {
- //need to re-create AABB unfortunately, calling this has a penalty
- if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- const uint8_t *r = buffer.ptr();
- const float *data = (const float *)r;
- _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- }
- }
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-}
-
-#define MULTIMESH_DIRTY_REGION_SIZE 512
-
-void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
- if (multimesh->data_cache.size() > 0) {
- return; //already local
- }
- ERR_FAIL_COND(multimesh->data_cache.size() > 0);
- // this means that the user wants to load/save individual elements,
- // for this, the data must reside on CPU, so just copy it there.
- multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = multimesh->data_cache.ptrw();
-
- if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- {
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
- } else {
- memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
- }
- }
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
-}
-
-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;
- ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
-#endif
- if (!multimesh->data_cache_dirty_regions[region_index]) {
- multimesh->data_cache_dirty_regions[region_index] = true;
- multimesh->data_cache_used_dirty_regions++;
- }
-
- if (p_aabb) {
- multimesh->aabb_dirty = true;
- }
-
- if (!multimesh->dirty) {
- multimesh->dirty_list = multimesh_dirty_list;
- multimesh_dirty_list = multimesh;
- multimesh->dirty = true;
- }
-}
-
-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;
-
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- if (!multimesh->data_cache_dirty_regions[i]) {
- multimesh->data_cache_dirty_regions[i] = true;
- multimesh->data_cache_used_dirty_regions++;
- }
- }
- }
-
- if (p_aabb) {
- multimesh->aabb_dirty = true;
- }
-
- if (!multimesh->dirty) {
- multimesh->dirty_list = multimesh_dirty_list;
- multimesh_dirty_list = multimesh;
- multimesh->dirty = true;
- }
-}
-
-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);
- for (int i = 0; i < p_instances; i++) {
- const float *data = p_data + multimesh->stride_cache * i;
- Transform3D t;
-
- if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
- t.basis.elements[0][0] = data[0];
- t.basis.elements[0][1] = data[1];
- t.basis.elements[0][2] = data[2];
- t.origin.x = data[3];
- t.basis.elements[1][0] = data[4];
- t.basis.elements[1][1] = data[5];
- t.basis.elements[1][2] = data[6];
- t.origin.y = data[7];
- t.basis.elements[2][0] = data[8];
- t.basis.elements[2][1] = data[9];
- t.basis.elements[2][2] = data[10];
- t.origin.z = data[11];
-
- } else {
- t.basis.elements[0].x = data[0];
- t.basis.elements[1].x = data[1];
- t.origin.x = data[3];
-
- t.basis.elements[0].y = data[4];
- t.basis.elements[1].y = data[5];
- t.origin.y = data[7];
- }
-
- if (i == 0) {
- aabb = t.xform(mesh_aabb);
- } else {
- aabb.merge_with(t.xform(mesh_aabb));
- }
- }
-
- multimesh->aabb = aabb;
-}
-
-void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache;
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, true);
-}
-
-void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache;
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
- }
-
- _multimesh_mark_dirty(multimesh, p_index, true);
-}
-
-void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(!multimesh->uses_colors);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, false);
-}
-
-void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(!multimesh->uses_custom_data);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, false);
-}
-
-RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, RID());
-
- return multimesh->mesh;
-}
-
-Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform3D());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
-
- _multimesh_make_local(multimesh);
-
- Transform3D t;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache;
-
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
- t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
- t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
- t.origin.z = dataptr[11];
- }
-
- return t;
-}
-
-Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform2D());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
-
- _multimesh_make_local(multimesh);
-
- Transform2D t;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache;
-
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
- }
-
- return t;
-}
-
-Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
- ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
-
- _multimesh_make_local(multimesh);
-
- Color c;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
- }
-
- return c;
-}
-
-Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
- ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
-
- _multimesh_make_local(multimesh);
-
- Color c;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
- }
-
- return c;
-}
-
-void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
-
- {
- const float *r = p_buffer.ptr();
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
- multimesh->buffer_set = true;
- }
-
- if (multimesh->data_cache.size()) {
- //if we have a data cache, just update it
- multimesh->data_cache = p_buffer;
- {
- //clear dirty since nothing will be dirty anymore
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
- } else if (multimesh->mesh.is_valid()) {
- //if we have a mesh set, we need to re-generate the AABB from the new data
- const float *data = p_buffer.ptr();
-
- _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
-}
-
-Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Vector<float>());
- if (multimesh->buffer.is_null()) {
- return Vector<float>();
- } else if (multimesh->data_cache.size()) {
- return multimesh->data_cache;
- } else {
- //get from memory
-
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- Vector<float> ret;
- ret.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = ret.ptrw();
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
-
- return ret;
- }
-}
-
-void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
- if (multimesh->visible_instances == p_visible) {
- return;
- }
-
- if (multimesh->data_cache.size()) {
- //there is a data cache..
- _multimesh_mark_all_dirty(multimesh, false, true);
- }
-
- multimesh->visible_instances = p_visible;
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
-}
-
-int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
- return multimesh->visible_instances;
-}
-
-AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, AABB());
- if (multimesh->aabb_dirty) {
- const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes();
- }
- return multimesh->aabb;
-}
-
-void RendererStorageRD::_update_dirty_multimeshes() {
- while (multimesh_dirty_list) {
- MultiMesh *multimesh = multimesh_dirty_list;
-
- if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
- const float *data = multimesh->data_cache.ptr();
-
- uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
-
- if (multimesh->data_cache_used_dirty_regions) {
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
-
- uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
-
- if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
- //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
- } else {
- //not that many regions? update them all
- for (uint32_t i = 0; i < visible_region_count; i++) {
- if (multimesh->data_cache_dirty_regions[i]) {
- uint32_t offset = i * region_size;
- uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
- uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
- }
- }
- }
-
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
-
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- if (multimesh->aabb_dirty) {
- //aabb is dirty..
- _multimesh_re_create_aabb(multimesh, data, visible_instances);
- multimesh->aabb_dirty = false;
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
- }
-
- multimesh_dirty_list = multimesh->dirty_list;
-
- multimesh->dirty_list = nullptr;
- multimesh->dirty = false;
- }
-
- multimesh_dirty_list = nullptr;
-}
-
-/* PARTICLES */
-
-RID RendererStorageRD::particles_allocate() {
- return particles_owner.allocate_rid();
-}
-void RendererStorageRD::particles_initialize(RID p_rid) {
- particles_owner.initialize_rid(p_rid, Particles());
-}
-
-void RendererStorageRD::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- if (particles->mode == p_mode) {
- return;
- }
-
- _particles_free_data(particles);
-
- particles->mode = p_mode;
-}
-
-void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->emitting = p_emitting;
-}
-
-bool RendererStorageRD::particles_get_emitting(RID p_particles) {
- ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, false);
-
- return particles->emitting;
-}
-
-void RendererStorageRD::_particles_free_data(Particles *particles) {
- if (particles->particle_buffer.is_valid()) {
- RD::get_singleton()->free(particles->particle_buffer);
- particles->particle_buffer = RID();
- RD::get_singleton()->free(particles->particle_instance_buffer);
- particles->particle_instance_buffer = RID();
- }
-
- particles->userdata_count = 0;
-
- if (particles->frame_params_buffer.is_valid()) {
- RD::get_singleton()->free(particles->frame_params_buffer);
- particles->frame_params_buffer = RID();
- }
- particles->particles_transforms_buffer_uniform_set = RID();
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) {
- RD::get_singleton()->free(particles->trail_bind_pose_uniform_set);
- }
- particles->trail_bind_pose_uniform_set = RID();
-
- if (particles->trail_bind_pose_buffer.is_valid()) {
- RD::get_singleton()->free(particles->trail_bind_pose_buffer);
- particles->trail_bind_pose_buffer = RID();
- }
- if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) {
- RD::get_singleton()->free(particles->collision_textures_uniform_set);
- }
- particles->collision_textures_uniform_set = RID();
-
- if (particles->particles_sort_buffer.is_valid()) {
- RD::get_singleton()->free(particles->particles_sort_buffer);
- particles->particles_sort_buffer = RID();
- particles->particles_sort_uniform_set = RID();
- }
-
- if (particles->emission_buffer != nullptr) {
- particles->emission_buffer = nullptr;
- particles->emission_buffer_data.clear();
- RD::get_singleton()->free(particles->emission_storage_buffer);
- particles->emission_storage_buffer = RID();
- }
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
- //will need to be re-created
- RD::get_singleton()->free(particles->particles_material_uniform_set);
- }
- particles->particles_material_uniform_set = RID();
-}
-
-void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (particles->amount == p_amount) {
- return;
- }
-
- _particles_free_data(particles);
-
- particles->amount = p_amount;
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_lifetime(RID p_particles, double p_lifetime) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->lifetime = p_lifetime;
-}
-
-void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->one_shot = p_one_shot;
-}
-
-void RendererStorageRD::particles_set_pre_process_time(RID p_particles, double p_time) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->pre_process_time = p_time;
-}
-void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->explosiveness = p_ratio;
-}
-void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->randomness = p_ratio;
-}
-
-void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->custom_aabb = p_aabb;
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_set_speed_scale(RID p_particles, double p_scale) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->speed_scale = p_scale;
-}
-void RendererStorageRD::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->use_local_coords = p_enable;
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->fixed_fps = p_fps;
-
- _particles_free_data(particles);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_interpolate(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->interpolate = p_enable;
-}
-
-void RendererStorageRD::particles_set_fractional_delta(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->fractional_delta = p_enable;
-}
-
-void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(p_length < 0.1);
- p_length = MIN(10.0, p_length);
-
- particles->trails_enabled = p_enable;
- particles->trail_length = p_length;
-
- _particles_free_data(particles);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
- _particles_free_data(particles);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- }
- particles->trail_bind_poses = p_bind_poses;
- particles->trail_bind_poses_dirty = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_collision_base_size(RID p_particles, real_t p_size) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->collision_base_size = p_size;
-}
-
-void RendererStorageRD::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->transform_align = p_transform_align;
-}
-
-void RendererStorageRD::particles_set_process_material(RID p_particles, RID p_material) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->process_material = p_material;
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
-}
-
-RID RendererStorageRD::particles_get_process_material(RID p_particles) const {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
-
- return particles->process_material;
-}
-
-void RendererStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->draw_order = p_order;
-}
-
-void RendererStorageRD::particles_set_draw_passes(RID p_particles, int p_passes) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->draw_passes.resize(p_passes);
-}
-
-void RendererStorageRD::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
- particles->draw_passes.write[p_pass] = p_mesh;
-}
-
-void RendererStorageRD::particles_restart(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->restart_request = true;
-}
-
-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);
- memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size());
- particles->emission_buffer = (ParticleEmissionBuffer *)particles->emission_buffer_data.ptrw();
- particles->emission_buffer->particle_max = particles->amount;
-
- particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data);
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
- //will need to be re-created
- RD::get_singleton()->free(particles->particles_material_uniform_set);
- particles->particles_material_uniform_set = RID();
- }
-}
-
-void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(p_particles == p_subemitter_particles);
-
- particles->sub_emitter = p_subemitter_particles;
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
- RD::get_singleton()->free(particles->particles_material_uniform_set);
- particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting
- }
-}
-
-void RendererStorageRD::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(particles->amount == 0);
-
- if (particles->emitting) {
- particles->clear = true;
- particles->emitting = false;
- }
-
- if (particles->emission_buffer == nullptr) {
- _particles_allocate_emission_buffer(particles);
- }
-
- if (particles->inactive) {
- //in case it was inactive, make active again
- particles->inactive = false;
- particles->inactive_time = 0;
- }
-
- int32_t idx = particles->emission_buffer->particle_count;
- if (idx < particles->emission_buffer->particle_max) {
- store_transform(p_transform, particles->emission_buffer->data[idx].xform);
-
- particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
- particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
- particles->emission_buffer->data[idx].velocity[2] = p_velocity.z;
-
- particles->emission_buffer->data[idx].custom[0] = p_custom.r;
- particles->emission_buffer->data[idx].custom[1] = p_custom.g;
- particles->emission_buffer->data[idx].custom[2] = p_custom.b;
- particles->emission_buffer->data[idx].custom[3] = p_custom.a;
-
- particles->emission_buffer->data[idx].color[0] = p_color.r;
- particles->emission_buffer->data[idx].color[1] = p_color.g;
- particles->emission_buffer->data[idx].color[2] = p_color.b;
- particles->emission_buffer->data[idx].color[3] = p_color.a;
-
- particles->emission_buffer->data[idx].flags = p_emit_flags;
- particles->emission_buffer->particle_count++;
- }
-}
-
-void RendererStorageRD::particles_request_process(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (!particles->dirty) {
- particles->dirty = true;
- particles->update_list = particle_update_list;
- particle_update_list = particles;
- }
-}
-
-AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
- if (RSG::threaded) {
- WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
- }
-
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, AABB());
-
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
- ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB());
-
- Transform3D inv = particles->emission_transform.affine_inverse();
-
- AABB aabb;
- if (buffer.size()) {
- bool first = true;
-
- const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
- uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count;
-
- for (int i = 0; i < total_amount; i++) {
- const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i];
- if (particle_data.active) {
- Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]);
- if (!particles->use_local_coords) {
- pos = inv.xform(pos);
- }
- if (first) {
- aabb.position = pos;
- first = false;
- } else {
- aabb.expand_to(pos);
- }
- }
- }
- }
-
- float longest_axis_size = 0;
- for (int i = 0; i < particles->draw_passes.size(); i++) {
- if (particles->draw_passes[i].is_valid()) {
- AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID());
- longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
- }
- }
-
- aabb.grow_by(longest_axis_size);
-
- return aabb;
-}
-
-AABB RendererStorageRD::particles_get_aabb(RID p_particles) const {
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, AABB());
-
- return particles->custom_aabb;
-}
-
-void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->emission_transform = p_transform;
-}
-
-int RendererStorageRD::particles_get_draw_passes(RID p_particles) const {
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- return particles->draw_passes.size();
-}
-
-RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
- ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
-
- return particles->draw_passes[p_pass];
-}
-
-void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->collisions.insert(p_particles_collision_instance);
-}
-
-void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->collisions.erase(p_particles_collision_instance);
-}
-
-void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->has_sdf_collision = p_enable;
- particles->sdf_collision_transform = p_xform;
- particles->sdf_collision_to_screen = p_to_screen;
- particles->sdf_collision_texture = p_texture;
-}
-
-void RendererStorageRD::_particles_process(Particles *p_particles, double 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.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.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.ids.push_back(p_particles->particle_buffer);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- 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);
- } else {
- u.ids.push_back(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 3;
- Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
- if (sub_emitter) {
- if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
- _particles_allocate_emission_buffer(sub_emitter);
- }
- u.ids.push_back(sub_emitter->emission_storage_buffer);
- } else {
- u.ids.push_back(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
-
- p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
- }
-
- double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
-
- //move back history (if there is any)
- for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
- p_particles->frame_history[i] = p_particles->frame_history[i - 1];
- }
- //update current frame
- ParticlesFrameParams &frame_params = p_particles->frame_history[0];
-
- if (p_particles->clear) {
- p_particles->cycle_number = 0;
- p_particles->random_seed = Math::rand();
- } else if (new_phase < p_particles->phase) {
- if (p_particles->one_shot) {
- p_particles->emitting = false;
- }
- p_particles->cycle_number++;
- }
-
- frame_params.emitting = p_particles->emitting;
- frame_params.system_phase = new_phase;
- frame_params.prev_system_phase = p_particles->phase;
-
- p_particles->phase = new_phase;
-
- 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;
- frame_params.randomness = p_particles->randomness;
-
- if (p_particles->use_local_coords) {
- store_transform(Transform3D(), frame_params.emission_transform);
- } else {
- store_transform(p_particles->emission_transform, frame_params.emission_transform);
- }
-
- frame_params.cycle = p_particles->cycle_number;
- frame_params.frame = p_particles->frame_counter++;
- frame_params.pad0 = 0;
- frame_params.pad1 = 0;
- frame_params.pad2 = 0;
-
- { //collision and attractors
-
- frame_params.collider_count = 0;
- frame_params.attractor_count = 0;
- frame_params.particle_size = p_particles->collision_base_size;
-
- RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
- RID collision_heightmap_texture;
-
- Transform3D to_particles;
- if (p_particles->use_local_coords) {
- to_particles = p_particles->emission_transform.affine_inverse();
- }
-
- if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) {
- //2D collision
-
- Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
- Transform2D revert = xform.affine_inverse();
- frame_params.collider_count = 1;
- frame_params.colliders[0].transform[0] = xform.elements[0][0];
- frame_params.colliders[0].transform[1] = xform.elements[0][1];
- frame_params.colliders[0].transform[2] = 0;
- frame_params.colliders[0].transform[3] = xform.elements[2][0];
-
- frame_params.colliders[0].transform[4] = xform.elements[1][0];
- frame_params.colliders[0].transform[5] = xform.elements[1][1];
- frame_params.colliders[0].transform[6] = 0;
- frame_params.colliders[0].transform[7] = xform.elements[2][1];
-
- frame_params.colliders[0].transform[8] = revert.elements[0][0];
- frame_params.colliders[0].transform[9] = revert.elements[0][1];
- frame_params.colliders[0].transform[10] = 0;
- frame_params.colliders[0].transform[11] = revert.elements[2][0];
-
- frame_params.colliders[0].transform[12] = revert.elements[1][0];
- frame_params.colliders[0].transform[13] = revert.elements[1][1];
- frame_params.colliders[0].transform[14] = 0;
- frame_params.colliders[0].transform[15] = revert.elements[2][1];
-
- frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
- frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
- frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
- frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
- frame_params.colliders[0].texture_index = 0;
- frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
-
- collision_heightmap_texture = p_particles->sdf_collision_texture;
-
- //replace in all other history frames where used because parameters are no longer valid if screen moves
- for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
- if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
- p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
- }
- }
- }
-
- uint32_t collision_3d_textures_used = 0;
- for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get());
- if (!pci || !pci->active) {
- continue;
- }
- ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
- ERR_CONTINUE(!pc);
-
- Transform3D to_collider = pci->transform;
- if (p_particles->use_local_coords) {
- to_collider = to_particles * to_collider;
- }
- Vector3 scale = to_collider.basis.get_scale();
- to_collider.basis.orthonormalize();
-
- if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
- //attractor
- if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
- continue;
- }
-
- ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
-
- store_transform(to_collider, attr.transform);
- attr.strength = pc->attractor_strength;
- attr.attenuation = pc->attractor_attenuation;
- attr.directionality = pc->attractor_directionality;
-
- switch (pc->type) {
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
- attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
- float radius = pc->radius;
- radius *= (scale.x + scale.y + scale.z) / 3.0;
- attr.extents[0] = radius;
- attr.extents[1] = radius;
- attr.extents[2] = radius;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
- attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
- Vector3 extents = pc->extents * scale;
- attr.extents[0] = extents.x;
- attr.extents[1] = extents.y;
- attr.extents[2] = extents.z;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
- if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
- continue;
- }
- attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD;
- Vector3 extents = pc->extents * scale;
- attr.extents[0] = extents.x;
- attr.extents[1] = extents.y;
- attr.extents[2] = extents.z;
- attr.texture_index = collision_3d_textures_used;
-
- collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
- collision_3d_textures_used++;
- } break;
- default: {
- }
- }
-
- frame_params.attractor_count++;
- } else {
- //collider
- if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
- continue;
- }
-
- ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
-
- store_transform(to_collider, col.transform);
- switch (pc->type) {
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
- col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
- float radius = pc->radius;
- radius *= (scale.x + scale.y + scale.z) / 3.0;
- col.extents[0] = radius;
- col.extents[1] = radius;
- col.extents[2] = radius;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
- col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
- Vector3 extents = pc->extents * scale;
- col.extents[0] = extents.x;
- col.extents[1] = extents.y;
- col.extents[2] = extents.z;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
- if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
- continue;
- }
- col.type = ParticlesFrameParams::COLLISION_TYPE_SDF;
- Vector3 extents = pc->extents * scale;
- col.extents[0] = extents.x;
- col.extents[1] = extents.y;
- col.extents[2] = extents.z;
- col.texture_index = collision_3d_textures_used;
- col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported
-
- collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
- collision_3d_textures_used++;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
- if (collision_heightmap_texture != RID()) { //already taken
- continue;
- }
-
- col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
- Vector3 extents = pc->extents * scale;
- col.extents[0] = extents.x;
- col.extents[1] = extents.y;
- col.extents[2] = extents.z;
- collision_heightmap_texture = pc->heightfield_texture;
- } break;
- default: {
- }
- }
-
- frame_params.collider_count++;
- }
- }
-
- bool different = false;
- if (collision_3d_textures_used == p_particles->collision_3d_textures_used) {
- for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
- if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) {
- different = true;
- break;
- }
- }
- }
-
- if (collision_heightmap_texture != p_particles->collision_heightmap_texture) {
- different = true;
- }
-
- bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set);
-
- if (different || !uniform_set_valid) {
- if (uniform_set_valid) {
- RD::get_singleton()->free(p_particles->collision_textures_uniform_set);
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
- RID rd_tex;
- if (i < collision_3d_textures_used) {
- Texture *t = texture_owner.get_or_null(collision_3d_textures[i]);
- if (t && t->type == Texture::TYPE_3D) {
- rd_tex = t->rd_texture;
- }
- }
-
- if (rd_tex == RID()) {
- rd_tex = default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE];
- }
- u.ids.push_back(rd_tex);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- if (collision_heightmap_texture.is_valid()) {
- u.ids.push_back(collision_heightmap_texture);
- } else {
- u.ids.push_back(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]);
- }
- uniforms.push_back(u);
- }
- p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
- }
- }
-
- ParticlesShader::PushConstant push_constant;
-
- int process_amount = p_particles->amount;
-
- if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
- process_amount *= p_particles->trail_bind_poses.size();
- }
- push_constant.clear = p_particles->clear;
- push_constant.total_particles = p_particles->amount;
- push_constant.lifetime = p_particles->lifetime;
- push_constant.trail_size = p_particles->trail_params.size();
- push_constant.use_fractional_delta = p_particles->fractional_delta;
- push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit);
- push_constant.trail_pass = false;
-
- p_particles->force_sub_emit = false; //reset
-
- Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
-
- if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) {
- // print_line("updating subemitter buffer");
- int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 };
- RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero);
- push_constant.can_emit = true;
-
- if (sub_emitter->emitting) {
- sub_emitter->emitting = false;
- sub_emitter->clear = true; //will need to clear if it was emitting, sorry
- }
- //make sure the sub emitter processes particles too
- sub_emitter->inactive = false;
- sub_emitter->inactive_time = 0;
-
- sub_emitter->force_sub_emit = true;
-
- } else {
- push_constant.can_emit = false;
- }
-
- if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) {
- RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer);
- p_particles->emission_buffer->particle_count = 0;
- }
-
- p_particles->clear = false;
-
- if (p_particles->trail_params.size() > 1) {
- //fill the trail params
- for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) {
- uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size();
- p_particles->trail_params[i] = p_particles->frame_history[src_idx];
- }
- } else {
- p_particles->trail_params[0] = p_particles->frame_history[0];
- }
-
- RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
-
- ParticlesMaterialData *m = (ParticlesMaterialData *)material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES);
- if (!m) {
- m = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES);
- }
-
- ERR_FAIL_COND(!m);
-
- p_particles->has_collision_cache = m->shader_data->uses_collision;
-
- //todo should maybe compute all particle systems together?
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2);
-
- if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
-
- if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
- //trails requires two passes in order to catch particle starts
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- push_constant.trail_pass = true;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1);
- } else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
- return;
- }
-
- if (particles->particle_buffer.is_null()) {
- return; //particles have not processed yet
- }
-
- bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
-
- //copy to sort buffer
- if (do_sort && particles->particles_sort_buffer == RID()) {
- uint32_t size = particles->amount;
- if (size & 1) {
- size++; //make multiple of 16
- }
- size *= sizeof(float) * 2;
- particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size);
-
- {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(particles->particles_sort_buffer);
- uniforms.push_back(u);
- }
-
- particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1);
- }
- }
-
- ParticlesShader::CopyPushConstant copy_push_constant;
-
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- int fixed_fps = 60.0;
- if (particles->fixed_fps > 0) {
- fixed_fps = particles->fixed_fps;
- }
-
- copy_push_constant.trail_size = particles->trail_bind_poses.size();
- copy_push_constant.trail_total = particles->frame_history.size();
- copy_push_constant.frame_delta = 1.0 / fixed_fps;
- } else {
- copy_push_constant.trail_size = 1;
- copy_push_constant.trail_total = 1;
- copy_push_constant.frame_delta = 0.0;
- }
-
- copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
- copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
- copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
-
- copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
- copy_push_constant.total_particles = particles->amount;
- copy_push_constant.copy_mode_2d = false;
-
- Vector3 axis = -p_axis; // cameras look to z negative
-
- if (particles->use_local_coords) {
- axis = particles->emission_transform.basis.xform_inv(axis).normalized();
- }
-
- copy_push_constant.sort_direction[0] = axis.x;
- copy_push_constant.sort_direction[1] = axis.y;
- copy_push_constant.sort_direction[2] = axis.z;
-
- copy_push_constant.align_up[0] = p_up_axis.x;
- copy_push_constant.align_up[1] = p_up_axis.y;
- copy_push_constant.align_up[2] = p_up_axis.z;
-
- copy_push_constant.align_mode = particles->transform_align;
-
- if (do_sort) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
-
- RD::get_singleton()->compute_list_end();
- effects->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
- }
-
- copy_push_constant.total_particles *= copy_push_constant.total_particles;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
- copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX;
- copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
- if (do_sort) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::_particles_update_buffers(Particles *particles) {
- uint32_t userdata_count = 0;
-
- const Material *material = material_owner.get_or_null(particles->process_material);
- if (material && material->shader && material->shader->data) {
- const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
- userdata_count = shader_data->userdata_count;
- }
-
- if (userdata_count != particles->userdata_count) {
- // Mismatch userdata, re-create buffers.
- _particles_free_data(particles);
- }
-
- if (particles->amount > 0 && particles->particle_buffer.is_null()) {
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
- uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
-
- particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
-
- particles->userdata_count = userdata_count;
-
- particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount);
- //needs to clear it
-
- {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- 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.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.ids.push_back(particles->particle_instance_buffer);
- uniforms.push_back(u);
- }
-
- particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0);
- }
- }
-}
-void RendererStorageRD::update_particles() {
- while (particle_update_list) {
- //use transform feedback to process particles
-
- Particles *particles = particle_update_list;
-
- //take and remove
- particle_update_list = particles->update_list;
- particles->update_list = nullptr;
- particles->dirty = false;
-
- _particles_update_buffers(particles);
-
- if (particles->restart_request) {
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- particles->restart_request = false;
- }
-
- if (particles->inactive && !particles->emitting) {
- //go next
- continue;
- }
-
- if (particles->emitting) {
- if (particles->inactive) {
- //restart system from scratch
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- }
- particles->inactive = false;
- particles->inactive_time = 0;
- } else {
- particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time();
- if (particles->inactive_time > particles->lifetime * 1.2) {
- particles->inactive = true;
- continue;
- }
- }
-
-#ifndef _MSC_VER
-#warning Should use display refresh rate for all this
-#endif
-
- float screen_hz = 60;
-
- int fixed_fps = 0;
- if (particles->fixed_fps > 0) {
- fixed_fps = particles->fixed_fps;
- } else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- fixed_fps = screen_hz;
- }
- {
- //update trails
- int history_size = 1;
- int trail_steps = 1;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- history_size = MAX(1, int(particles->trail_length * fixed_fps));
- trail_steps = particles->trail_bind_poses.size();
- }
-
- if (uint32_t(history_size) != particles->frame_history.size()) {
- particles->frame_history.resize(history_size);
- memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size);
- }
-
- if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) {
- particles->trail_params.resize(trail_steps);
- if (particles->frame_params_buffer.is_valid()) {
- RD::get_singleton()->free(particles->frame_params_buffer);
- }
- particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps);
- }
-
- if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) {
- particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size());
- particles->trail_bind_poses_dirty = true;
- }
-
- if (particles->trail_bind_pose_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- if (particles->trail_bind_pose_buffer.is_valid()) {
- u.ids.push_back(particles->trail_bind_pose_buffer);
- } else {
- u.ids.push_back(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
-
- particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2);
- }
-
- if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) {
- if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) {
- particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16);
- }
-
- for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
- store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
- }
-
- RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
- }
- }
-
- bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
-
- if (particles->clear && particles->pre_process_time > 0.0) {
- double frame_time;
- if (fixed_fps > 0) {
- frame_time = 1.0 / fixed_fps;
- } else {
- frame_time = 1.0 / 30.0;
- }
-
- double todo = particles->pre_process_time;
-
- while (todo >= 0) {
- _particles_process(particles, frame_time);
- todo -= frame_time;
- }
- }
-
- if (fixed_fps > 0) {
- double frame_time;
- double decr;
- if (zero_time_scale) {
- frame_time = 0.0;
- decr = 1.0 / fixed_fps;
- } else {
- frame_time = 1.0 / fixed_fps;
- decr = frame_time;
- }
- double 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..
- delta = 0.001;
- }
- double todo = particles->frame_remainder + delta;
-
- while (todo >= frame_time) {
- _particles_process(particles, frame_time);
- todo -= decr;
- }
-
- particles->frame_remainder = todo;
-
- } else {
- if (zero_time_scale) {
- _particles_process(particles, 0.0);
- } else {
- _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
- }
- }
-
- //copy particles to instance buffer
-
- if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
- //does not need view dependent operation, do copy here
- ParticlesShader::CopyPushConstant copy_push_constant;
-
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
- // Affect 2D only.
- if (particles->use_local_coords) {
- // In local mode, particle positions are calculated locally (relative to the node position)
- // and they're also drawn locally.
- // It works as expected, so we just pass an identity transform.
- store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
- } else {
- // In global mode, particle positions are calculated globally (relative to the canvas origin)
- // but they're drawn locally.
- // So, we need to pass the inverse of the emission transform to bring the
- // particles to local coordinates before drawing.
- Transform3D inv = particles->emission_transform.affine_inverse();
- store_transform(inv, copy_push_constant.inv_emission_transform);
- }
-
- copy_push_constant.total_particles = total_amount;
- copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
- copy_push_constant.align_mode = particles->transform_align;
- copy_push_constant.align_up[0] = 0;
- copy_push_constant.align_up[1] = 0;
- copy_push_constant.align_up[2] = 0;
-
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- copy_push_constant.trail_size = particles->trail_bind_poses.size();
- copy_push_constant.trail_total = particles->frame_history.size();
- copy_push_constant.frame_delta = 1.0 / fixed_fps;
- } else {
- copy_push_constant.trail_size = 1;
- copy_push_constant.trail_total = 1;
- copy_push_constant.frame_delta = 0.0;
- }
-
- copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
- copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
- copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1);
-
- RD::get_singleton()->compute_list_end();
- }
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
-}
-
-bool RendererStorageRD::particles_is_inactive(RID p_particles) const {
- ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, false);
- return !particles->emitting && particles->inactive;
-}
-
-/* SKY SHADER */
-
-void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
- //compile
-
- code = p_code;
- valid = false;
- ubo_size = 0;
- uniforms.clear();
- uses_collision = false;
-
- if (code.is_empty()) {
- return; //just invalid, but no error
- }
-
- ShaderCompiler::GeneratedCode gen_code;
- ShaderCompiler::IdentifierActions actions;
- actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE;
- actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE;
-
- /*
- uses_time = false;
-
- actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
- actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
-
- actions.usage_flag_pointers["TIME"] = &uses_time;
-*/
-
- actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
-
- userdata_count = 0;
- for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
- userdatas_used[i] = false;
- actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
- }
-
- actions.uniforms = &uniforms;
-
- Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
- ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
-
- if (version.is_null()) {
- version = base_singleton->particles_shader.shader.version_create();
- }
-
- for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
- if (userdatas_used[i]) {
- userdata_count++;
- }
- }
-
- base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
- ERR_FAIL_COND(!base_singleton->particles_shader.shader.version_is_valid(version));
-
- ubo_size = gen_code.uniform_total_size;
- ubo_offsets = gen_code.uniform_offsets;
- texture_uniforms = gen_code.texture_uniforms;
-
- //update pipelines
-
- pipeline = RD::get_singleton()->compute_pipeline_create(base_singleton->particles_shader.shader.version_get_shader(version, 0));
-
- valid = true;
-}
-
-void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
- if (!p_texture.is_valid()) {
- if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
- default_texture_params[p_name].erase(p_index);
-
- if (default_texture_params[p_name].is_empty()) {
- default_texture_params.erase(p_name);
- }
- }
- } else {
- if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
- }
- default_texture_params[p_name][p_index] = p_texture;
- }
-}
-
-void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- if (E.value.texture_order >= 0) {
- order[E.value.texture_order + 100000] = E.key;
- } else {
- order[E.value.order] = E.key;
- }
- }
-
- for (const KeyValue<int, StringName> &E : order) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
- pi.name = E.value;
- p_param_list->push_back(pi);
- }
-}
-
-void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- RendererStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E.value);
- p.info.name = E.key; //supply name
- p.index = E.value.instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
- p_param_list->push_back(p);
- }
-}
-
-bool RendererStorageRD::ParticlesShaderData::is_param_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
-bool RendererStorageRD::ParticlesShaderData::is_animated() const {
- return false;
-}
-
-bool RendererStorageRD::ParticlesShaderData::casts_shadows() const {
- return false;
-}
-
-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;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
-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;
-}
-
-RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() {
- //pipeline variants will clear themselves if shader is gone
- if (version.is_valid()) {
- base_singleton->particles_shader.shader.version_free(version);
- }
-}
-
-RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func() {
- ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
- return shader_data;
-}
-
-bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
-}
-
-RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() {
- free_parameters_uniform_set(uniform_set);
-}
-
-RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
- ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
- material_data->shader_data = p_shader;
- //update will happen later anyway so do nothing.
- return material_data;
-}
-////////
-
-/* PARTICLES COLLISION API */
-
-RID RendererStorageRD::particles_collision_allocate() {
- return particles_collision_owner.allocate_rid();
-}
-void RendererStorageRD::particles_collision_initialize(RID p_rid) {
- particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
-}
-
-RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, RID());
- ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID());
-
- if (particles_collision->heightfield_texture == RID()) {
- //create
- int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
- Size2i size;
- if (particles_collision->extents.x > particles_collision->extents.z) {
- size.x = resolutions[particles_collision->heightfield_resolution];
- size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
- } else {
- size.y = resolutions[particles_collision->heightfield_resolution];
- size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
- }
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_D32_SFLOAT;
- tf.width = size.x;
- tf.height = size.y;
- 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());
-
- Vector<RID> fb_tex;
- fb_tex.push_back(particles_collision->heightfield_texture);
- particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex);
- particles_collision->heightfield_fb_size = size;
- }
-
- return particles_collision->heightfield_fb;
-}
-
-void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- if (p_type == particles_collision->type) {
- return;
- }
-
- if (particles_collision->heightfield_texture.is_valid()) {
- RD::get_singleton()->free(particles_collision->heightfield_texture);
- particles_collision->heightfield_texture = RID();
- }
- particles_collision->type = p_type;
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
- particles_collision->cull_mask = p_cull_mask;
-}
-
-void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->radius = p_radius;
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->extents = p_extents;
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->attractor_strength = p_strength;
-}
-
-void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->attractor_directionality = p_directionality;
-}
-
-void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->attractor_attenuation = p_curve;
-}
-
-void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->field_texture = p_texture;
-}
-
-void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
- ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
-
- if (particles_collision->heightfield_resolution == p_resolution) {
- return;
- }
-
- particles_collision->heightfield_resolution = p_resolution;
-
- if (particles_collision->heightfield_texture.is_valid()) {
- RD::get_singleton()->free(particles_collision->heightfield_texture);
- particles_collision->heightfield_texture = RID();
- }
-}
-
-AABB RendererStorageRD::particles_collision_get_aabb(RID p_particles_collision) const {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, AABB());
-
- switch (particles_collision->type) {
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
- AABB aabb;
- aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
- aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
- return aabb;
- }
- default: {
- AABB aabb;
- aabb.position = -particles_collision->extents;
- aabb.size = particles_collision->extents * 2;
- return aabb;
- }
- }
-
- return AABB();
-}
-
-Vector3 RendererStorageRD::particles_collision_get_extents(RID p_particles_collision) const {
- const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, Vector3());
- return particles_collision->extents;
-}
-
-bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_collision) const {
- const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(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 Transform3D &p_transform) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(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.get_or_null(p_collision_instance);
- ERR_FAIL_COND(!pci);
- pci->active = p_active;
-}
-
/* FOG VOLUMES */
RID RendererStorageRD::fog_volume_allocate() {
@@ -6191,6 +97,8 @@ AABB RendererStorageRD::fog_volume_get_aabb(RID p_fog_volume) const {
switch (fog_volume->shape) {
case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
+ case RS::FOG_VOLUME_SHAPE_CONE:
+ case RS::FOG_VOLUME_SHAPE_CYLINDER:
case RS::FOG_VOLUME_SHAPE_BOX: {
AABB aabb;
aabb.position = -fog_volume->extents;
@@ -6265,795 +173,7 @@ void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, b
}
}
-/* SKELETON API */
-
-RID RendererStorageRD::skeleton_allocate() {
- return skeleton_owner.allocate_rid();
-}
-void RendererStorageRD::skeleton_initialize(RID p_rid) {
- skeleton_owner.initialize_rid(p_rid, Skeleton());
-}
-
-void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
- if (!skeleton->dirty) {
- skeleton->dirty = true;
- skeleton->dirty_list = skeleton_dirty_list;
- skeleton_dirty_list = skeleton;
- }
-}
-
-void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_COND(p_bones < 0);
-
- if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
- return;
- }
-
- skeleton->size = p_bones;
- skeleton->use_2d = p_2d_skeleton;
- skeleton->uniform_set_3d = RID();
-
- if (skeleton->buffer.is_valid()) {
- RD::get_singleton()->free(skeleton->buffer);
- skeleton->buffer = RID();
- skeleton->data.clear();
- skeleton->uniform_set_mi = RID();
- }
-
- if (skeleton->size) {
- skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
- skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
- memset(skeleton->data.ptrw(), 0, 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 RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, 0);
-
- return skeleton->size;
-}
-
-void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 12;
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
-
- _skeleton_make_dirty(skeleton);
-}
-
-Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform3D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
- ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
-
- const float *dataptr = skeleton->data.ptr() + p_bone * 12;
-
- Transform3D t;
-
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
- t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
- t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
- t.origin.z = dataptr[11];
-
- return t;
-}
-
-void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(!skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 8;
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
-
- _skeleton_make_dirty(skeleton);
-}
-
-Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform2D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
- ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
-
- const float *dataptr = skeleton->data.ptr() + p_bone * 8;
-
- Transform2D t;
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
-
- return t;
-}
-
-void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton->use_2d);
-
- skeleton->base_transform_2d = p_base_transform;
-}
-
-void RendererStorageRD::_update_dirty_skeletons() {
- while (skeleton_dirty_list) {
- Skeleton *skeleton = skeleton_dirty_list;
-
- if (skeleton->size) {
- RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr());
- }
-
- skeleton_dirty_list = skeleton->dirty_list;
-
- skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES);
-
- skeleton->version++;
-
- skeleton->dirty = false;
- skeleton->dirty_list = nullptr;
- }
-
- skeleton_dirty_list = nullptr;
-}
-
-/* LIGHT */
-
-void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) {
- Light light;
- light.type = p_type;
-
- light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
- light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
- 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_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_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
- light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
-
- light_owner.initialize_rid(p_light, light);
-}
-
-RID RendererStorageRD::directional_light_allocate() {
- return light_owner.allocate_rid();
-}
-void RendererStorageRD::directional_light_initialize(RID p_light) {
- _light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
-}
-
-RID RendererStorageRD::omni_light_allocate() {
- return light_owner.allocate_rid();
-}
-void RendererStorageRD::omni_light_initialize(RID p_light) {
- _light_initialize(p_light, RS::LIGHT_OMNI);
-}
-
-RID RendererStorageRD::spot_light_allocate() {
- return light_owner.allocate_rid();
-}
-void RendererStorageRD::spot_light_initialize(RID p_light) {
- _light_initialize(p_light, RS::LIGHT_SPOT);
-}
-
-void RendererStorageRD::light_set_color(RID p_light, const Color &p_color) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->color = p_color;
-}
-
-void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
- ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
-
- if (light->param[p_param] == p_value) {
- return;
- }
-
- switch (p_param) {
- case RS::LIGHT_PARAM_RANGE:
- case RS::LIGHT_PARAM_SPOT_ANGLE:
- case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
- case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
- case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
- case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
- case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
- case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
- case RS::LIGHT_PARAM_SHADOW_BIAS: {
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
- } break;
- case RS::LIGHT_PARAM_SIZE: {
- if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
- //changing from no size to size and the opposite
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
- }
- } break;
- default: {
- }
- }
-
- light->param[p_param] = p_value;
-}
-
-void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
- light->shadow = p_enabled;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
- light->shadow_color = p_color;
-}
-
-void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- if (light->projector == p_texture) {
- return;
- }
-
- if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
- texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
- }
-
- light->projector = p_texture;
-
- if (light->type != RS::LIGHT_DIRECTIONAL) {
- if (light->projector.is_valid()) {
- texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
- }
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
- }
-}
-
-void RendererStorageRD::light_set_negative(RID p_light, bool p_enable) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->negative = p_enable;
-}
-
-void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->cull_mask = p_mask;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->reverse_cull = p_enabled;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->bake_mode = p_bake_mode;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->max_sdfgi_cascade = p_cascade;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->omni_shadow_mode = p_mode;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
-
- return light->omni_shadow_mode;
-}
-
-void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_shadow_mode = p_mode;
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_blend_splits = p_enable;
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, false);
-
- return light->directional_blend_splits;
-}
-
-void RendererStorageRD::light_directional_set_sky_only(RID p_light, bool p_sky_only) {
- Light *light = light_owner.get_or_null(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.get_or_null(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.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
-
- return light->directional_shadow_mode;
-}
-
-uint32_t RendererStorageRD::light_get_max_sdfgi_cascade(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->max_sdfgi_cascade;
-}
-
-RS::LightBakeMode RendererStorageRD::light_get_bake_mode(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
-
- return light->bake_mode;
-}
-
-uint64_t RendererStorageRD::light_get_version(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->version;
-}
-
-AABB RendererStorageRD::light_get_aabb(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, AABB());
-
- switch (light->type) {
- case RS::LIGHT_SPOT: {
- float len = light->param[RS::LIGHT_PARAM_RANGE];
- float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
- return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
- };
- case RS::LIGHT_OMNI: {
- float r = light->param[RS::LIGHT_PARAM_RANGE];
- return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
- };
- case RS::LIGHT_DIRECTIONAL: {
- return AABB();
- };
- }
-
- ERR_FAIL_V(AABB());
-}
-
-/* REFLECTION PROBE */
-
-RID RendererStorageRD::reflection_probe_allocate() {
- return reflection_probe_owner.allocate_rid();
-}
-void RendererStorageRD::reflection_probe_initialize(RID p_reflection_probe) {
- reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
-}
-
-void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->update_mode = p_mode;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->intensity = p_intensity;
-}
-
-void RendererStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->ambient_mode = p_mode;
-}
-
-void RendererStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->ambient_color = p_color;
-}
-
-void RendererStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->ambient_color_energy = p_energy;
-}
-
-void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->max_distance = p_distance;
-
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- if (reflection_probe->extents == p_extents) {
- return;
- }
- reflection_probe->extents = p_extents;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->origin_offset = p_offset;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->interior = p_enable;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->box_projection = p_enable;
-}
-
-void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->enable_shadows = p_enable;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->cull_mask = p_layers;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
- ERR_FAIL_COND(p_resolution < 32);
-
- reflection_probe->resolution = p_resolution;
-}
-
-void RendererStorageRD::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->mesh_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.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, AABB());
-
- AABB aabb;
- aabb.position = -reflection_probe->extents;
- aabb.size = reflection_probe->extents * 2.0;
-
- return aabb;
-}
-
-RS::ReflectionProbeUpdateMode RendererStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
-
- return reflection_probe->update_mode;
-}
-
-uint32_t RendererStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->cull_mask;
-}
-
-Vector3 RendererStorageRD::reflection_probe_get_extents(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Vector3());
-
- return reflection_probe->extents;
-}
-
-Vector3 RendererStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Vector3());
-
- return reflection_probe->origin_offset;
-}
-
-bool RendererStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->enable_shadows;
-}
-
-float RendererStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->max_distance;
-}
-
-float RendererStorageRD::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->mesh_lod_threshold;
-}
-
-int RendererStorageRD::reflection_probe_get_resolution(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->resolution;
-}
-
-float RendererStorageRD::reflection_probe_get_intensity(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->intensity;
-}
-
-bool RendererStorageRD::reflection_probe_is_interior(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->interior;
-}
-
-bool RendererStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->box_projection;
-}
-
-RS::ReflectionProbeAmbientMode RendererStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
- return reflection_probe->ambient_mode;
-}
-
-Color RendererStorageRD::reflection_probe_get_ambient_color(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Color());
-
- return reflection_probe->ambient_color;
-}
-float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->ambient_color_energy;
-}
-
-RID RendererStorageRD::decal_allocate() {
- return decal_owner.allocate_rid();
-}
-void RendererStorageRD::decal_initialize(RID p_decal) {
- decal_owner.initialize_rid(p_decal, Decal());
-}
-
-void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->extents = p_extents;
- decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
-
- if (decal->textures[p_type] == p_texture) {
- return;
- }
-
- ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture));
-
- if (decal->textures[p_type].is_valid() && texture_owner.owns(decal->textures[p_type])) {
- texture_remove_from_decal_atlas(decal->textures[p_type]);
- }
-
- decal->textures[p_type] = p_texture;
-
- if (decal->textures[p_type].is_valid()) {
- texture_add_to_decal_atlas(decal->textures[p_type]);
- }
-
- decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL);
-}
-
-void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->emission_energy = p_energy;
-}
-
-void RendererStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->albedo_mix = p_mix;
-}
-
-void RendererStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->modulate = p_modulate;
-}
-
-void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->cull_mask = p_layers;
- decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->distance_fade = p_enabled;
- decal->distance_fade_begin = p_begin;
- decal->distance_fade_length = p_length;
-}
-
-void RendererStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->upper_fade = p_above;
- decal->lower_fade = p_below;
-}
-
-void RendererStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->normal_fade = p_fade;
-}
-
-AABB RendererStorageRD::decal_get_aabb(RID p_decal) const {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND_V(!decal, AABB());
-
- return AABB(-decal->extents, decal->extents * 2.0);
-}
+/* VOXEL GI */
RID RendererStorageRD::voxel_gi_allocate() {
return voxel_gi_owner.allocate_rid();
@@ -7136,21 +256,21 @@ void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.ids.push_back(voxel_gi->octree_buffer);
+ u.append_id(voxel_gi->octree_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.ids.push_back(voxel_gi->data_buffer);
+ u.append_id(voxel_gi->data_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 3;
- u.ids.push_back(shared_tex);
+ u.append_id(shared_tex);
uniforms.push_back(u);
}
@@ -7383,902 +503,38 @@ RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
return voxel_gi->sdf_texture;
}
-/* LIGHTMAP API */
-
-RID RendererStorageRD::lightmap_allocate() {
- return lightmap_owner.allocate_rid();
-}
-
-void RendererStorageRD::lightmap_initialize(RID p_lightmap) {
- lightmap_owner.initialize_rid(p_lightmap, Lightmap());
-}
-
-void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
-
- lightmap_array_version++;
-
- //erase lightmap users
- if (lm->light_texture.is_valid()) {
- Texture *t = texture_owner.get_or_null(lm->light_texture);
- if (t) {
- t->lightmap_users.erase(p_lightmap);
- }
- }
-
- Texture *t = texture_owner.get_or_null(p_light);
- lm->light_texture = p_light;
- lm->uses_spherical_harmonics = p_uses_spherical_haromics;
-
- RID default_2d_array = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE];
- if (!t) {
- if (using_lightmap_array) {
- if (lm->array_index >= 0) {
- lightmap_textures.write[lm->array_index] = default_2d_array;
- lm->array_index = -1;
- }
- }
-
- return;
- }
-
- t->lightmap_users.insert(p_lightmap);
-
- if (using_lightmap_array) {
- if (lm->array_index < 0) {
- //not in array, try to put in array
- for (int i = 0; i < lightmap_textures.size(); i++) {
- if (lightmap_textures[i] == default_2d_array) {
- lm->array_index = i;
- break;
- }
- }
- }
- ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly.");
-
- lightmap_textures.write[lm->array_index] = t->rd_texture;
- }
-}
-
-void RendererStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
- lm->bounds = p_bounds;
-}
-
-void RendererStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
- lm->interior = p_interior;
-}
-
-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.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
-
- if (p_points.size()) {
- ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());
- ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
- ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
- }
-
- lm->points = p_points;
- lm->bsp_tree = p_bsp_tree;
- lm->point_sh = p_point_sh;
- lm->tetrahedra = p_tetrahedra;
-}
-
-PackedVector3Array RendererStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedVector3Array());
-
- return lm->points;
-}
-
-PackedColorArray RendererStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedColorArray());
- return lm->point_sh;
-}
-
-PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedInt32Array());
- return lm->tetrahedra;
-}
-
-PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedInt32Array());
- return lm->bsp_tree;
-}
-
-void RendererStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) {
- lightmap_probe_capture_update_speed = p_speed;
-}
-
-void RendererStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
-
- for (int i = 0; i < 9; i++) {
- r_sh[i] = Color(0, 0, 0, 0);
- }
-
- if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {
- return;
- }
-
- static_assert(sizeof(Lightmap::BSP) == 24);
-
- const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();
- int32_t node = 0;
- while (node >= 0) {
- if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);
-#endif
-
- node = bsp[node].over;
- } else {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);
-#endif
- node = bsp[node].under;
- }
- }
-
- if (node == Lightmap::BSP::EMPTY_LEAF) {
- return; //nothing could be done
- }
-
- node = ABS(node) - 1;
-
- uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
- Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
- const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
- Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
-
- for (int i = 0; i < 4; i++) {
- float c = CLAMP(barycentric[i], 0.0, 1.0);
- for (int j = 0; j < 9; j++) {
- r_sh[j] += sh_colors[i][j] * c;
- }
- }
-}
-
-bool RendererStorageRD::lightmap_is_interior(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, false);
- return lm->interior;
-}
-
-AABB RendererStorageRD::lightmap_get_aabb(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, AABB());
- return lm->bounds;
-}
-
-/* RENDER TARGET API */
-
-void RendererStorageRD::_clear_render_target(RenderTarget *rt) {
- //free in reverse dependency order
- if (rt->framebuffer.is_valid()) {
- RD::get_singleton()->free(rt->framebuffer);
- rt->framebuffer_uniform_set = RID(); //chain deleted
- }
-
- if (rt->color.is_valid()) {
- RD::get_singleton()->free(rt->color);
- }
-
- if (rt->backbuffer.is_valid()) {
- RD::get_singleton()->free(rt->backbuffer);
- rt->backbuffer = RID();
- rt->backbuffer_mipmaps.clear();
- rt->backbuffer_uniform_set = RID(); //chain deleted
- }
-
- _render_target_clear_sdf(rt);
-
- rt->framebuffer = RID();
- rt->color = RID();
-}
-
-void RendererStorageRD::_update_render_target(RenderTarget *rt) {
- if (rt->texture.is_null()) {
- //create a placeholder until updated
- rt->texture = texture_allocate();
- texture_2d_placeholder_initialize(rt->texture);
- Texture *tex = texture_owner.get_or_null(rt->texture);
- tex->is_render_target = true;
- }
-
- _clear_render_target(rt);
-
- if (rt->size.width == 0 || rt->size.height == 0) {
- return;
- }
- //until we implement support for HDR monitors (and render target is attached to screen), this is enough.
- rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
-
- RD::TextureFormat rd_format;
- RD::TextureView rd_view;
- { //attempt register
- rd_format.format = rt->color_format;
- rd_format.width = rt->size.width;
- rd_format.height = rt->size.height;
- rd_format.depth = 1;
- rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
- rd_format.mipmaps = 1;
- if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
- rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- } else {
- 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);
- rd_format.shareable_formats.push_back(rt->color_format_srgb);
- }
-
- rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
- ERR_FAIL_COND(rt->color.is_null());
-
- Vector<RID> fb_textures;
- fb_textures.push_back(rt->color);
- rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
- if (rt->framebuffer.is_null()) {
- _clear_render_target(rt);
- ERR_FAIL_COND(rt->framebuffer.is_null());
- }
-
- { //update texture
-
- Texture *tex = texture_owner.get_or_null(rt->texture);
-
- //free existing textures
- if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
- RD::get_singleton()->free(tex->rd_texture);
- }
- if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
- RD::get_singleton()->free(tex->rd_texture_srgb);
- }
-
- tex->rd_texture = RID();
- tex->rd_texture_srgb = RID();
-
- //create shared textures to the color buffer,
- //so transparent can be supported
- RD::TextureView view;
- view.format_override = rt->color_format;
- if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
- view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- }
- tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
- if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
- view.format_override = rt->color_format_srgb;
- tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
- }
- tex->rd_view = view;
- tex->width = rt->size.width;
- tex->height = rt->size.height;
- tex->width_2d = rt->size.width;
- tex->height_2d = rt->size.height;
- tex->rd_format = rt->color_format;
- tex->rd_format_srgb = rt->color_format_srgb;
- tex->format = rt->image_format;
-
- Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
- for (int i = 0; i < proxies.size(); i++) {
- texture_proxy_update(proxies[i], rt->texture);
- }
- }
-}
-
-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);
- RD::TextureFormat tf;
- tf.format = rt->color_format;
- tf.width = rt->size.width;
- tf.height = rt->size.height;
- 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;
-
- rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rt->backbuffer, "Render Target Back Buffer");
- rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
- RD::get_singleton()->set_resource_name(rt->backbuffer_mipmap0, "Back Buffer slice mipmap 0");
-
- {
- Vector<RID> fb_tex;
- fb_tex.push_back(rt->backbuffer_mipmap0);
- rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
- }
-
- if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
- //the new one will require the backbuffer.
- RD::get_singleton()->free(rt->framebuffer_uniform_set);
- rt->framebuffer_uniform_set = RID();
- }
- //create mipmaps
- for (uint32_t i = 1; i < mipmaps_required; i++) {
- RID mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
- RD::get_singleton()->set_resource_name(mipmap, "Back Buffer slice mip: " + itos(i));
-
- rt->backbuffer_mipmaps.push_back(mipmap);
- }
-}
-
-RID RendererStorageRD::render_target_create() {
- RenderTarget render_target;
-
- render_target.was_used = false;
- render_target.clear_requested = false;
-
- for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
- render_target.flags[i] = false;
- }
- _update_render_target(&render_target);
- return render_target_owner.make_rid(render_target);
-}
-
-void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) {
- //unused for this render target
-}
-
-void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
- rt->size.x = p_width;
- rt->size.y = p_height;
- rt->view_count = p_view_count;
- _update_render_target(rt);
- }
-}
-
-RID RendererStorageRD::render_target_get_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- return rt->texture;
-}
-
-void RendererStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
-}
-
-void RendererStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->flags[p_flag] = p_value;
- _update_render_target(rt);
-}
-
-bool RendererStorageRD::render_target_was_used(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
- return rt->was_used;
-}
-
-void RendererStorageRD::render_target_set_as_unused(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->was_used = false;
-}
-
-Size2 RendererStorageRD::render_target_get_size(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
-
- return rt->size;
-}
-
-RID RendererStorageRD::render_target_get_rd_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- return rt->framebuffer;
-}
-
-RID RendererStorageRD::render_target_get_rd_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- return rt->color;
-}
-
-RID RendererStorageRD::render_target_get_rd_backbuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- return rt->backbuffer;
-}
-
-RID RendererStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- return rt->backbuffer_fb;
-}
-
-void RendererStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->clear_requested = true;
- rt->clear_color = p_clear_color;
-}
-
-bool RendererStorageRD::render_target_is_clear_requested(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
- return rt->clear_requested;
-}
-
-Color RendererStorageRD::render_target_get_clear_request_color(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Color());
- return rt->clear_color;
-}
-
-void RendererStorageRD::render_target_disable_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->clear_requested = false;
-}
-
-void RendererStorageRD::render_target_do_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->clear_requested) {
- return;
- }
- Vector<Color> clear_colors;
- clear_colors.push_back(rt->clear_color);
- RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
- RD::get_singleton()->draw_list_end();
- rt->clear_requested = false;
-}
-
-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.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
- return;
- }
-
- rt->sdf_oversize = p_size;
- rt->sdf_scale = p_scale;
-
- _render_target_clear_sdf(rt);
-}
-
-Rect2i RendererStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const {
- Size2i margin;
- int scale;
- switch (rt->sdf_oversize) {
- case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
- scale = 100;
- } break;
- case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
- scale = 120;
- } break;
- case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
- scale = 150;
- } break;
- case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
- scale = 200;
- } break;
- default: {
- }
- }
-
- margin = (rt->size * scale / 100) - rt->size;
-
- Rect2i r(Vector2i(), rt->size);
- r.position -= margin;
- r.size += margin * 2;
-
- return r;
-}
-
-Rect2i RendererStorageRD::render_target_get_sdf_rect(RID p_render_target) const {
- const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Rect2i());
-
- return _render_target_get_sdf_rect(rt);
-}
-
-void RendererStorageRD::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->sdf_enabled = p_enabled;
-}
-
-bool RendererStorageRD::render_target_is_sdf_enabled(RID p_render_target) const {
- const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
-
- return rt->sdf_enabled;
-}
-
-RID RendererStorageRD::render_target_get_sdf_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- if (rt->sdf_buffer_read.is_null()) {
- // no texture, create a dummy one for the 2D uniform set
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- memset(pv.ptrw(), 0, 16 * 4);
- Vector<Vector<uint8_t>> vpv;
-
- rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
-
- return rt->sdf_buffer_read;
-}
-
-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);
- rt->sdf_buffer_read = RID();
- }
-
- Size2i size = _render_target_get_sdf_rect(rt).size;
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8_UNORM;
- 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.texture_type = RD::TEXTURE_TYPE_2D;
-
- rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-
- {
- Vector<RID> write_fb;
- write_fb.push_back(rt->sdf_buffer_write);
- rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
- }
-
- int scale;
- switch (rt->sdf_scale) {
- case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
- scale = 100;
- } break;
- case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
- scale = 50;
- } break;
- case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
- scale = 25;
- } break;
- default: {
- scale = 100;
- } break;
- }
-
- rt->process_size = size * scale / 100;
- rt->process_size.x = MAX(rt->process_size.x, 1);
- rt->process_size.y = MAX(rt->process_size.y, 1);
-
- tformat.format = RD::DATA_FORMAT_R16G16_SINT;
- tformat.width = rt->process_size.width;
- tformat.height = rt->process_size.height;
- tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-
- tformat.format = RD::DATA_FORMAT_R16_SNORM;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- 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.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.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.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 4;
- u.ids.push_back(rt->sdf_buffer_process[1]);
- uniforms.push_back(u);
- }
-
- rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
- SWAP(uniforms.write[2].ids.write[0], uniforms.write[3].ids.write[0]);
- rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
- }
-}
-
-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();
- }
- if (rt->sdf_buffer_write_fb.is_valid()) {
- RD::get_singleton()->free(rt->sdf_buffer_write);
- RD::get_singleton()->free(rt->sdf_buffer_process[0]);
- RD::get_singleton()->free(rt->sdf_buffer_process[1]);
- rt->sdf_buffer_write = RID();
- rt->sdf_buffer_write_fb = RID();
- rt->sdf_buffer_process[0] = RID();
- rt->sdf_buffer_process[1] = RID();
- rt->sdf_buffer_process_uniform_sets[0] = RID();
- rt->sdf_buffer_process_uniform_sets[1] = RID();
- }
-}
-
-RID RendererStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- if (rt->sdf_buffer_write_fb.is_null()) {
- _render_target_allocate_sdf(rt);
- }
-
- return rt->sdf_buffer_write_fb;
-}
-void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
-
- RenderTargetSDF::PushConstant push_constant;
-
- Rect2i r = _render_target_get_sdf_rect(rt);
-
- push_constant.size[0] = r.size.width;
- push_constant.size[1] = r.size.height;
- push_constant.stride = 0;
- push_constant.shift = 0;
- push_constant.base_size[0] = r.size.width;
- push_constant.base_size[1] = r.size.height;
-
- bool shrink = false;
-
- switch (rt->sdf_scale) {
- case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
- push_constant.size[0] >>= 1;
- push_constant.size[1] >>= 1;
- push_constant.shift = 1;
- shrink = true;
- } break;
- case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
- push_constant.size[0] >>= 2;
- push_constant.size[1] >>= 2;
- push_constant.shift = 2;
- shrink = true;
- } break;
- default: {
- };
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- /* Load */
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
-
- /* Process */
-
- int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- bool swap = false;
-
- //jumpflood
- while (stride > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
- push_constant.stride = stride;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
- stride /= 2;
- swap = !swap;
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
-
- /* Store */
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-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.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- Rect2i region;
- if (p_region == Rect2i()) {
- region.size = rt->size;
- } else {
- region = Rect2i(Size2i(), rt->size).intersection(p_region);
- if (region.size == Size2i()) {
- return; //nothing to do
- }
- }
-
- //single texture copy for backbuffer
- //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
-
- if (!p_gen_mipmaps) {
- return;
- }
- RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps");
- //then mipmap blur
- RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
-
- for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
- region.position.x >>= 1;
- region.position.y >>= 1;
- region.size.x = MAX(1, region.size.x >> 1);
- region.size.y = MAX(1, region.size.y >> 1);
-
- RID mipmap = rt->backbuffer_mipmaps[i];
- effects->gaussian_blur(prev_texture, mipmap, region, true);
- prev_texture = mipmap;
- }
- RD::get_singleton()->draw_command_end_label();
-}
-
-void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- Rect2i region;
- if (p_region == Rect2i()) {
- region.size = rt->size;
- } else {
- region = Rect2i(Size2i(), rt->size).intersection(p_region);
- if (region.size == Size2i()) {
- return; //nothing to do
- }
- }
-
- //single texture copy for backbuffer
- effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
-}
-
-void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- Rect2i region;
- if (p_region == Rect2i()) {
- region.size = rt->size;
- } else {
- region = Rect2i(Size2i(), rt->size).intersection(p_region);
- if (region.size == Size2i()) {
- return; //nothing to do
- }
- }
- RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
- //then mipmap blur
- RID prev_texture = rt->backbuffer_mipmap0;
-
- for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
- region.position.x >>= 1;
- region.position.y >>= 1;
- region.size.x = MAX(1, region.size.x >> 1);
- region.size.y = MAX(1, region.size.y >> 1);
-
- RID mipmap = rt->backbuffer_mipmaps[i];
- effects->gaussian_blur(prev_texture, mipmap, region, true);
- prev_texture = mipmap;
- }
- RD::get_singleton()->draw_command_end_label();
-}
-
-RID RendererStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- return rt->framebuffer_uniform_set;
-}
-RID RendererStorageRD::render_target_get_backbuffer_uniform_set(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- return rt->backbuffer_uniform_set;
-}
-
-void RendererStorageRD::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->framebuffer_uniform_set = p_uniform_set;
-}
-void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->backbuffer_uniform_set = p_uniform_set;
-}
+/* misc */
void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
- if (mesh_owner.owns(p_base)) {
- Mesh *mesh = mesh_owner.get_or_null(p_base);
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {
+ RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base);
p_instance->update_dependency(&mesh->dependency);
- } else if (multimesh_owner.owns(p_base)) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_base);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base);
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.get_or_null(p_base);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
+ RendererRD::ReflectionProbe *rp = RendererRD::LightStorage::get_singleton()->get_reflection_probe(p_base);
p_instance->update_dependency(&rp->dependency);
- } else if (decal_owner.owns(p_base)) {
- Decal *decal = decal_owner.get_or_null(p_base);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_base)) {
+ RendererRD::Decal *decal = RendererRD::TextureStorage::get_singleton()->get_decal(p_base);
p_instance->update_dependency(&decal->dependency);
} else if (voxel_gi_owner.owns(p_base)) {
VoxelGI *gip = voxel_gi_owner.get_or_null(p_base);
p_instance->update_dependency(&gip->dependency);
- } else if (lightmap_owner.owns(p_base)) {
- Lightmap *lm = lightmap_owner.get_or_null(p_base);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_base)) {
+ RendererRD::Lightmap *lm = RendererRD::LightStorage::get_singleton()->get_lightmap(p_base);
p_instance->update_dependency(&lm->dependency);
- } else if (light_owner.owns(p_base)) {
- Light *l = light_owner.get_or_null(p_base);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_base)) {
+ RendererRD::Light *l = RendererRD::LightStorage::get_singleton()->get_light(p_base);
p_instance->update_dependency(&l->dependency);
- } else if (particles_owner.owns(p_base)) {
- Particles *p = particles_owner.get_or_null(p_base);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_base)) {
+ RendererRD::Particles *p = RendererRD::ParticlesStorage::get_singleton()->get_particles(p_base);
p_instance->update_dependency(&p->dependency);
- } else if (particles_collision_owner.owns(p_base)) {
- ParticlesCollision *pc = particles_collision_owner.get_or_null(p_base);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
+ RendererRD::ParticlesCollision *pc = RendererRD::ParticlesStorage::get_singleton()->get_particles_collision(p_base);
p_instance->update_dependency(&pc->dependency);
} else if (fog_volume_owner.owns(p_base)) {
FogVolume *fv = fog_volume_owner.get_or_null(p_base);
@@ -8289,39 +545,32 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
}
}
-void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND(!skeleton);
-
- p_instance->update_dependency(&skeleton->dependency);
-}
-
RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
- if (mesh_owner.owns(p_rid)) {
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
return RS::INSTANCE_MESH;
}
- if (multimesh_owner.owns(p_rid)) {
+ if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
return RS::INSTANCE_MULTIMESH;
}
- if (reflection_probe_owner.owns(p_rid)) {
+ if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
return RS::INSTANCE_REFLECTION_PROBE;
}
- if (decal_owner.owns(p_rid)) {
+ if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
return RS::INSTANCE_DECAL;
}
if (voxel_gi_owner.owns(p_rid)) {
return RS::INSTANCE_VOXEL_GI;
}
- if (light_owner.owns(p_rid)) {
+ if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
return RS::INSTANCE_LIGHT;
}
- if (lightmap_owner.owns(p_rid)) {
+ if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
return RS::INSTANCE_LIGHTMAP;
}
- if (particles_owner.owns(p_rid)) {
+ if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
return RS::INSTANCE_PARTICLES;
}
- if (particles_collision_owner.owns(p_rid)) {
+ if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
if (fog_volume_owner.owns(p_rid)) {
@@ -8334,910 +583,19 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
return RS::INSTANCE_NONE;
}
-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;
- t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
- decal_atlas.textures[p_texture] = t;
- decal_atlas.dirty = true;
- } else {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
- t->users++;
- if (p_panorama_to_dp) {
- t->panorama_to_dp_users++;
- }
- }
-}
-
-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--;
- if (p_panorama_to_dp) {
- ERR_FAIL_COND(t->panorama_to_dp_users == 0);
- t->panorama_to_dp_users--;
- }
- if (t->users == 0) {
- decal_atlas.textures.erase(p_texture);
- //do not mark it dirty, there is no need to since it remains working
- }
-}
-
-RID RendererStorageRD::decal_atlas_get_texture() const {
- return decal_atlas.texture;
-}
-
-RID RendererStorageRD::decal_atlas_get_texture_srgb() const {
- return decal_atlas.texture_srgb;
-}
-
-void RendererStorageRD::_update_decal_atlas() {
- if (!decal_atlas.dirty) {
- return; //nothing to do
- }
-
- decal_atlas.dirty = false;
-
- if (decal_atlas.texture.is_valid()) {
- RD::get_singleton()->free(decal_atlas.texture);
- decal_atlas.texture = RID();
- decal_atlas.texture_srgb = RID();
- decal_atlas.texture_mipmaps.clear();
- }
-
- int border = 1 << decal_atlas.mipmaps;
-
- if (decal_atlas.textures.size()) {
- //generate atlas
- Vector<DecalAtlas::SortItem> itemsv;
- itemsv.resize(decal_atlas.textures.size());
- int base_size = 8;
- const RID *K = nullptr;
-
- int idx = 0;
- while ((K = decal_atlas.textures.next(K))) {
- DecalAtlas::SortItem &si = itemsv.write[idx];
-
- Texture *src_tex = texture_owner.get_or_null(*K);
-
- si.size.width = (src_tex->width / border) + 1;
- si.size.height = (src_tex->height / border) + 1;
- si.pixel_size = Size2i(src_tex->width, src_tex->height);
-
- if (base_size < si.size.width) {
- base_size = nearest_power_of_2_templated(si.size.width);
- }
-
- si.texture = *K;
- idx++;
- }
-
- //sort items by size
- itemsv.sort();
-
- //attempt to create atlas
- int item_count = itemsv.size();
- DecalAtlas::SortItem *items = itemsv.ptrw();
-
- int atlas_height = 0;
-
- while (true) {
- Vector<int> v_offsetsv;
- v_offsetsv.resize(base_size);
-
- int *v_offsets = v_offsetsv.ptrw();
- memset(v_offsets, 0, sizeof(int) * base_size);
-
- int max_height = 0;
-
- for (int i = 0; i < item_count; i++) {
- //best fit
- DecalAtlas::SortItem &si = items[i];
- int best_idx = -1;
- int best_height = 0x7FFFFFFF;
- for (int j = 0; j <= base_size - si.size.width; j++) {
- int height = 0;
- for (int k = 0; k < si.size.width; k++) {
- int h = v_offsets[k + j];
- if (h > height) {
- height = h;
- if (height > best_height) {
- break; //already bad
- }
- }
- }
-
- if (height < best_height) {
- best_height = height;
- best_idx = j;
- }
- }
-
- //update
- for (int k = 0; k < si.size.width; k++) {
- v_offsets[k + best_idx] = best_height + si.size.height;
- }
-
- si.pos.x = best_idx;
- si.pos.y = best_height;
-
- if (si.pos.y + si.size.height > max_height) {
- max_height = si.pos.y + si.size.height;
- }
- }
-
- if (max_height <= base_size * 2) {
- atlas_height = max_height;
- break; //good ratio, break;
- }
-
- base_size *= 2;
- }
-
- decal_atlas.size.width = base_size * border;
- decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
-
- for (int i = 0; i < item_count; i++) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
- t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
- t->uv_rect.size = items[i].pixel_size;
-
- t->uv_rect.position /= Size2(decal_atlas.size);
- t->uv_rect.size /= Size2(decal_atlas.size);
- }
- } else {
- //use border as size, so it at least has enough mipmaps
- decal_atlas.size.width = border;
- decal_atlas.size.height = border;
- }
-
- //blit textures
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- 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.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);
-
- decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1);
-
- {
- //create the framebuffer
-
- Size2i s = decal_atlas.size;
-
- for (int i = 0; i < decal_atlas.mipmaps; i++) {
- DecalAtlas::MipMap mm;
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
- Vector<RID> fb;
- fb.push_back(mm.texture);
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
- mm.size = s;
- decal_atlas.texture_mipmaps.push_back(mm);
-
- s.width = MAX(1, s.width >> 1);
- s.height = MAX(1, s.height >> 1);
- }
- {
- //create the SRGB variant
- RD::TextureView rd_view;
- rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
- }
- }
-
- RID prev_texture;
- for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
- const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
-
- Color clear_color(0, 0, 0, 0);
-
- if (decal_atlas.textures.size()) {
- if (i == 0) {
- Vector<Color> cc;
- cc.push_back(clear_color);
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
-
- const RID *K = nullptr;
- while ((K = decal_atlas.textures.next(K))) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
- Texture *src_tex = texture_owner.get_or_null(*K);
- effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
- }
-
- RD::get_singleton()->draw_list_end();
-
- prev_texture = mm.texture;
- } else {
- effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
- prev_texture = mm.texture;
- }
- } else {
- RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1);
- }
- }
-}
-
-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) {
- bool valid = true;
- for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
- valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
- break;
- }
- }
-
- if (!valid) {
- continue; //if not valid, idx is in new position
- }
-
- return idx;
- } else {
- idx += global_variables.buffer_usage[idx].elements;
- }
- }
-
- return -1;
-}
-
-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];
- bool b = p_value;
- bv.x = b ? 1.0 : 0.0;
- bv.y = 0.0;
- bv.z = 0.0;
- bv.w = 0.0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = 0.0;
- bv.w = 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = (bvec & 4) ? 1.0 : 0.0;
- bv.w = 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = (bvec & 4) ? 1.0 : 0.0;
- bv.w = (bvec & 8) ? 1.0 : 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- int32_t v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector2i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector3i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector<int32_t> v = p_value;
- bv.x = v.size() >= 1 ? v[0] : 0;
- bv.y = v.size() >= 2 ? v[1] : 0;
- bv.z = v.size() >= 3 ? v[2] : 0;
- bv.w = v.size() >= 4 ? v[3] : 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Rect2i v = p_value;
- bv.x = v.position.x;
- bv.y = v.position.y;
- bv.z = v.size.x;
- bv.w = v.size.y;
- } break;
- case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- uint32_t v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector2i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector3i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector<int32_t> v = p_value;
- bv.x = v.size() >= 1 ? v[0] : 0;
- bv.y = v.size() >= 2 ? v[1] : 0;
- bv.z = v.size() >= 3 ? v[2] : 0;
- bv.w = v.size() >= 4 ? v[3] : 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- float v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Vector2 v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Vector3 v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Plane v = p_value;
- bv.x = v.normal.x;
- bv.y = v.normal.y;
- bv.z = v.normal.z;
- bv.w = v.d;
- } break;
- case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Color v = p_value;
- bv.x = v.r;
- bv.y = v.g;
- bv.z = v.b;
- bv.w = v.a;
-
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
- v = v.to_linear();
- bv_linear.x = v.r;
- bv_linear.y = v.g;
- bv_linear.z = v.b;
- bv_linear.w = v.a;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Rect2 v = p_value;
- bv.x = v.position.x;
- bv.y = v.position.y;
- bv.z = v.size.x;
- bv.w = v.size.y;
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Vector<float> m2 = p_value;
- if (m2.size() < 4) {
- m2.resize(4);
- }
- bv[0].x = m2[0];
- bv[0].y = m2[1];
- bv[0].z = 0;
- bv[0].w = 0;
-
- bv[1].x = m2[2];
- bv[1].y = m2[3];
- bv[1].z = 0;
- bv[1].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Basis v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[1][0];
- bv[0].z = v.elements[2][0];
- bv[0].w = 0;
-
- bv[1].x = v.elements[0][1];
- bv[1].y = v.elements[1][1];
- bv[1].z = v.elements[2][1];
- bv[1].w = 0;
-
- bv[2].x = v.elements[0][2];
- bv[2].y = v.elements[1][2];
- bv[2].z = v.elements[2][2];
- bv[2].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
-
- Vector<float> m2 = p_value;
- if (m2.size() < 16) {
- m2.resize(16);
- }
-
- bv[0].x = m2[0];
- bv[0].y = m2[1];
- bv[0].z = m2[2];
- bv[0].w = m2[3];
-
- bv[1].x = m2[4];
- bv[1].y = m2[5];
- bv[1].z = m2[6];
- bv[1].w = m2[7];
-
- bv[2].x = m2[8];
- bv[2].y = m2[9];
- bv[2].z = m2[10];
- bv[2].w = m2[11];
-
- bv[3].x = m2[12];
- bv[3].y = m2[13];
- bv[3].z = m2[14];
- bv[3].w = m2[15];
-
- } break;
- case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform2D v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[0][1];
- bv[0].z = 0;
- bv[0].w = 0;
-
- bv[1].x = v.elements[1][0];
- bv[1].y = v.elements[1][1];
- bv[1].z = 0;
- bv[1].w = 0;
-
- bv[2].x = v.elements[2][0];
- bv[2].y = v.elements[2][1];
- bv[2].z = 1;
- bv[2].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform3D v = p_value;
- bv[0].x = v.basis.elements[0][0];
- bv[0].y = v.basis.elements[1][0];
- bv[0].z = v.basis.elements[2][0];
- bv[0].w = 0;
-
- bv[1].x = v.basis.elements[0][1];
- bv[1].y = v.basis.elements[1][1];
- bv[1].z = v.basis.elements[2][1];
- bv[1].w = 0;
-
- bv[2].x = v.basis.elements[0][2];
- bv[2].y = v.basis.elements[1][2];
- bv[2].z = v.basis.elements[2][2];
- bv[2].w = 0;
-
- bv[3].x = v.origin.x;
- bv[3].y = v.origin.y;
- bv[3].z = v.origin.z;
- bv[3].w = 1;
-
- } break;
- default: {
- ERR_FAIL();
- }
- }
-}
-
-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++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
- }
- }
-
- prev_chunk = chunk;
- }
-}
-
-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;
- gv.value = p_value;
- gv.buffer_index = -1;
-
- if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //is texture
- global_variables.must_update_texture_materials = true; //normally there are none
- } else {
- gv.buffer_elements = 1;
- if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 2;
- }
- if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 3;
- }
- if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 4;
- }
-
- //is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
- ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
-
- global_variables.must_update_buffer_materials = true; //normally there are none
- }
-
- global_variables.variables[p_name] = gv;
-}
-
-void RendererStorageRD::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
- return;
- }
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
-
- if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
- } else {
- global_variables.must_update_texture_materials = true;
- }
-
- global_variables.variables.erase(p_name);
-}
-
-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.");
- }
-
- const StringName *K = nullptr;
- Vector<StringName> names;
- while ((K = global_variables.variables.next(K))) {
- names.push_back(*K);
- }
- names.sort_custom<StringName::AlphCompare>();
- return names;
-}
-
-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;
- if (gv.override.get_type() == Variant::NIL) {
- if (gv.buffer_index >= 0) {
- //buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- } else {
- //texture
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.get_or_null(E->get());
- ERR_CONTINUE(!material);
- _material_queue_update(material, false, true);
- }
- }
- }
-}
-
-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
- }
-
- ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
-
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
-
- gv.override = p_value;
-
- if (gv.buffer_index >= 0) {
- //buffer
- if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- } else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
- }
-
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- } else {
- //texture
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.get_or_null(E->get());
- ERR_CONTINUE(!material);
- _material_queue_update(material, false, true);
- }
- }
-}
-
-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.");
- }
-
- if (!global_variables.variables.has(p_name)) {
- return Variant();
- }
-
- return global_variables.variables[p_name].value;
-}
-
-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;
- }
-
- return global_variables.variables[p_name].type;
-}
-
-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.");
- }
-
- return global_variable_get_type_internal(p_name);
-}
-
-void RendererStorageRD::global_variables_load_settings(bool p_load_textures) {
- List<PropertyInfo> settings;
- ProjectSettings::get_singleton()->get_property_list(&settings);
-
- for (const PropertyInfo &E : settings) {
- if (E.name.begins_with("shader_globals/")) {
- StringName name = E.name.get_slice("/", 1);
- Dictionary d = ProjectSettings::get_singleton()->get(E.name);
-
- ERR_CONTINUE(!d.has("type"));
- ERR_CONTINUE(!d.has("value"));
-
- String type = d["type"];
-
- static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
- "bool",
- "bvec2",
- "bvec3",
- "bvec4",
- "int",
- "ivec2",
- "ivec3",
- "ivec4",
- "rect2i",
- "uint",
- "uvec2",
- "uvec3",
- "uvec4",
- "float",
- "vec2",
- "vec3",
- "vec4",
- "color",
- "rect2",
- "mat2",
- "mat3",
- "mat4",
- "transform_2d",
- "transform",
- "sampler2D",
- "sampler2DArray",
- "sampler3D",
- "samplerCube",
- };
-
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
-
- for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
- if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
- break;
- }
- }
-
- ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
-
- Variant value = d["value"];
-
- if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //textire
- if (!p_load_textures) {
- value = RID();
- continue;
- }
-
- String path = value;
- RES resource = ResourceLoader::load(path);
- ERR_CONTINUE(resource.is_null());
- value = resource;
- }
-
- if (global_variables.variables.has(name)) {
- //has it, update it
- global_variable_set(name, value);
- } else {
- global_variable_add(name, gvtype, value);
- }
- }
- }
-}
-
-void RendererStorageRD::global_variables_clear() {
- global_variables.variables.clear(); //not right but for now enough
-}
-
-RID RendererStorageRD::global_variables_get_storage_buffer() const {
- return global_variables.buffer;
-}
-
-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
- ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
- return pos;
-}
-
-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) {
- global_variables.buffer_usage[pos].elements = 0;
- }
- global_variables.instance_buffer_pos.erase(p_instance);
-}
-
-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
- }
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
-
- if (pos < 0) {
- return; //again, not allocated, ignore
- }
- ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
-
- ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
- ShaderLanguage::TYPE_MAX, //nil
- ShaderLanguage::TYPE_BOOL, //bool
- ShaderLanguage::TYPE_INT, //int
- ShaderLanguage::TYPE_FLOAT, //float
- ShaderLanguage::TYPE_MAX, //string
- ShaderLanguage::TYPE_VEC2, //vec2
- ShaderLanguage::TYPE_IVEC2, //vec2i
- ShaderLanguage::TYPE_VEC4, //rect2
- ShaderLanguage::TYPE_IVEC4, //rect2i
- ShaderLanguage::TYPE_VEC3, // vec3
- ShaderLanguage::TYPE_IVEC3, //vec3i
- ShaderLanguage::TYPE_MAX, //xform2d not supported here
- ShaderLanguage::TYPE_VEC4, //plane
- ShaderLanguage::TYPE_VEC4, //quat
- ShaderLanguage::TYPE_MAX, //aabb not supported here
- ShaderLanguage::TYPE_MAX, //basis not supported here
- ShaderLanguage::TYPE_MAX, //xform not supported here
- ShaderLanguage::TYPE_VEC4 //color
- };
-
- ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
-
- ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
-
- pos += p_index;
-
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
- _global_variable_mark_buffer_dirty(pos, 1);
-}
-
-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) {
- // 25% of regions dirty, just update all buffer
- RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
- } else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
-
- for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
-
- global_variables.buffer_dirty_regions[i] = false;
- }
- }
- }
-
- global_variables.buffer_dirty_region_count = 0;
- }
-
- if (global_variables.must_update_buffer_materials) {
- // only happens in the case of a buffer variable added or removed,
- // so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
- Material *material = material_owner.get_or_null(E);
- ERR_CONTINUE(!material); //wtf
-
- _material_queue_update(material, true, false);
- }
-
- global_variables.must_update_buffer_materials = false;
- }
-
- if (global_variables.must_update_texture_materials) {
- // only happens in the case of a buffer variable added or removed,
- // so not often.
- for (const RID &E : global_variables.materials_using_texture) {
- Material *material = material_owner.get_or_null(E);
- ERR_CONTINUE(!material); //wtf
-
- _material_queue_update(material, false, true);
- }
-
- global_variables.must_update_texture_materials = false;
- }
-}
-
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();
- _update_dirty_skeletons();
- _update_decal_atlas();
+ RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
+ RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
+ RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes();
+ RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons();
+ RendererRD::TextureStorage::get_singleton()->update_decal_atlas();
}
bool RendererStorageRD::has_os_feature(const String &p_feature) const {
+ if (!RD::get_singleton()) {
+ return false;
+ }
+
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;
}
@@ -9258,168 +616,51 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const {
}
bool RendererStorageRD::free(RID p_rid) {
- if (texture_owner.owns(p_rid)) {
- Texture *t = texture_owner.get_or_null(p_rid);
-
- ERR_FAIL_COND_V(!t, false);
- ERR_FAIL_COND_V(t->is_render_target, false);
-
- if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) {
- //erase this first, as it's a dependency of the one below
- RD::get_singleton()->free(t->rd_texture_srgb);
- }
- if (RD::get_singleton()->texture_is_valid(t->rd_texture)) {
- RD::get_singleton()->free(t->rd_texture);
- }
-
- if (t->is_proxy && t->proxy_to.is_valid()) {
- Texture *proxy_to = texture_owner.get_or_null(t->proxy_to);
- if (proxy_to) {
- proxy_to->proxies.erase(p_rid);
- }
- }
-
- if (decal_atlas.textures.has(p_rid)) {
- decal_atlas.textures.erase(p_rid);
- //there is not much a point of making it dirty, just let it be.
- }
-
- for (int i = 0; i < t->proxies.size(); i++) {
- Texture *p = texture_owner.get_or_null(t->proxies[i]);
- ERR_CONTINUE(!p);
- p->proxy_to = RID();
- p->rd_texture = RID();
- p->rd_texture_srgb = RID();
- }
-
- if (t->canvas_texture) {
- memdelete(t->canvas_texture);
- }
- texture_owner.free(p_rid);
-
- } else if (canvas_texture_owner.owns(p_rid)) {
- canvas_texture_owner.free(p_rid);
- } else if (shader_owner.owns(p_rid)) {
- Shader *shader = shader_owner.get_or_null(p_rid);
- //make material unreference this
- while (shader->owners.size()) {
- material_set_shader(shader->owners.front()->get()->self, RID());
- }
- //clear data if exists
- if (shader->data) {
- memdelete(shader->data);
- }
- shader_owner.free(p_rid);
-
- } else if (material_owner.owns(p_rid)) {
- Material *material = material_owner.get_or_null(p_rid);
- material_set_shader(p_rid, RID()); //clean up shader
- material->dependency.deleted_notify(p_rid);
-
- material_owner.free(p_rid);
- } else if (mesh_owner.owns(p_rid)) {
- mesh_clear(p_rid);
- mesh_set_shadow_mesh(p_rid, RID());
- Mesh *mesh = mesh_owner.get_or_null(p_rid);
- mesh->dependency.deleted_notify(p_rid);
- if (mesh->instances.size()) {
- ERR_PRINT("deleting mesh with active instances");
- }
- if (mesh->shadow_owners.size()) {
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
- }
- mesh_owner.free(p_rid);
- } else if (mesh_instance_owner.owns(p_rid)) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
- _mesh_instance_clear(mi);
- mi->mesh->instances.erase(mi->I);
- mi->I = nullptr;
-
- mesh_instance_owner.free(p_rid);
-
- } else if (multimesh_owner.owns(p_rid)) {
- _update_dirty_multimeshes();
- multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
- MultiMesh *multimesh = multimesh_owner.get_or_null(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_data(p_rid, 0);
- Skeleton *skeleton = skeleton_owner.get_or_null(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.get_or_null(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.get_or_null(p_rid);
- for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
- if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) {
- texture_remove_from_decal_atlas(decal->textures[i]);
- }
- }
- decal->dependency.deleted_notify(p_rid);
- decal_owner.free(p_rid);
+ if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->texture_free(p_rid);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->canvas_texture_free(p_rid);
+ } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
+ RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid);
+ } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) {
+ RendererRD::MaterialStorage::get_singleton()->material_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
+ RendererRD::LightStorage::get_singleton()->reflection_probe_free(p_rid);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->decal_free(p_rid);
} else if (voxel_gi_owner.owns(p_rid)) {
voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid);
voxel_gi->dependency.deleted_notify(p_rid);
voxel_gi_owner.free(p_rid);
- } else if (lightmap_owner.owns(p_rid)) {
- lightmap_set_textures(p_rid, RID(), false);
- Lightmap *lightmap = lightmap_owner.get_or_null(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.get_or_null(p_rid);
- light->dependency.deleted_notify(p_rid);
- light_owner.free(p_rid);
-
- } else if (particles_owner.owns(p_rid)) {
- update_particles();
- Particles *particles = particles_owner.get_or_null(p_rid);
- particles->dependency.deleted_notify(p_rid);
- _particles_free_data(particles);
- particles_owner.free(p_rid);
- } else if (particles_collision_owner.owns(p_rid)) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
-
- if (particles_collision->heightfield_texture.is_valid()) {
- RD::get_singleton()->free(particles_collision->heightfield_texture);
- }
- particles_collision->dependency.deleted_notify(p_rid);
- particles_collision_owner.free(p_rid);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
+ RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
+ RendererRD::LightStorage::get_singleton()->light_free(p_rid);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);
} else if (visibility_notifier_owner.owns(p_rid)) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid);
vn->dependency.deleted_notify(p_rid);
visibility_notifier_owner.free(p_rid);
- } else if (particles_collision_instance_owner.owns(p_rid)) {
- particles_collision_instance_owner.free(p_rid);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) {
+ RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);
} else if (fog_volume_owner.owns(p_rid)) {
FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
fog_volume->dependency.deleted_notify(p_rid);
fog_volume_owner.free(p_rid);
- } else if (render_target_owner.owns(p_rid)) {
- RenderTarget *rt = render_target_owner.get_or_null(p_rid);
-
- _clear_render_target(rt);
-
- if (rt->texture.is_valid()) {
- Texture *tex = texture_owner.get_or_null(rt->texture);
- tex->is_render_target = false;
- free(rt->texture);
- }
-
- render_target_owner.free(p_rid);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid);
} else {
return false;
}
@@ -9492,729 +733,17 @@ RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const {
return RenderingDevice::get_singleton()->get_device_type();
}
+String RendererStorageRD::get_video_adapter_api_version() const {
+ return RenderingDevice::get_singleton()->get_device_api_version();
+}
+
RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
RendererStorageRD::RendererStorageRD() {
base_singleton = this;
-
- for (int i = 0; i < SHADER_TYPE_MAX; i++) {
- shader_data_request_func[i] = nullptr;
- }
-
- static_assert(sizeof(GlobalVariables::Value) == 16);
-
- global_variables.buffer_size = GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size");
- global_variables.buffer_size = MAX(4096, global_variables.buffer_size);
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
-
- { //create default textures
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 255);
- pv.set(i * 4 + 1, 255);
- pv.set(i * 4 + 2, 255);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
-
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
-
- //take the chance and initialize decal atlas to something
- decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- decal_atlas.texture_srgb = decal_atlas.texture;
- }
-
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 128);
- pv.set(i * 4 + 1, 128);
- pv.set(i * 4 + 2, 255);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
-
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 255);
- pv.set(i * 4 + 1, 128);
- pv.set(i * 4 + 2, 255);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
-
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 0);
- }
-
- default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv);
-
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 0);
- }
-
- {
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
- { //create default cubemap
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.array_layers = 6;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 0);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- for (int i = 0; i < 6; i++) {
- vpv.push_back(pv);
- }
- default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
- { //create default cubemap array
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.array_layers = 6;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_CUBE;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 0);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- for (int i = 0; i < 6; i++) {
- vpv.push_back(pv);
- }
- default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
- { //create default cubemap white array
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.array_layers = 6;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_CUBE;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 255);
- pv.set(i * 4 + 1, 255);
- pv.set(i * 4 + 2, 255);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- for (int i = 0; i < 6; i++) {
- vpv.push_back(pv);
- }
- default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
- { //create default 3D
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.depth = 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_3D;
-
- Vector<uint8_t> pv;
- pv.resize(64 * 4);
- for (int i = 0; i < 64; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 0);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- for (int i = 0; i < 64; i++) {
- pv.set(i * 4 + 0, 255);
- pv.set(i * 4 + 1, 255);
- pv.set(i * 4 + 2, 255);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
- { //create default array
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.array_layers = 1;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 255);
- pv.set(i * 4 + 1, 255);
- pv.set(i * 4 + 2, 255);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
- //default samplers
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- RD::SamplerState sampler_state;
- switch (i) {
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
-
- } break;
- default: {
- }
- }
- switch (j) {
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- } break;
- default: {
- }
- }
-
- default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
- }
- }
-
- //custom sampler
- sampler_rd_configure_custom(0.0f);
-
- //default rd buffers
- {
- Vector<uint8_t> buffer;
- {
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //normal
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //tangent
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //color
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 1.0;
- fptr[2] = 1.0;
- fptr[3] = 1.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //tex uv 1
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
- { //tex uv 2
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- 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);
- {
- uint8_t *w = buffer.ptrw();
- uint32_t *fptr = (uint32_t *)w;
- fptr[0] = 0;
- fptr[1] = 0;
- fptr[2] = 0;
- fptr[3] = 0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //weights
- 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_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
- }
-
- using_lightmap_array = true; // high end
- if (using_lightmap_array) {
- uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
-
- if (textures_per_stage <= 256) {
- lightmap_textures.resize(32);
- } else {
- lightmap_textures.resize(1024);
- }
-
- for (int i = 0; i < lightmap_textures.size(); i++) {
- lightmap_textures.write[i] = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE];
- }
- }
-
- lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
-
- /* Particles */
-
- {
- // Initialize particles
- Vector<String> particles_modes;
- particles_modes.push_back("");
- particles_shader.shader.initialize(particles_modes, String());
- }
- 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);
-
- {
- ShaderCompiler::DefaultIdentifierActions actions;
-
- actions.renames["COLOR"] = "PARTICLE.color";
- actions.renames["VELOCITY"] = "PARTICLE.velocity";
- //actions.renames["MASS"] = "mass"; ?
- actions.renames["ACTIVE"] = "particle_active";
- actions.renames["RESTART"] = "restart";
- actions.renames["CUSTOM"] = "PARTICLE.custom";
- for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
- String udname = "USERDATA" + itos(i + 1);
- actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
- actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
- }
- actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "frame_history.data[0].time";
- actions.renames["PI"] = _MKSTR(Math_PI);
- actions.renames["TAU"] = _MKSTR(Math_TAU);
- actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["LIFETIME"] = "params.lifetime";
- actions.renames["DELTA"] = "local_delta";
- actions.renames["NUMBER"] = "particle_number";
- actions.renames["INDEX"] = "index";
- //actions.renames["GRAVITY"] = "current_gravity";
- actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
- actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
- actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
- actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
- actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
- actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR";
- actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM";
- actions.renames["RESTART_POSITION"] = "restart_position";
- actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale";
- actions.renames["RESTART_VELOCITY"] = "restart_velocity";
- actions.renames["RESTART_COLOR"] = "restart_color";
- actions.renames["RESTART_CUSTOM"] = "restart_custom";
- actions.renames["emit_subparticle"] = "emit_subparticle";
- actions.renames["COLLIDED"] = "collided";
- actions.renames["COLLISION_NORMAL"] = "collision_normal";
- actions.renames["COLLISION_DEPTH"] = "collision_depth";
- actions.renames["ATTRACTOR_FORCE"] = "attractor_force";
-
- actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
- actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
- actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
- actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
-
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = 3;
- actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
-
- actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
- actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
-
- particles_shader.compiler.initialize(actions);
- }
-
- {
- // default material and shader for particles shader
- particles_shader.default_shader = shader_allocate();
- shader_initialize(particles_shader.default_shader);
- shader_set_code(particles_shader.default_shader, R"(
-// Default particles shader.
-
-shader_type particles;
-
-void process() {
- COLOR = vec4(1.0);
-}
-)");
- particles_shader.default_material = material_allocate();
- material_initialize(particles_shader.default_material);
- material_set_shader(particles_shader.default_material, particles_shader.default_shader);
-
- 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.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 1;
- u.ids.resize(12);
- RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.ids.push_back(global_variables_get_storage_buffer());
- uniforms.push_back(u);
- }
-
- particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
- }
-
- default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
-
- {
- Vector<String> copy_modes;
- for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
- if (i == 0) {
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n");
- copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n");
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n");
- } else {
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n");
- copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
- }
- }
-
- particles_shader.copy_shader.initialize(copy_modes);
-
- particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
-
- for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
- for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
- particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
- }
- }
- }
-
- {
- Vector<String> sdf_modes;
- sdf_modes.push_back("\n#define MODE_LOAD\n");
- sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
- sdf_modes.push_back("\n#define MODE_PROCESS\n");
- sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
- sdf_modes.push_back("\n#define MODE_STORE\n");
- sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
-
- rt_sdf.shader.initialize(sdf_modes);
-
- rt_sdf.shader_version = rt_sdf.shader.version_create();
-
- for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
- 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);
- }
- }
}
RendererStorageRD::~RendererStorageRD() {
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- RD::get_singleton()->free(global_variables.buffer);
-
- //def textures
- for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
- RD::get_singleton()->free(default_rd_textures[i]);
- }
-
- //def samplers
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- RD::get_singleton()->free(default_rd_samplers[i][j]);
- }
- }
-
- //custom samplers
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- if (custom_rd_samplers[i][j].is_valid()) {
- RD::get_singleton()->free(custom_rd_samplers[i][j]);
- }
- }
- }
-
- //def buffers
- for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
- RD::get_singleton()->free(mesh_default_rd_buffers[i]);
- }
-
- 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);
-
- RD::get_singleton()->free(default_rd_storage_buffer);
-
- if (decal_atlas.textures.size()) {
- ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
- }
-
- if (decal_atlas.texture.is_valid()) {
- RD::get_singleton()->free(decal_atlas.texture);
- }
-
if (effects) {
memdelete(effects);
effects = nullptr;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 33a3b8e229..07fae45a26 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -36,28 +36,26 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/effects_rd.h"
-#include "servers/rendering/renderer_rd/shaders/canvas_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_rd/shaders/voxel_gi_sdf.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
+
class RendererStorageRD : public RendererStorage {
public:
static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[1][0];
- p_array[2] = p_mtx.basis.elements[2][0];
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[1][0];
+ p_array[2] = p_mtx.basis.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.basis.elements[0][1];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[2][1];
+ p_array[4] = p_mtx.basis.rows[0][1];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.basis.elements[0][2];
- p_array[9] = p_mtx.basis.elements[1][2];
- p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[8] = p_mtx.basis.rows[0][2];
+ p_array[9] = p_mtx.basis.rows[1][2];
+ p_array[10] = p_mtx.basis.rows[2][2];
p_array[11] = 0;
p_array[12] = p_mtx.origin.x;
p_array[13] = p_mtx.origin.y;
@@ -66,47 +64,47 @@ public:
}
static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.elements[0][0];
- p_array[1] = p_mtx.elements[1][0];
- p_array[2] = p_mtx.elements[2][0];
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.elements[0][1];
- p_array[5] = p_mtx.elements[1][1];
- p_array[6] = p_mtx.elements[2][1];
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.elements[0][2];
- p_array[9] = p_mtx.elements[1][2];
- p_array[10] = p_mtx.elements[2][2];
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.elements[0][0];
- p_array[1] = p_mtx.elements[1][0];
- p_array[2] = p_mtx.elements[2][0];
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.elements[0][1];
- p_array[5] = p_mtx.elements[1][1];
- p_array[6] = p_mtx.elements[2][1];
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.elements[0][2];
- p_array[9] = p_mtx.elements[1][2];
- p_array[10] = p_mtx.elements[2][2];
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[0][1];
- p_array[2] = p_mtx.basis.elements[0][2];
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[0][1];
+ p_array[2] = p_mtx.basis.rows[0][2];
p_array[3] = p_mtx.origin.x;
- p_array[4] = p_mtx.basis.elements[1][0];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[1][2];
+ p_array[4] = p_mtx.basis.rows[1][0];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[1][2];
p_array[7] = p_mtx.origin.y;
- p_array[8] = p_mtx.basis.elements[2][0];
- p_array[9] = p_mtx.basis.elements[2][1];
- p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[8] = p_mtx.basis.rows[2][0];
+ p_array[9] = p_mtx.basis.rows[2][1];
+ p_array[10] = p_mtx.basis.rows[2][2];
p_array[11] = p_mtx.origin.z;
}
@@ -124,849 +122,7 @@ public:
}
}
- enum ShaderType {
- SHADER_TYPE_2D,
- SHADER_TYPE_3D,
- SHADER_TYPE_PARTICLES,
- SHADER_TYPE_SKY,
- SHADER_TYPE_FOG,
- SHADER_TYPE_MAX
- };
-
- struct ShaderData {
- virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
-
- virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_param_texture(const StringName &p_param) const = 0;
- 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() {}
- };
-
- typedef ShaderData *(*ShaderDataRequestFunction)();
-
- struct MaterialData {
- void 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 update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
-
- virtual void set_render_priority(int p_priority) = 0;
- virtual void set_next_pass(RID p_pass) = 0;
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
- virtual ~MaterialData();
-
- //to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void free_parameters_uniform_set(RID p_uniform_set);
-
- private:
- friend class RendererStorageRD;
- RID self;
- List<RID>::Element *global_buffer_E = nullptr;
- List<RID>::Element *global_texture_E = nullptr;
- uint64_t global_textures_pass = 0;
- Map<StringName, uint64_t> used_global_textures;
-
- //internally by update_parameters_uniform_set
- Vector<uint8_t> ubo_data;
- RID uniform_buffer;
- Vector<RID> texture_cache;
- };
- typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
- static void _material_uniform_set_erased(void *p_material);
-
- enum DefaultRDTexture {
- DEFAULT_RD_TEXTURE_WHITE,
- DEFAULT_RD_TEXTURE_BLACK,
- DEFAULT_RD_TEXTURE_NORMAL,
- DEFAULT_RD_TEXTURE_ANISO,
- DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
- DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
- DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
- DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
- DEFAULT_RD_TEXTURE_3D_WHITE,
- DEFAULT_RD_TEXTURE_3D_BLACK,
- DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
- DEFAULT_RD_TEXTURE_2D_UINT,
- DEFAULT_RD_TEXTURE_MAX
- };
-
- enum DefaultRDBuffer {
- DEFAULT_RD_BUFFER_VERTEX,
- DEFAULT_RD_BUFFER_NORMAL,
- DEFAULT_RD_BUFFER_TANGENT,
- 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,
- };
-
private:
- /* CANVAS TEXTURE API (2D) */
-
- struct CanvasTexture {
- RID diffuse;
- RID normal_map;
- RID specular;
- Color specular_color = Color(1, 1, 1, 1);
- float shininess = 1.0;
-
- RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
- RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
- RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
- void clear_sets();
- ~CanvasTexture();
- };
-
- RID_Owner<CanvasTexture, true> canvas_texture_owner;
-
- /* TEXTURE API */
- struct Texture {
- enum Type {
- TYPE_2D,
- TYPE_LAYERED,
- TYPE_3D
- };
-
- Type type;
- RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
-
- RenderingDevice::TextureType rd_type;
- RID rd_texture;
- RID rd_texture_srgb;
- RenderingDevice::DataFormat rd_format;
- RenderingDevice::DataFormat rd_format_srgb;
-
- RD::TextureView rd_view;
-
- Image::Format format;
- Image::Format validated_format;
-
- int width;
- int height;
- int depth;
- int layers;
- int mipmaps;
-
- int height_2d;
- int width_2d;
-
- struct BufferSlice3D {
- Size2i size;
- uint32_t offset = 0;
- uint32_t buffer_size = 0;
- };
- Vector<BufferSlice3D> buffer_slices_3d;
- uint32_t buffer_size_3d = 0;
-
- bool is_render_target;
- bool is_proxy;
-
- Ref<Image> image_cache_2d;
- String path;
-
- RID proxy_to;
- Vector<RID> proxies;
- Set<RID> lightmap_users;
-
- RS::TextureDetectCallback detect_3d_callback = nullptr;
- void *detect_3d_callback_ud = nullptr;
-
- RS::TextureDetectCallback detect_normal_callback = nullptr;
- void *detect_normal_callback_ud = nullptr;
-
- RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
- void *detect_roughness_callback_ud = nullptr;
-
- CanvasTexture *canvas_texture = nullptr;
- };
-
- struct TextureToRDFormat {
- RD::DataFormat format;
- RD::DataFormat format_srgb;
- RD::TextureSwizzle swizzle_r;
- RD::TextureSwizzle swizzle_g;
- RD::TextureSwizzle swizzle_b;
- RD::TextureSwizzle swizzle_a;
- TextureToRDFormat() {
- format = RD::DATA_FORMAT_MAX;
- format_srgb = RD::DATA_FORMAT_MAX;
- swizzle_r = RD::TEXTURE_SWIZZLE_R;
- swizzle_g = RD::TEXTURE_SWIZZLE_G;
- swizzle_b = RD::TEXTURE_SWIZZLE_B;
- swizzle_a = RD::TEXTURE_SWIZZLE_A;
- }
- };
-
- //textures can be created from threads, so this RID_Owner is thread safe
- mutable RID_Owner<Texture, true> texture_owner;
-
- Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
-
- RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
- RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
- RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
- RID default_rd_storage_buffer;
-
- /* DECAL ATLAS */
-
- struct DecalAtlas {
- struct Texture {
- int panorama_to_dp_users;
- int users;
- Rect2 uv_rect;
- };
-
- struct SortItem {
- RID texture;
- Size2i pixel_size;
- Size2i size;
- Point2i pos;
-
- bool operator<(const SortItem &p_item) const {
- //sort larger to smaller
- if (size.height == p_item.size.height) {
- return size.width > p_item.size.width;
- } else {
- return size.height > p_item.size.height;
- }
- }
- };
-
- HashMap<RID, Texture> textures;
- bool dirty = true;
- int mipmaps = 5;
-
- RID texture;
- RID texture_srgb;
- struct MipMap {
- RID fb;
- RID texture;
- Size2i size;
- };
- Vector<MipMap> texture_mipmaps;
-
- Size2i size;
-
- } decal_atlas;
-
- void _update_decal_atlas();
-
- /* SHADER */
-
- struct Material;
-
- struct Shader {
- ShaderData *data;
- String code;
- ShaderType type;
- Map<StringName, Map<int, RID>> default_texture_parameter;
- Set<Material *> owners;
- };
-
- ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Shader, true> shader_owner;
-
- /* Material */
-
- struct Material {
- RID self;
- MaterialData *data = nullptr;
- Shader *shader = nullptr;
- //shortcut to shader data and type
- ShaderType shader_type = SHADER_TYPE_MAX;
- uint32_t shader_id = 0;
- bool uniform_dirty = false;
- bool texture_dirty = false;
- Map<StringName, Variant> params;
- int32_t priority = 0;
- RID next_pass;
- SelfList<Material> update_element;
-
- Dependency dependency;
-
- Material() :
- update_element(this) {}
- };
-
- MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Material, true> material_owner;
-
- SelfList<Material>::List material_update_list;
- void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
- void _update_queued_materials();
-
- /* 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
- // material.
- // There are never that many geometry/material
- // combinations, so a simple array is the most
- // cache-efficient structure.
-
- struct Version {
- uint32_t input_mask = 0;
- RD::VertexFormatID vertex_format = 0;
- RID vertex_array;
- };
-
- SpinLock version_lock; //needed to access versions
- Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
-
- RID index_buffer;
- RID index_array;
- uint32_t index_count = 0;
-
- struct LOD {
- float edge_length = 0.0;
- uint32_t index_count = 0;
- RID index_buffer;
- RID index_array;
- };
-
- LOD *lods = nullptr;
- uint32_t lod_count = 0;
-
- AABB aabb;
-
- Vector<AABB> bone_aabbs;
-
- RID blend_shape_buffer;
-
- RID material;
-
- uint32_t render_index = 0;
- uint64_t render_pass = 0;
-
- uint32_t multimesh_render_index = 0;
- uint64_t multimesh_render_pass = 0;
-
- uint32_t particles_render_index = 0;
- uint64_t particles_render_pass = 0;
-
- RID uniform_set;
- };
-
- uint32_t blend_shape_count = 0;
- RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
-
- Surface **surfaces = nullptr;
- uint32_t surface_count = 0;
-
- Vector<AABB> bone_aabbs;
-
- bool has_bone_weights = false;
-
- AABB aabb;
- AABB custom_aabb;
-
- Vector<RID> material_cache;
-
- List<MeshInstance *> instances;
-
- RID shadow_mesh;
- Set<Mesh *> shadow_owners;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Mesh, true> mesh_owner;
-
- 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_Owner<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];
-
- /* MultiMesh */
- struct MultiMesh {
- RID mesh;
- int instances = 0;
- RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
- bool uses_colors = false;
- bool uses_custom_data = false;
- int visible_instances = -1;
- AABB aabb;
- bool aabb_dirty = false;
- bool buffer_set = false;
- uint32_t stride_cache = 0;
- uint32_t color_offset_cache = 0;
- uint32_t custom_data_offset_cache = 0;
-
- Vector<float> data_cache; //used if individual setting is used
- bool *data_cache_dirty_regions = nullptr;
- uint32_t data_cache_used_dirty_regions = 0;
-
- RID buffer; //storage buffer
- RID uniform_set_3d;
- RID uniform_set_2d;
-
- bool dirty = false;
- MultiMesh *dirty_list = nullptr;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<MultiMesh, true> multimesh_owner;
-
- MultiMesh *multimesh_dirty_list = nullptr;
-
- _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
- _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
- void _update_dirty_multimeshes();
-
- /* PARTICLES */
-
- struct ParticleData {
- float xform[16];
- float velocity[3];
- uint32_t active;
- float color[4];
- float custom[3];
- float lifetime;
- };
-
- struct ParticlesFrameParams {
- enum {
- MAX_ATTRACTORS = 32,
- MAX_COLLIDERS = 32,
- MAX_3D_TEXTURES = 7
- };
-
- enum AttractorType {
- ATTRACTOR_TYPE_SPHERE,
- ATTRACTOR_TYPE_BOX,
- ATTRACTOR_TYPE_VECTOR_FIELD,
- };
-
- struct Attractor {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
-
- uint32_t texture_index; //texture index for vector field
- float strength;
- float attenuation;
- float directionality;
- };
-
- enum CollisionType {
- COLLISION_TYPE_SPHERE,
- COLLISION_TYPE_BOX,
- COLLISION_TYPE_SDF,
- COLLISION_TYPE_HEIGHT_FIELD,
- COLLISION_TYPE_2D_SDF,
-
- };
-
- struct Collider {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
-
- uint32_t texture_index; //texture index for vector field
- real_t scale;
- uint32_t pad[2];
- };
-
- uint32_t emitting;
- float system_phase;
- float prev_system_phase;
- uint32_t cycle;
-
- real_t explosiveness;
- real_t randomness;
- float time;
- float delta;
-
- uint32_t frame;
- uint32_t pad0;
- uint32_t pad1;
- uint32_t pad2;
-
- uint32_t random_seed;
- uint32_t attractor_count;
- uint32_t collider_count;
- float particle_size;
-
- float emission_transform[16];
-
- Attractor attractors[MAX_ATTRACTORS];
- Collider colliders[MAX_COLLIDERS];
- };
-
- struct ParticleEmissionBufferData {
- };
-
- struct ParticleEmissionBuffer {
- struct Data {
- float xform[16];
- float velocity[3];
- uint32_t flags;
- float color[4];
- float custom[4];
- };
-
- int32_t particle_count;
- int32_t particle_max;
- uint32_t pad1;
- uint32_t pad2;
- Data data[1]; //its 2020 and empty arrays are still non standard in C++
- };
-
- struct Particles {
- RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
- bool inactive = true;
- double inactive_time = 0.0;
- bool emitting = false;
- bool one_shot = false;
- int amount = 0;
- double lifetime = 1.0;
- double pre_process_time = 0.0;
- real_t explosiveness = 0.0;
- real_t randomness = 0.0;
- bool restart_request = false;
- AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
- bool use_local_coords = true;
- bool has_collision_cache = false;
-
- bool has_sdf_collision = false;
- Transform2D sdf_collision_transform;
- Rect2 sdf_collision_to_screen;
- RID sdf_collision_texture;
-
- RID process_material;
- uint32_t frame_counter = 0;
- RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
-
- RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
-
- Vector<RID> draw_passes;
- Vector<Transform3D> trail_bind_poses;
- bool trail_bind_poses_dirty = false;
- RID trail_bind_pose_buffer;
- RID trail_bind_pose_uniform_set;
-
- RID particle_buffer;
- RID particle_instance_buffer;
- RID frame_params_buffer;
-
- uint32_t userdata_count = 0;
-
- RID particles_material_uniform_set;
- RID particles_copy_uniform_set;
- RID particles_transforms_buffer_uniform_set;
- RID collision_textures_uniform_set;
-
- RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
- uint32_t collision_3d_textures_used = 0;
- RID collision_heightmap_texture;
-
- RID particles_sort_buffer;
- RID particles_sort_uniform_set;
-
- bool dirty = false;
- Particles *update_list = nullptr;
-
- RID sub_emitter;
-
- double phase = 0.0;
- double prev_phase = 0.0;
- uint64_t prev_ticks = 0;
- uint32_t random_seed = 0;
-
- uint32_t cycle_number = 0;
-
- double speed_scale = 1.0;
-
- int fixed_fps = 30;
- bool interpolate = true;
- bool fractional_delta = false;
- double frame_remainder = 0;
- real_t collision_base_size = 0.01;
-
- bool clear = true;
-
- bool force_sub_emit = false;
-
- Transform3D emission_transform;
-
- Vector<uint8_t> emission_buffer_data;
-
- ParticleEmissionBuffer *emission_buffer = nullptr;
- RID emission_storage_buffer;
-
- Set<RID> collisions;
-
- Dependency dependency;
-
- double trail_length = 1.0;
- bool trails_enabled = false;
- LocalVector<ParticlesFrameParams> frame_history;
- LocalVector<ParticlesFrameParams> trail_params;
-
- Particles() {
- }
- };
-
- void _particles_process(Particles *p_particles, double p_delta);
- void _particles_allocate_emission_buffer(Particles *particles);
- void _particles_free_data(Particles *particles);
- void _particles_update_buffers(Particles *particles);
-
- struct ParticlesShader {
- struct PushConstant {
- float lifetime;
- uint32_t clear;
- uint32_t total_particles;
- uint32_t trail_size;
-
- uint32_t use_fractional_delta;
- uint32_t sub_emitter_mode;
- uint32_t can_emit;
- uint32_t trail_pass;
- };
-
- ParticlesShaderRD shader;
- ShaderCompiler compiler;
-
- RID default_shader;
- RID default_material;
- RID default_shader_rd;
-
- RID base_uniform_set;
-
- struct CopyPushConstant {
- float sort_direction[3];
- uint32_t total_particles;
-
- uint32_t trail_size;
- uint32_t trail_total;
- float frame_delta;
- float frame_remainder;
-
- float align_up[3];
- uint32_t align_mode;
-
- uint32_t order_by_lifetime;
- uint32_t lifetime_split;
- uint32_t lifetime_reverse;
- uint32_t copy_mode_2d;
-
- float inv_emission_transform[16];
- };
-
- enum {
- MAX_USERDATAS = 6
- };
- enum {
- COPY_MODE_FILL_INSTANCES,
- COPY_MODE_FILL_SORT_BUFFER,
- COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
- COPY_MODE_MAX,
- };
-
- ParticlesCopyShaderRD copy_shader;
- RID copy_shader_version;
- RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
-
- LocalVector<float> pose_update_buffer;
-
- } particles_shader;
-
- Particles *particle_update_list = nullptr;
-
- struct ParticlesShaderData : public ShaderData {
- bool valid;
- RID version;
- bool uses_collision = false;
-
- //PipelineCacheRD pipelines[SKY_VERSION_MAX];
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
-
- String path;
- String code;
- Map<StringName, Map<int, RID>> default_texture_params;
-
- RID pipeline;
-
- bool uses_time = false;
-
- bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
- uint32_t userdata_count = 0;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *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 RendererStorageRD::ShaderData *_create_particles_shader_funcs() {
- return base_singleton->_create_particles_shader_func();
- }
-
- struct ParticlesMaterialData : public MaterialData {
- ParticlesShaderData *shader_data = nullptr;
- RID uniform_set;
-
- virtual void set_render_priority(int p_priority) {}
- virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~ParticlesMaterialData();
- };
-
- MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
- return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
- }
-
- void update_particles();
-
- mutable RID_Owner<Particles, true> particles_owner;
-
- /* Particles Collision */
-
- struct ParticlesCollision {
- RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
- uint32_t cull_mask = 0xFFFFFFFF;
- float radius = 1.0;
- Vector3 extents = Vector3(1, 1, 1);
- float attractor_strength = 1.0;
- float attractor_attenuation = 1.0;
- float attractor_directionality = 0.0;
- RID field_texture;
- RID heightfield_texture;
- RID heightfield_fb;
- Size2i heightfield_fb_size;
-
- RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
-
- struct ParticlesCollisionInstance {
- RID collision;
- Transform3D transform;
- bool active = false;
- };
-
- mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
-
/* FOG VOLUMES */
struct FogVolume {
@@ -991,103 +147,6 @@ private:
mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
- /* Skeleton */
-
- struct Skeleton {
- bool use_2d = false;
- int size = 0;
- Vector<float> data;
- RID buffer;
-
- bool dirty = false;
- Skeleton *dirty_list = nullptr;
- Transform2D base_transform_2d;
-
- RID uniform_set_3d;
- RID uniform_set_mi;
-
- uint64_t version = 1;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Skeleton, true> skeleton_owner;
-
- _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
-
- Skeleton *skeleton_dirty_list = nullptr;
-
- void _update_dirty_skeletons();
-
- /* LIGHT */
-
- struct Light {
- RS::LightType type;
- float param[RS::LIGHT_PARAM_MAX];
- Color color = Color(1, 1, 1, 1);
- Color shadow_color;
- RID projector;
- bool shadow = false;
- bool negative = false;
- bool reverse_cull = false;
- RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
- uint32_t max_sdfgi_cascade = 2;
- uint32_t cull_mask = 0xFFFFFFFF;
- RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
- RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- bool directional_blend_splits = false;
- bool directional_sky_only = false;
- uint64_t version = 0;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Light, true> light_owner;
-
- /* REFLECTION PROBE */
-
- struct ReflectionProbe {
- RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
- int resolution = 256;
- float intensity = 1.0;
- RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
- Color ambient_color;
- float ambient_color_energy = 1.0;
- float max_distance = 0;
- Vector3 extents = Vector3(1, 1, 1);
- Vector3 origin_offset;
- bool interior = false;
- bool box_projection = false;
- bool enable_shadows = false;
- uint32_t cull_mask = (1 << 20) - 1;
- float mesh_lod_threshold = 0.01;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
-
- /* DECAL */
-
- struct Decal {
- Vector3 extents = Vector3(1, 1, 1);
- RID textures[RS::DECAL_TEXTURE_MAX];
- float emission_energy = 1.0;
- float albedo_mix = 1.0;
- Color modulate = Color(1, 1, 1, 1);
- uint32_t cull_mask = (1 << 20) - 1;
- float upper_fade = 0.3;
- float lower_fade = 0.3;
- bool distance_fade = false;
- float distance_fade_begin = 10;
- float distance_fade_length = 1;
- float normal_fade = 0.0;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Decal, true> decal_owner;
-
/* VOXEL GI */
struct VoxelGI {
@@ -1124,937 +183,14 @@ private:
mutable RID_Owner<VoxelGI, true> voxel_gi_owner;
- /* REFLECTION PROBE */
-
- struct Lightmap {
- RID light_texture;
- bool uses_spherical_harmonics = false;
- bool interior = false;
- AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
- int32_t array_index = -1; //unassigned
- PackedVector3Array points;
- PackedColorArray point_sh;
- PackedInt32Array tetrahedra;
- PackedInt32Array bsp_tree;
-
- struct BSP {
- static const int32_t EMPTY_LEAF = INT32_MIN;
- float plane[4];
- int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
- };
-
- Dependency dependency;
- };
-
- bool using_lightmap_array; //high end uses this
- /* for high end */
-
- Vector<RID> lightmap_textures;
-
- uint64_t lightmap_array_version = 0;
-
- mutable RID_Owner<Lightmap, true> lightmap_owner;
-
- float lightmap_probe_capture_update_speed = 4;
-
- /* RENDER TARGET */
-
- struct RenderTarget {
- Size2i size;
- uint32_t view_count;
- RID framebuffer;
- RID color;
-
- //used for retrieving from CPU
- RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- Image::Format image_format = Image::FORMAT_L8;
-
- bool flags[RENDER_TARGET_FLAG_MAX];
-
- bool sdf_enabled = false;
-
- RID backbuffer; //used for effects
- RID backbuffer_fb;
- RID backbuffer_mipmap0;
-
- Vector<RID> backbuffer_mipmaps;
-
- RID framebuffer_uniform_set;
- RID backbuffer_uniform_set;
-
- RID sdf_buffer_write;
- RID sdf_buffer_write_fb;
- RID sdf_buffer_process[2];
- RID sdf_buffer_read;
- RID sdf_buffer_process_uniform_sets[2];
- RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
- RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
- Size2i process_size;
-
- //texture generated for this owner (nor RD).
- RID texture;
- bool was_used;
-
- //clear request
- bool clear_requested;
- Color clear_color;
- };
-
- mutable RID_Owner<RenderTarget> render_target_owner;
-
- void _clear_render_target(RenderTarget *rt);
- void _update_render_target(RenderTarget *rt);
- void _create_render_target_backbuffer(RenderTarget *rt);
- void _render_target_allocate_sdf(RenderTarget *rt);
- void _render_target_clear_sdf(RenderTarget *rt);
- Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
-
- struct RenderTargetSDF {
- enum {
- SHADER_LOAD,
- SHADER_LOAD_SHRINK,
- SHADER_PROCESS,
- SHADER_PROCESS_OPTIMIZED,
- SHADER_STORE,
- SHADER_STORE_SHRINK,
- SHADER_MAX
- };
-
- struct PushConstant {
- int32_t size[2];
- int32_t stride;
- int32_t shift;
- int32_t base_size[2];
- int32_t pad[2];
- };
-
- CanvasSdfShaderRD shader;
- RID shader_version;
- RID pipelines[SHADER_MAX];
- } rt_sdf;
-
- /* GLOBAL SHADER VARIABLES */
-
- struct GlobalVariables {
- enum {
- BUFFER_DIRTY_REGION_SIZE = 1024
- };
- struct Variable {
- Set<RID> texture_materials; // materials using this
-
- RS::GlobalVariableType type;
- Variant value;
- Variant override;
- int32_t buffer_index; //for vectors
- int32_t buffer_elements; //for vectors
- };
-
- HashMap<StringName, Variable> variables;
-
- struct Value {
- float x;
- float y;
- float z;
- float w;
- };
-
- struct ValueInt {
- int32_t x;
- int32_t y;
- int32_t z;
- int32_t w;
- };
-
- struct ValueUInt {
- uint32_t x;
- uint32_t y;
- uint32_t z;
- uint32_t w;
- };
-
- struct ValueUsage {
- uint32_t elements = 0;
- };
-
- List<RID> materials_using_buffer;
- List<RID> materials_using_texture;
-
- RID buffer;
- Value *buffer_values;
- ValueUsage *buffer_usage;
- bool *buffer_dirty_regions;
- uint32_t buffer_dirty_region_count = 0;
-
- uint32_t buffer_size;
-
- bool must_update_texture_materials = false;
- bool must_update_buffer_materials = false;
-
- HashMap<RID, int32_t> instance_buffer_pos;
-
- } global_variables;
-
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
-
- void _update_global_variables();
/* EFFECTS */
EffectsRD *effects = nullptr;
public:
- virtual bool can_create_resources_async() const;
-
- /* TEXTURE API */
-
- virtual RID texture_allocate();
-
- virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image);
- virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type);
- virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent
- virtual void texture_proxy_initialize(RID p_texture, RID p_base);
-
- virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate);
-
- virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
- virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data);
- virtual void texture_proxy_update(RID p_texture, RID p_proxy_to);
-
- //these two APIs can be used together or in combination with the others.
- virtual void texture_2d_placeholder_initialize(RID p_texture);
- virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type);
- virtual void texture_3d_placeholder_initialize(RID p_texture);
-
- virtual Ref<Image> texture_2d_get(RID p_texture) const;
- virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const;
- virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const;
-
- virtual void texture_replace(RID p_texture, RID p_by_texture);
- virtual void texture_set_size_override(RID p_texture, int p_width, int p_height);
-
- virtual void texture_set_path(RID p_texture, const String &p_path);
- virtual String texture_get_path(RID p_texture) const;
-
- virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
- virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
- virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata);
-
- virtual void texture_debug_usage(List<RS::TextureInfo> *r_info);
-
- virtual void texture_set_proxy(RID p_proxy, RID p_base);
- virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable);
-
- virtual Size2 texture_size_with_proxy(RID p_proxy);
-
- virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false);
- virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false);
-
- RID decal_atlas_get_texture() const;
- RID decal_atlas_get_texture_srgb() const;
- _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
- if (!t) {
- return Rect2();
- }
-
- return t->uv_rect;
- }
-
//internal usage
- _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
- if (p_texture.is_null()) {
- return RID();
- }
- Texture *tex = texture_owner.get_or_null(p_texture);
-
- if (!tex) {
- return RID();
- }
- return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
- }
-
- _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) {
- if (p_texture.is_null()) {
- return Size2i();
- }
- Texture *tex = texture_owner.get_or_null(p_texture);
-
- if (!tex) {
- return Size2i();
- }
- return Size2i(tex->width_2d, tex->height_2d);
- }
-
- _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
- return default_rd_textures[p_texture];
- }
- _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
- return default_rd_samplers[p_filter][p_repeat];
- }
- _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
- return custom_rd_samplers[p_filter][p_repeat];
- }
-
- void sampler_rd_configure_custom(float mipmap_bias);
-
- void sampler_rd_set_default(float p_mipmap_bias);
-
- /* CANVAS TEXTURE API */
-
- RID canvas_texture_allocate();
- void canvas_texture_initialize(RID p_canvas_texture);
-
- virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture);
- virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess);
-
- virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter);
- virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat);
-
- bool 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);
-
- /* SHADER API */
-
- RID shader_allocate();
- void shader_initialize(RID p_shader);
-
- void shader_set_code(RID p_shader, const String &p_code);
- String shader_get_code(RID p_shader) const;
- void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
-
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
- 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_allocate();
- void material_initialize(RID p_material);
-
- void material_set_shader(RID p_material, RID p_shader);
-
- void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
- Variant material_get_param(RID p_material, const StringName &p_param) const;
-
- void material_set_next_pass(RID p_material, RID p_next_material);
- void material_set_render_priority(RID p_material, int priority);
-
- bool material_is_animated(RID p_material);
- bool material_casts_shadows(RID p_material);
-
- void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
-
- void material_update_dependency(RID p_material, DependencyTracker *p_instance);
-
- 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.get_or_null(p_material);
- return material->shader_id;
- }
-
- _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
- Material *material = material_owner.get_or_null(p_material);
- if (!material || material->shader_type != p_shader_type) {
- return nullptr;
- } else {
- return material->data;
- }
- }
-
- /* MESH API */
-
- RID mesh_allocate();
- void mesh_initialize(RID p_mesh);
-
- 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);
-
- virtual int mesh_get_blend_shape_count(RID p_mesh) const;
-
- virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode);
- virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
-
- virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
- virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
- virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
-
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
-
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const;
-
- virtual int mesh_get_surface_count(RID p_mesh) const;
-
- virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
-
- virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID());
- virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh);
-
- 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.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, nullptr);
- r_surface_count = mesh->surface_count;
- if (r_surface_count == 0) {
- return nullptr;
- }
- 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;
- }
- }
-
- return mesh->material_cache.ptr();
- }
-
- _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, nullptr);
- ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
-
- return mesh->surfaces[p_surface_index];
- }
-
- _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
-
- return mesh->shadow_mesh;
- }
-
- _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
- Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
- return surface->primitive;
- }
-
- _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_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
- return s->index_count ? s->index_count : s->vertex_count;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- int32_t current_lod = -1;
- if (r_index_count) {
- *r_index_count = s->index_count;
- }
- 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_mesh_lod_threshold) {
- break;
- }
- current_lod = i;
- }
- if (current_lod == -1) {
- return 0;
- } else {
- if (r_index_count) {
- *r_index_count = s->lods[current_lod].index_count;
- }
- return current_lod + 1;
- }
- }
-
- _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- if (p_lod == 0) {
- return s->index_array;
- } else {
- return s->lods[p_lod - 1].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();
-
- //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
-
- for (uint32_t i = 0; i < s->version_count; i++) {
- if (s->versions[i].input_mask != p_input_mask) {
- continue;
- }
- //we have this version, hooray
- r_vertex_format = s->versions[i].vertex_format;
- r_vertex_array_rd = s->versions[i].vertex_array;
- s->version_lock.unlock();
- return;
- }
-
- 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->versions[version], s, p_input_mask);
-
- r_vertex_format = s->versions[version].vertex_format;
- r_vertex_array_rd = s->versions[version].vertex_array;
-
- 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.get_or_null(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];
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->render_pass != p_render_pass) {
- (*r_index)++;
- s->render_pass = p_render_pass;
- s->render_index = *r_index;
- }
-
- return s->render_index;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->multimesh_render_pass != p_render_pass) {
- (*r_index)++;
- s->multimesh_render_pass = p_render_pass;
- s->multimesh_render_index = *r_index;
- }
-
- return s->multimesh_render_index;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->particles_render_pass != p_render_pass) {
- (*r_index)++;
- s->particles_render_pass = p_render_pass;
- s->particles_render_index = *r_index;
- }
-
- return s->particles_render_index;
- }
-
- /* MULTIMESH API */
-
- RID multimesh_allocate();
- void multimesh_initialize(RID p_multimesh);
-
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
- int multimesh_get_instance_count(RID p_multimesh) const;
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform);
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
-
- RID multimesh_get_mesh(RID p_multimesh) const;
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
-
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer);
- Vector<float> multimesh_get_buffer(RID p_multimesh) const;
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
- int multimesh_get_visible_instances(RID p_multimesh) const;
-
- AABB multimesh_get_aabb(RID p_multimesh) const;
-
- _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->xform_format;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_colors;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_custom_data;
- }
-
- _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (multimesh->visible_instances >= 0) {
- return multimesh->visible_instances;
- }
- return multimesh->instances;
- }
-
- _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (!multimesh->uniform_set_3d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(multimesh->buffer);
- uniforms.push_back(u);
- multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return multimesh->uniform_set_3d;
- }
-
- _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (!multimesh->uniform_set_2d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(multimesh->buffer);
- uniforms.push_back(u);
- multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return multimesh->uniform_set_2d;
- }
-
- /* SKELETON API */
-
- RID skeleton_allocate();
- void skeleton_initialize(RID p_skeleton);
-
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
- void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
- int skeleton_get_bone_count(RID p_skeleton) const;
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform);
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
- 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.get_or_null(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.get_or_null(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, RID());
- ERR_FAIL_COND_V(skeleton->size == 0, RID());
- if (skeleton->use_2d) {
- return RID();
- }
- if (!skeleton->uniform_set_3d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(skeleton->buffer);
- uniforms.push_back(u);
- skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return skeleton->uniform_set_3d;
- }
- /* Light API */
-
- void _light_initialize(RID p_rid, RS::LightType p_type);
-
- RID directional_light_allocate();
- void directional_light_initialize(RID p_light);
-
- RID omni_light_allocate();
- void omni_light_initialize(RID p_light);
-
- RID spot_light_allocate();
- void spot_light_initialize(RID p_light);
-
- void light_set_color(RID p_light, const Color &p_color);
- void light_set_param(RID p_light, RS::LightParam p_param, float p_value);
- void light_set_shadow(RID p_light, bool p_enabled);
- void light_set_shadow_color(RID p_light, const Color &p_color);
- void light_set_projector(RID p_light, RID p_texture);
- void light_set_negative(RID p_light, bool p_enable);
- void light_set_cull_mask(RID p_light, uint32_t p_mask);
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
- void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode);
- void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade);
-
- void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode);
-
- 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;
-
- RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
- RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
-
- _FORCE_INLINE_ RS::LightType light_get_type(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light->type;
- }
- AABB light_get_aabb(RID p_light) const;
-
- _FORCE_INLINE_ float light_get_param(RID p_light, RS::LightParam p_param) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->param[p_param];
- }
-
- _FORCE_INLINE_ RID light_get_projector(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RID());
-
- return light->projector;
- }
-
- _FORCE_INLINE_ Color light_get_color(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, Color());
-
- return light->color;
- }
-
- _FORCE_INLINE_ Color light_get_shadow_color(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, Color());
-
- return light->shadow_color;
- }
-
- _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->cull_mask;
- }
-
- _FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light->shadow;
- }
-
- _FORCE_INLINE_ bool light_has_projector(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return texture_owner.owns(light->projector);
- }
-
- _FORCE_INLINE_ bool light_is_negative(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light->negative;
- }
-
- _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0.0);
-
- return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
- }
-
- _FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0.0);
-
- return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
- }
-
- RS::LightBakeMode light_get_bake_mode(RID p_light);
- uint32_t light_get_max_sdfgi_cascade(RID p_light);
- uint64_t light_get_version(RID p_light) const;
-
- /* PROBE API */
-
- RID reflection_probe_allocate();
- void reflection_probe_initialize(RID p_reflection_probe);
-
- void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode);
- void reflection_probe_set_intensity(RID p_probe, float p_intensity);
- void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode);
- void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color);
- void reflection_probe_set_ambient_energy(RID p_probe, float p_energy);
- void reflection_probe_set_max_distance(RID p_probe, float p_distance);
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
- 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_mesh_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;
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
- 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_mesh_lod_threshold(RID p_probe) const;
-
- int reflection_probe_get_resolution(RID p_probe) const;
- bool reflection_probe_renders_shadows(RID p_probe) const;
-
- float reflection_probe_get_intensity(RID p_probe) const;
- bool reflection_probe_is_interior(RID p_probe) const;
- bool reflection_probe_is_box_projection(RID p_probe) const;
- RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
- 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, DependencyTracker *p_instance);
- void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
-
- /* DECAL API */
-
- RID decal_allocate();
- void decal_initialize(RID p_decal);
-
- virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents);
- virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture);
- virtual void decal_set_emission_energy(RID p_decal, float p_energy);
- virtual void decal_set_albedo_mix(RID p_decal, float p_mix);
- virtual void decal_set_modulate(RID p_decal, const Color &p_modulate);
- virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers);
- virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length);
- virtual void decal_set_fade(RID p_decal, float p_above, float p_below);
- virtual void decal_set_normal_fade(RID p_decal, float p_fade);
-
- _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->extents;
- }
-
- _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->textures[p_texture];
- }
-
- _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->modulate;
- }
-
- _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->emission_energy;
- }
-
- _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->albedo_mix;
- }
-
- _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->cull_mask;
- }
-
- _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->upper_fade;
- }
-
- _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->lower_fade;
- }
-
- _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->normal_fade;
- }
-
- _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->distance_fade;
- }
-
- _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->distance_fade_begin;
- }
-
- _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->distance_fade_length;
- }
-
- virtual AABB decal_get_aabb(RID p_decal) const;
/* VOXEL GI API */
@@ -2104,187 +240,6 @@ public:
RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
- /* LIGHTMAP CAPTURE */
-
- RID lightmap_allocate();
- void lightmap_initialize(RID p_lightmap);
-
- virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics);
- virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds);
- virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior);
- 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);
- virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const;
- virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const;
- virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const;
- virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const;
- virtual AABB lightmap_get_aabb(RID p_lightmap) const;
- virtual bool lightmap_is_interior(RID p_lightmap) const;
- virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh);
- virtual void lightmap_set_probe_capture_update_speed(float p_speed);
- _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.get_or_null(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.get_or_null(p_lightmap);
- return lm->array_index;
- }
- _FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
- ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- return lm->uses_spherical_harmonics;
- }
- _FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
- ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
- return lightmap_array_version;
- }
-
- _FORCE_INLINE_ int lightmap_array_get_size() const {
- ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
- return lightmap_textures.size();
- }
-
- _FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
- ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
- return lightmap_textures;
- }
-
- /* PARTICLES */
-
- RID particles_allocate();
- void particles_initialize(RID p_particles_collision);
-
- void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode);
- void particles_set_emitting(RID p_particles, bool p_emitting);
- void particles_set_amount(RID p_particles, int p_amount);
- void particles_set_lifetime(RID p_particles, double p_lifetime);
- void particles_set_one_shot(RID p_particles, bool p_one_shot);
- void particles_set_pre_process_time(RID p_particles, double p_time);
- void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio);
- void particles_set_randomness_ratio(RID p_particles, real_t p_ratio);
- void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
- void particles_set_speed_scale(RID p_particles, double p_scale);
- void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
- void particles_set_process_material(RID p_particles, RID p_material);
- RID particles_get_process_material(RID p_particles) const;
-
- void particles_set_fixed_fps(RID p_particles, int p_fps);
- void particles_set_interpolate(RID p_particles, bool p_enable);
- void particles_set_fractional_delta(RID p_particles, bool p_enable);
- void particles_set_collision_base_size(RID p_particles, real_t p_size);
- void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align);
-
- void particles_set_trails(RID p_particles, bool p_enable, double p_length);
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses);
-
- void particles_restart(RID p_particles);
- void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
-
- void particles_set_subemitter(RID p_particles, RID p_subemitter_particles);
-
- void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order);
-
- void particles_set_draw_passes(RID p_particles, int p_count);
- void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh);
-
- void particles_request_process(RID p_particles);
- AABB particles_get_current_aabb(RID p_particles);
- AABB particles_get_aabb(RID p_particles) const;
-
- void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform);
-
- bool particles_get_emitting(RID p_particles);
- int particles_get_draw_passes(RID p_particles) const;
- RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
-
- void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis);
-
- virtual bool particles_is_inactive(RID p_particles) const;
-
- _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
- return particles->mode;
- }
-
- _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- r_trail_divisor = particles->trail_bind_poses.size();
- } else {
- r_trail_divisor = 1;
- }
-
- return particles->amount * r_trail_divisor;
- }
-
- _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- return particles->has_collision_cache;
- }
-
- _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, false);
-
- return particles->use_local_coords;
- }
-
- _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
- if (particles->particles_transforms_buffer_uniform_set.is_null()) {
- _particles_update_buffers(particles);
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(particles->particle_instance_buffer);
- uniforms.push_back(u);
- }
-
- particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return particles->particles_transforms_buffer_uniform_set;
- }
-
- 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);
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
-
- /* PARTICLES COLLISION */
-
- RID particles_collision_allocate();
- void particles_collision_initialize(RID p_particles_collision);
-
- virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type);
- virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask);
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius); //for spheres
- virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents); //for non-spheres
- virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength);
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality);
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve);
- virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture); //for SDF and vector field, heightfield is dynamic
- virtual void particles_collision_height_field_update(RID p_particles_collision); //for SDF and vector field
- virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution); //for SDF and vector field
- virtual AABB particles_collision_get_aabb(RID p_particles_collision) const;
- virtual Vector3 particles_collision_get_extents(RID p_particles_collision) const;
- virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
- RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
-
/* FOG VOLUMES */
virtual RID fog_volume_allocate();
@@ -2308,74 +263,6 @@ public:
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
- //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 Transform3D &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);
- virtual void global_variable_remove(const StringName &p_name);
- virtual Vector<StringName> global_variable_get_list() const;
-
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value);
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value);
- virtual Variant global_variable_get(const StringName &p_name) const;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
-
- virtual void global_variables_load_settings(bool p_load_textures = true);
- virtual void global_variables_clear();
-
- virtual int32_t global_variables_instance_allocate(RID p_instance);
- virtual void global_variables_instance_free(RID p_instance);
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value);
-
- RID global_variables_get_storage_buffer() const;
-
- /* RENDER TARGET API */
-
- RID render_target_create();
- void render_target_set_position(RID p_render_target, int p_x, int p_y);
- void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
- RID render_target_get_texture(RID p_render_target);
- void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
- void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
- bool render_target_was_used(RID p_render_target);
- void render_target_set_as_unused(RID p_render_target);
- void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
- void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
- void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
-
- RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
-
- virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color);
- virtual bool render_target_is_clear_requested(RID p_render_target);
- virtual Color render_target_get_clear_request_color(RID p_render_target);
- virtual void render_target_disable_clear_request(RID p_render_target);
- virtual void render_target_do_clear_request(RID p_render_target);
-
- virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale);
- RID render_target_get_sdf_texture(RID p_render_target);
- RID render_target_get_sdf_framebuffer(RID p_render_target);
- void render_target_sdf_process(RID p_render_target);
- virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const;
- void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled);
- bool render_target_is_sdf_enabled(RID p_render_target) const;
-
- Size2 render_target_get_size(RID p_render_target);
- RID render_target_get_rd_framebuffer(RID p_render_target);
- RID render_target_get_rd_texture(RID p_render_target);
- RID render_target_get_rd_backbuffer(RID p_render_target);
- RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
-
- RID render_target_get_framebuffer_uniform_set(RID p_render_target);
- RID render_target_get_backbuffer_uniform_set(RID p_render_target);
-
- void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
- void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
-
RS::InstanceType get_base_type(RID p_rid) const;
bool free(RID p_rid);
@@ -2397,6 +284,7 @@ public:
String get_video_adapter_name() const;
String get_video_adapter_vendor() const;
RenderingDevice::DeviceType get_video_adapter_type() const;
+ String get_video_adapter_api_version() const;
virtual void capture_timestamps_begin();
virtual void capture_timestamp(const String &p_name);
@@ -2406,8 +294,6 @@ public:
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
virtual String get_captured_timestamp_name(uint32_t p_index) const;
- RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
-
static RendererStorageRD *base_singleton;
void init_effects(bool p_prefer_raster_effects);
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 73766d14d8..04e05380f1 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -382,8 +382,8 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- FileAccessRef f = FileAccess::open(path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
+ if (f.is_null()) {
return false;
}
@@ -445,8 +445,8 @@ void ShaderRD::_save_to_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE);
- ERR_FAIL_COND(!f);
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
+ ERR_FAIL_COND(f.is_null());
f->store_buffer((const uint8_t *)shader_file_header, 4);
f->store_32(cache_file_version); //file version
uint32_t variant_count = variant_defines.size();
@@ -456,8 +456,6 @@ void ShaderRD::_save_to_cache(Version *p_version) {
f->store_32(p_version->variant_data[i].size()); //stage count
f->store_buffer(p_version->variant_data[i].ptr(), p_version->variant_data[i].size());
}
-
- f->close();
}
void ShaderRD::_compile_version(Version *p_version) {
@@ -524,7 +522,7 @@ void ShaderRD::_compile_version(Version *p_version) {
p_version->valid = true;
}
-void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) {
+void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) {
ERR_FAIL_COND(is_compute);
Version *version = version_owner.get_or_null(p_version);
@@ -549,7 +547,7 @@ void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code
}
}
-void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) {
+void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) {
ERR_FAIL_COND(!is_compute);
Version *version = version_owner.get_or_null(p_version);
@@ -652,8 +650,8 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
base_sha256 = hash_build.as_string().sha256_text();
- DirAccessRef d = DirAccess::open(shader_cache_dir);
- ERR_FAIL_COND(!d);
+ Ref<DirAccess> d = DirAccess::open(shader_cache_dir);
+ ERR_FAIL_COND(d.is_null());
if (d->change_dir(name) != OK) {
Error err = d->make_dir(name);
ERR_FAIL_COND(err != OK);
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index 8e57f0d9af..40b10808c2 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -35,7 +35,7 @@
#include "core/string/string_builder.h"
#include "core/templates/hash_map.h"
#include "core/templates/local_vector.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/templates/rid_owner.h"
#include "core/variant/variant.h"
#include "servers/rendering_server.h"
@@ -51,7 +51,7 @@ class ShaderRD {
CharString vertex_globals;
CharString compute_globals;
CharString fragment_globals;
- Map<StringName, CharString> code_sections;
+ HashMap<StringName, CharString> code_sections;
Vector<CharString> custom_defines;
Vector<uint8_t> *variant_data = nullptr;
@@ -129,8 +129,8 @@ protected:
public:
RID version_create();
- void version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines);
- void version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines);
+ void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines);
+ void version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines);
_FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) {
ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID());
diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub
index fc513d3fb9..acb843bfb6 100644
--- a/servers/rendering/renderer_rd/shaders/SCsub
+++ b/servers/rendering/renderer_rd/shaders/SCsub
@@ -15,3 +15,5 @@ if "RD_GLSL" in env["BUILDERS"]:
# compile shaders
for glsl_file in glsl_files:
env.RD_GLSL(glsl_file)
+
+SConscript("effects/SCsub")
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
deleted file mode 100644
index e7a2e18323..0000000000
--- a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
+++ /dev/null
@@ -1,21 +0,0 @@
-#define FLAG_HORIZONTAL (1 << 0)
-#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
-#define FLAG_GLOW_FIRST_PASS (1 << 2)
-
-layout(push_constant, std430) uniform Blur {
- vec2 pixel_size;
- uint flags;
- uint pad;
-
- // Glow.
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
-
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
-}
-blur;
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 65a621b203..f8e9020f9f 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -82,7 +82,7 @@ void main() {
#endif
- mat4 world_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0));
+ mat4 model_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0));
#define FLAGS_INSTANCING_MASK 0x7F
#define FLAGS_INSTANCING_HAS_COLORS (1 << 7)
@@ -156,7 +156,7 @@ void main() {
}
matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
+ model_matrix = model_matrix * matrix;
}
}
@@ -179,7 +179,7 @@ void main() {
#endif
#if !defined(SKIP_TRANSFORM_USED)
- vertex = (world_matrix * vec4(vertex, 0.0, 1.0)).xy;
+ vertex = (model_matrix * vec4(vertex, 0.0, 1.0)).xy;
#endif
color_interp = color;
@@ -461,10 +461,6 @@ float msdf_median(float r, float g, float b, float a) {
return min(max(min(r, g), min(max(r, g), b)), a);
}
-vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) {
- return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min);
-}
-
void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub
new file mode 100644
index 0000000000..fc513d3fb9
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/SCsub
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+Import("env")
+
+if "RD_GLSL" in env["BUILDERS"]:
+ # find all include files
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
+
+ # find all shader code(all glsl files excluding our include files)
+ glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
+
+ # make sure we recompile shaders if include files change
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+
+ # compile shaders
+ for glsl_file in glsl_files:
+ env.RD_GLSL(glsl_file)
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index f8b4e3f610..96f5c3e9f2 100644
--- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -53,7 +53,9 @@ void main() {
#ifdef MODE_GAUSSIAN_BLUR
- //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
+ // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
+
+ // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount.
if (bool(blur.flags & FLAG_HORIZONTAL)) {
vec2 pix_size = blur.pixel_size;
@@ -94,6 +96,7 @@ void main() {
if (bool(blur.flags & FLAG_HORIZONTAL)) {
vec2 pix_size = blur.pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
+
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
GLOW_ADD(vec2(1.0, 0.0), 0.165569);
GLOW_ADD(vec2(2.0, 0.0), 0.140367);
@@ -101,7 +104,10 @@ void main() {
GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
+
+ // only do this in the horizontal pass, if we also do this in the vertical pass we're doubling up.
color *= blur.glow_strength;
+
frag_color = color;
} else {
vec2 pix_size = blur.pixel_size;
@@ -110,13 +116,17 @@ void main() {
GLOW_ADD(vec2(0.0, 2.0), 0.122581);
GLOW_ADD(vec2(0.0, -1.0), 0.233062);
GLOW_ADD(vec2(0.0, -2.0), 0.122581);
- color *= blur.glow_strength;
+
frag_color = color;
}
#undef GLOW_ADD
if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
+ // In the first pass bring back to correct color range else we're applying the wrong threshold
+ // in subsequent passes we can use it as is as we'd just be undoing it right after.
+ frag_color *= blur.luminance_multiplier;
+
#ifdef GLOW_USE_AUTO_EXPOSURE
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
@@ -126,10 +136,10 @@ void main() {
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
- frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
+ frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)) / blur.luminance_multiplier;
}
-#endif
+#endif // MODE_GAUSSIAN_GLOW
#ifdef MODE_COPY
vec4 color = textureLod(source_color, uv_interp, 0.0);
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
new file mode 100644
index 0000000000..730504571a
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
@@ -0,0 +1,26 @@
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
+#define FLAG_GLOW_FIRST_PASS (1 << 2)
+
+layout(push_constant, std430) uniform Blur {
+ vec2 pixel_size; // 08 - 08
+ uint flags; // 04 - 12
+ uint pad; // 04 - 16
+
+ // Glow.
+ float glow_strength; // 04 - 20
+ float glow_bloom; // 04 - 24
+ float glow_hdr_threshold; // 04 - 28
+ float glow_hdr_scale; // 04 - 32
+
+ float glow_exposure; // 04 - 36
+ float glow_white; // 04 - 40
+ float glow_luminance_cap; // 04 - 44
+ float glow_auto_exposure_grey; // 04 - 48
+
+ float luminance_multiplier; // 04 - 52
+ float res1; // 04 - 56
+ float res2; // 04 - 60
+ float res3; // 04 - 64
+}
+blur;
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0438671dd2..0438671dd2 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
index b90a527554..b90a527554 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a3b3938ee9..a3b3938ee9 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
diff --git a/servers/rendering/renderer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index 4563ac7af9..3a4ef86ef0 100644
--- a/servers/rendering/renderer_rd/shaders/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -189,7 +189,7 @@ void main() {
#endif
color *= params.glow_exposure;
- float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114));
+ float luminance = max(color.r, max(color.g, color.b));
float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
color = min(color * feedback, vec4(params.glow_luminance_cap));
diff --git a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 9787c9879d..9787c9879d 100644
--- a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
index 19a9350137..a8ccdea60b 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
@@ -44,7 +44,11 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#ifdef MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2DArray source_glow;
+#else
layout(set = 2, binding = 0) uniform sampler2D source_glow;
+#endif
layout(set = 2, binding = 1) uniform sampler2D glow_map;
#ifdef USE_1D_LUT
@@ -118,6 +122,36 @@ float h1(float a) {
return 1.0f + w3(a) / (w2(a) + w3(a));
}
+#ifdef MULTIVIEW
+vec4 texture2D_bicubic(sampler2DArray tex, vec2 uv, int p_lod) {
+ float lod = float(p_lod);
+ vec2 tex_size = vec2(params.glow_texture_size >> p_lod);
+ vec2 pixel_size = vec2(1.0f) / tex_size;
+
+ uv = uv * tex_size + vec2(0.5f);
+
+ vec2 iuv = floor(uv);
+ vec2 fuv = fract(uv);
+
+ float g0x = g0(fuv.x);
+ float g1x = g1(fuv.x);
+ float h0x = h0(fuv.x);
+ float h1x = h1(fuv.x);
+ float h0y = h0(fuv.y);
+ float h1y = h1(fuv.y);
+
+ vec3 p0 = vec3((vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex);
+ vec3 p1 = vec3((vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex);
+ vec3 p2 = vec3((vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex);
+ vec3 p3 = vec3((vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex);
+
+ return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
+ (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
+}
+
+#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
+#else // MULTIVIEW
+
vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
float lod = float(p_lod);
vec2 tex_size = vec2(params.glow_texture_size >> p_lod);
@@ -145,12 +179,17 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
+#endif // !MULTIVIEW
-#else
+#else // USE_GLOW_FILTER_BICUBIC
+#ifdef MULTIVIEW
+#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, vec3(m_uv, ViewIndex), float(m_lod))
+#else // MULTIVIEW
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
+#endif // !MULTIVIEW
-#endif
+#endif // !USE_GLOW_FILTER_BICUBIC
vec3 tonemap_filmic(vec3 color, float white) {
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
@@ -231,7 +270,11 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
}
}
+#ifdef MULTIVIEW
+vec3 gather_glow(sampler2DArray tex, vec2 uv) { // sample all selected glow levels, view is added to uv later
+#else
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
+#endif // defined(MULTIVIEW)
vec3 glow = vec3(0.0f);
if (params.glow_levels[0] > 0.0001) {
@@ -383,12 +426,13 @@ vec3 screen_space_dither(vec2 frag_coord) {
void main() {
#ifdef SUBPASS
// SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer
- vec3 color = subpassLoad(input_color).rgb * params.luminance_multiplier;
+ vec4 color = subpassLoad(input_color);
#elif defined(MULTIVIEW)
- vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb * params.luminance_multiplier;
+ vec4 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f);
#else
- vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb * params.luminance_multiplier;
+ vec4 color = textureLod(source_color, uv_interp, 0.0f);
#endif
+ color.rgb *= params.luminance_multiplier;
// Exposure
@@ -400,7 +444,7 @@ void main() {
}
#endif
- color *= exposure;
+ color.rgb *= exposure;
// Early Tonemap & SRGB Conversion
#ifndef SUBPASS
@@ -413,19 +457,19 @@ void main() {
}
if (params.use_fxaa) {
- color = do_fxaa(color, exposure, uv_interp);
+ color.rgb = do_fxaa(color.rgb, exposure, uv_interp);
}
#endif
if (params.use_debanding) {
// For best results, debanding should be done before tonemapping.
// Otherwise, we're adding noise to an already-quantized image.
- color += screen_space_dither(gl_FragCoord.xy);
+ color.rgb += screen_space_dither(gl_FragCoord.xy);
}
- color = apply_tonemapping(color, params.white);
+ color.rgb = apply_tonemapping(color.rgb, params.white);
- color = linear_to_srgb(color); // regular linear -> SRGB conversion
+ color.rgb = linear_to_srgb(color.rgb); // regular linear -> SRGB conversion
#ifndef SUBPASS
// Glow
@@ -439,19 +483,19 @@ void main() {
glow = apply_tonemapping(glow, params.white);
glow = linear_to_srgb(glow);
- color = apply_glow(color, glow);
+ color.rgb = apply_glow(color.rgb, glow);
}
#endif
// Additional effects
if (params.use_bcs) {
- color = apply_bcs(color, params.bcs);
+ color.rgb = apply_bcs(color.rgb, params.bcs);
}
if (params.use_color_correction) {
- color = apply_color_correction(color);
+ color.rgb = apply_color_correction(color.rgb);
}
- frag_color = vec4(color, 1.0f);
+ frag_color = color;
}
diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
index 52787bb204..61c8488a05 100644
--- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
@@ -76,10 +76,6 @@ struct DirectionalLightData {
highp mat4 shadow_matrix2;
highp mat4 shadow_matrix3;
highp mat4 shadow_matrix4;
- mediump vec4 shadow_color1;
- mediump vec4 shadow_color2;
- mediump vec4 shadow_color3;
- mediump vec4 shadow_color4;
highp vec2 uv_scale1;
highp vec2 uv_scale2;
highp vec2 uv_scale3;
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 1b1051ecfa..acb62b812e 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -228,6 +228,14 @@ bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom
return true;
}
+vec3 safe_normalize(vec3 direction) {
+ const float EPSILON = 0.001;
+ if (length(direction) < EPSILON) {
+ return vec3(0.0);
+ }
+ return normalize(direction);
+}
+
#GLOBALS
void main() {
@@ -431,7 +439,7 @@ void main() {
switch (FRAME.attractors[i].type) {
case ATTRACTOR_TYPE_SPHERE: {
- dir = normalize(rel_vec);
+ dir = safe_normalize(rel_vec);
float d = length(local_pos) / FRAME.attractors[i].extents.x;
if (d > 1.0) {
continue;
@@ -439,7 +447,7 @@ void main() {
amount = max(0.0, 1.0 - d);
} break;
case ATTRACTOR_TYPE_BOX: {
- dir = normalize(rel_vec);
+ dir = safe_normalize(rel_vec);
vec3 abs_pos = abs(local_pos / FRAME.attractors[i].extents);
float d = max(abs_pos.x, max(abs_pos.y, abs_pos.z));
@@ -455,13 +463,13 @@ void main() {
continue;
}
vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz;
- dir = mat3(FRAME.attractors[i].transform) * normalize(s); //revert direction
+ dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction
amount = length(s);
} break;
}
amount = pow(amount, FRAME.attractors[i].attenuation);
- dir = normalize(mix(dir, FRAME.attractors[i].transform[2].xyz, FRAME.attractors[i].directionality));
+ dir = safe_normalize(mix(dir, FRAME.attractors[i].transform[2].xyz, FRAME.attractors[i].directionality));
attractor_force -= amount * dir * FRAME.attractors[i].strength;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index a8648fc96a..92c4fc3d67 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -83,6 +83,11 @@ layout(location = 5) out vec3 tangent_interp;
layout(location = 6) out vec3 binormal_interp;
#endif
+#ifdef MOTION_VECTORS
+layout(location = 7) out vec4 screen_position;
+layout(location = 8) out vec4 prev_screen_position;
+#endif
+
#ifdef MATERIAL_UNIFORMS_USED
layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
@@ -93,38 +98,39 @@ layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms
#ifdef MODE_DUAL_PARABOLOID
-layout(location = 8) out float dp_clip;
+layout(location = 9) out float dp_clip;
#endif
-layout(location = 9) out flat uint instance_index_interp;
+layout(location = 10) out flat uint instance_index_interp;
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
invariant gl_Position;
#GLOBALS
-void main() {
+void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
- uint instance_index = draw_call.instance_index;
-
- bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
- if (!is_multimesh) {
- instance_index += gl_InstanceIndex;
- }
-
- instance_index_interp = instance_index;
-
- mat4 world_matrix = instances.data[instance_index].transform;
-
- mat3 world_normal_matrix;
+ mat3 model_normal_matrix;
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
- world_normal_matrix = transpose(inverse(mat3(world_matrix)));
+ model_normal_matrix = transpose(inverse(mat3(model_matrix)));
} else {
- world_normal_matrix = mat3(world_matrix);
+ model_normal_matrix = mat3(model_matrix);
}
if (is_multimesh) {
@@ -217,8 +223,8 @@ void main() {
#endif
//transpose
matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
- world_normal_matrix = world_normal_matrix * mat3(matrix);
+ model_matrix = model_matrix * matrix;
+ model_normal_matrix = model_normal_matrix * mat3(matrix);
}
vec3 vertex = vertex_attrib;
@@ -244,29 +250,35 @@ void main() {
vec4 position;
#endif
+#ifdef USE_MULTIVIEW
+ mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
+#else
mat4 projection_matrix = scene_data.projection_matrix;
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+#endif //USE_MULTIVIEW
//using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (world_matrix * vec4(vertex, 1.0)).xyz;
+ vertex = (model_matrix * vec4(vertex, 1.0)).xyz;
#ifdef NORMAL_USED
- normal = world_normal_matrix * normal;
+ normal = model_normal_matrix * normal;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- tangent = world_normal_matrix * tangent;
- binormal = world_normal_matrix * binormal;
+ tangent = model_normal_matrix * tangent;
+ binormal = model_normal_matrix * binormal;
#endif
#endif
float roughness = 1.0;
- mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
- mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
+ mat4 modelview = scene_data.view_matrix * model_matrix;
+ mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix;
{
#CODE : VERTEX
@@ -291,18 +303,23 @@ void main() {
//using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz;
+ vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz;
#ifdef NORMAL_USED
- normal = (scene_data.inv_camera_matrix * vec4(normal, 0.0)).xyz;
+ normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- binormal = (scene_data.inv_camera_matrix * vec4(binormal, 0.0)).xyz;
- tangent = (scene_data.inv_camera_matrix * vec4(tangent, 0.0)).xyz;
+ binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz;
+ tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz;
#endif
#endif
vertex_interp = vertex;
+
+#ifdef MOTION_VECTORS
+ screen_pos = projection_matrix * vec4(vertex_interp, 1.0);
+#endif
+
#ifdef NORMAL_USED
normal_interp = normal;
#endif
@@ -357,6 +374,26 @@ void main() {
#endif
}
+void main() {
+ uint instance_index = draw_call.instance_index;
+
+ bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
+ if (!is_multimesh) {
+ instance_index += gl_InstanceIndex;
+ }
+
+ instance_index_interp = instance_index;
+
+ mat4 model_matrix = instances.data[instance_index].transform;
+#if defined(MOTION_VECTORS)
+ vertex_shader(instance_index, is_multimesh, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
+ vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position);
+#else
+ vec4 screen_position;
+ vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position);
+#endif
+}
+
#[fragment]
#version 450
@@ -413,18 +450,41 @@ layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp;
#endif
+#ifdef MOTION_VECTORS
+layout(location = 7) in vec4 screen_position;
+layout(location = 8) in vec4 prev_screen_position;
+#endif
+
#ifdef MODE_DUAL_PARABOLOID
-layout(location = 8) in float dp_clip;
+layout(location = 9) in float dp_clip;
#endif
-layout(location = 9) in flat uint instance_index_interp;
+layout(location = 10) in flat uint instance_index_interp;
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
//defines to keep compatibility with vertex
-#define world_matrix instances.data[instance_index].transform
+#define model_matrix instances.data[draw_call.instance_index].transform
+#ifdef USE_MULTIVIEW
+#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
+#define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex]
+#else
#define projection_matrix scene_data.projection_matrix
+#define inv_projection_matrix scene_data.inv_projection_matrix
+#endif
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
//both required for transmittance to be enabled
@@ -463,17 +523,21 @@ layout(location = 1) out uvec2 voxel_gi_buffer;
#endif //MODE_RENDER_NORMAL
#else // RENDER DEPTH
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
layout(location = 0) out vec4 frag_color;
-#endif // MODE_MULTIPLE_RENDER_TARGETS
+#endif // MODE_SEPARATE_SPECULAR
#endif // RENDER DEPTH
+#ifdef MOTION_VECTORS
+layout(location = 2) out vec2 motion_vector;
+#endif
+
#include "scene_forward_aa_inc.glsl"
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -492,24 +556,24 @@ layout(location = 0) out vec4 frag_color;
#ifndef MODE_RENDER_DEPTH
vec4 volumetric_fog_process(vec2 screen_uv, float z) {
- vec3 fog_pos = vec3(screen_uv, z * scene_data.volumetric_fog_inv_length);
+ vec3 fog_pos = vec3(screen_uv, z * scene_data_block.data.volumetric_fog_inv_length);
if (fog_pos.z < 0.0) {
return vec4(0.0);
} else if (fog_pos.z < 1.0) {
- fog_pos.z = pow(fog_pos.z, scene_data.volumetric_fog_detail_spread);
+ fog_pos.z = pow(fog_pos.z, scene_data_block.data.volumetric_fog_detail_spread);
}
return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos);
}
vec4 fog_process(vec3 vertex) {
- vec3 fog_color = scene_data.fog_light_color;
+ vec3 fog_color = scene_data_block.data.fog_light_color;
- if (scene_data.fog_aerial_perspective > 0.0) {
+ if (scene_data_block.data.fog_aerial_perspective > 0.0) {
vec3 sky_fog_color = vec3(0.0);
- vec3 cube_view = scene_data.radiance_inverse_xform * vertex;
+ vec3 cube_view = scene_data_block.data.radiance_inverse_xform * vertex;
// mip_level always reads from the second mipmap and higher so the fog is always slightly blurred
- float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
+ float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data_block.data.z_near) / (scene_data_block.data.z_far - scene_data_block.data.z_near));
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod);
@@ -518,29 +582,29 @@ vec4 fog_process(vec3 vertex) {
#else
sky_fog_color = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_view, mip_level * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
- fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective);
+ fog_color = mix(fog_color, sky_fog_color, scene_data_block.data.fog_aerial_perspective);
}
- if (scene_data.fog_sun_scatter > 0.001) {
+ if (scene_data_block.data.fog_sun_scatter > 0.001) {
vec4 sun_scatter = vec4(0.0);
float sun_total = 0.0;
vec3 view = normalize(vertex);
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0);
- fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
+ fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter;
}
}
- float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
+ float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density));
- if (abs(scene_data.fog_height_density) >= 0.0001) {
- float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
+ if (abs(scene_data_block.data.fog_height_density) >= 0.0001) {
+ float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y;
- float y_dist = y - scene_data.fog_height;
+ float y_dist = y - scene_data_block.data.fog_height;
- float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data_block.data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
@@ -565,13 +629,7 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
#endif //!MODE_RENDER DEPTH
-void main() {
-#ifdef MODE_DUAL_PARABOLOID
-
- if (dp_clip > 0.0)
- discard;
-#endif
-
+void fragment_shader(in SceneData scene_data) {
uint instance_index = instance_index_interp;
//lay out everything, whatever is unused is optimized away anyway
@@ -643,7 +701,7 @@ void main() {
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
+ vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size;
float sss_strength = 0.0;
@@ -1007,7 +1065,7 @@ void main() {
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
uint index = instances.data[instance_index].gi_offset;
- vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
+ vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal;
const float c1 = 0.429043;
const float c2 = 0.511664;
const float c3 = 0.743125;
@@ -1061,9 +1119,9 @@ void main() {
if (sc_use_forward_gi && bool(instances.data[instance_index].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;
- vec3 cam_normal = mat3(scene_data.camera_matrix) * normal;
- vec3 cam_reflection = mat3(scene_data.camera_matrix) * reflect(-view, normal);
+ vec3 cam_pos = mat3(scene_data.inv_view_matrix) * vertex;
+ vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normal;
+ vec3 cam_reflection = mat3(scene_data.inv_view_matrix) * reflect(-view, normal);
//apply y-mult
cam_pos.y *= sdfgi.y_mult;
@@ -1443,62 +1501,78 @@ void main() {
} else { //no soft shadows
vec4 pssm_coord;
+ float blur_factor;
+
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 0)
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ blur_factor = 1.0;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
-
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
}
pssm_coord /= pssm_coord.w;
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor, pssm_coord);
if (directional_lights.data[i].blend_splits) {
float pssm_blend;
+ float blur_factor2;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+ blur_factor2 = 1.0;
}
pssm_coord /= pssm_coord.w;
- float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor2, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
}
}
@@ -1803,7 +1877,7 @@ void main() {
vec3(0, -1, 0),
vec3(0, 0, -1));
- vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp);
+ vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normalize(normal_interp);
float closest_dist = -1e20;
@@ -1930,7 +2004,7 @@ void main() {
//restore fog
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
diffuse_buffer = vec4(albedo.rgb, 0.0);
@@ -1948,7 +2022,7 @@ void main() {
diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
-#else //MODE_MULTIPLE_RENDER_TARGETS
+#else //MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
frag_color = vec4(albedo, alpha);
@@ -1960,7 +2034,26 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
-#endif //MODE_MULTIPLE_RENDER_TARGETS
+#endif //MODE_SEPARATE_SPECULAR
#endif //MODE_RENDER_DEPTH
+#ifdef MOTION_VECTORS
+ vec2 position_clip = (screen_position.xy / screen_position.w) - scene_data.taa_jitter;
+ vec2 prev_position_clip = (prev_screen_position.xy / prev_screen_position.w) - scene_data_block.prev_data.taa_jitter;
+
+ vec2 position_uv = position_clip * vec2(0.5, 0.5);
+ vec2 prev_position_uv = prev_position_clip * vec2(0.5, 0.5);
+
+ motion_vector = position_uv - prev_position_uv;
+#endif
+}
+
+void main() {
+#ifdef MODE_DUAL_PARABOLOID
+
+ if (dp_clip > 0.0)
+ discard;
+#endif
+
+ fragment_shader(scene_data_block.data);
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index 3b110aded2..b700e21543 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -2,6 +2,7 @@
#define ROUGHNESS_MAX_LOD 5
#define MAX_VOXEL_GI_INSTANCES 8
+#define MAX_VIEWS 2
#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
@@ -12,6 +13,10 @@
#endif
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
#include "cluster_data_inc.glsl"
#include "decal_data_inc.glsl"
@@ -166,12 +171,15 @@ sdfgi;
/* Set 1: Render Pass (changes per render pass) */
-layout(set = 1, binding = 0, std140) uniform SceneData {
+struct SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
+ mat4 inv_view_matrix;
+ mat4 view_matrix;
- mat4 camera_matrix;
- mat4 inv_camera_matrix;
+ // only used for multiview
+ mat4 projection_matrix_view[MAX_VIEWS];
+ mat4 inv_projection_matrix_view[MAX_VIEWS];
vec2 viewport_size;
vec2 screen_pixel_size;
@@ -241,11 +249,19 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
+ vec2 taa_jitter;
+ uvec2 pad;
+};
+
+layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
+ SceneData data;
+ SceneData prev_data;
}
-scene_data;
+scene_data_block;
struct InstanceData {
mat4 transform;
+ mat4 prev_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)
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 1c9b08b6d3..5a308bbd02 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -1,9 +1,9 @@
// Functions related to lighting
float D_GGX(float cos_theta_m, float alpha) {
- float alpha2 = alpha * alpha;
- float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m;
- return alpha2 / (M_PI * d * d);
+ float a = cos_theta_m * alpha;
+ float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a);
+ return k * k * (1.0 / M_PI);
}
// From Earl Hammon, Jr. "PBR Diffuse Lighting for GGX+Smith Microsurfaces" https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX
@@ -262,7 +262,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float avg = 0.0;
for (uint i = 0; i < sc_directional_soft_shadow_samples; i++) {
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
}
return avg * (1.0 / float(sc_directional_soft_shadow_samples));
@@ -288,7 +288,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float avg = 0.0;
for (uint i = 0; i < sc_soft_shadow_samples; i++) {
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.soft_shadow_kernel[i].xy), depth, 1.0));
}
return avg * (1.0 / float(sc_soft_shadow_samples));
@@ -311,10 +311,10 @@ float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec
}
float avg = 0.0;
- vec2 offset_scale = blur_scale * 2.0 * scene_data.shadow_atlas_pixel_size / uv_rect.zw;
+ vec2 offset_scale = blur_scale * 2.0 * scene_data_block.data.shadow_atlas_pixel_size / uv_rect.zw;
for (uint i = 0; i < sc_soft_shadow_samples; i++) {
- vec2 offset = offset_scale * (disk_rotation * scene_data.soft_shadow_kernel[i].xy);
+ vec2 offset = offset_scale * (disk_rotation * scene_data_block.data.soft_shadow_kernel[i].xy);
vec2 sample_coord = coord + offset;
float sample_coord_length_sqaured = dot(sample_coord, sample_coord);
@@ -351,7 +351,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
}
for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) {
- vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data_block.data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < pssm_coord.z) {
blocker_average += d;
@@ -367,7 +367,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
float s = 0.0;
for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) {
- vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data_block.data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
}
@@ -394,7 +394,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
if (omni_lights.data[idx].shadow_enabled) {
// there is a shadowmap
- vec2 texel_size = scene_data.shadow_atlas_pixel_size;
+ vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
base_uv_rect.xy += texel_size;
base_uv_rect.zw -= texel_size * 2.0;
@@ -438,7 +438,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
bitangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
- vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+ vec2 disk = disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy;
vec3 pos = local_vert + tangent * disk.x + bitangent * disk.y;
@@ -474,7 +474,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
shadow = 0.0;
for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
- vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+ vec2 disk = disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy;
vec3 pos = local_vert + tangent * disk.x + bitangent * disk.y;
pos = normalize(pos);
@@ -579,7 +579,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
splane.xy = splane.xy * 0.5 + 0.5;
splane.z = shadow_len * omni_lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
- // splane.xy = clamp(splane.xy,clamp_rect.xy + scene_data.shadow_atlas_pixel_size,clamp_rect.xy + clamp_rect.zw - scene_data.shadow_atlas_pixel_size );
+ // splane.xy = clamp(splane.xy,clamp_rect.xy + scene_data_block.data.shadow_atlas_pixel_size,clamp_rect.xy + clamp_rect.zw - scene_data_block.data.shadow_atlas_pixel_size );
splane.w = 1.0; //needed? i think it should be 1 already
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
@@ -709,7 +709,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
float uv_size = spot_lights.data[idx].soft_shadow_size * z_norm * spot_lights.data[idx].soft_shadow_scale;
vec2 clamp_max = spot_lights.data[idx].atlas_rect.xy + spot_lights.data[idx].atlas_rect.zw;
for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
- vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
+ vec2 suv = shadow_uv + (disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < splane.z) {
@@ -726,7 +726,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
shadow = 0.0;
for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
- vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
+ vec2 suv = shadow_uv + (disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0));
}
@@ -740,7 +740,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
} else {
//hard shadow
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
- shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
+ shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv);
}
return shadow;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index a1cf1d3c04..e15ebbfc91 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -115,6 +115,8 @@ invariant gl_Position;
#GLOBALS
void main() {
+ SceneData scene_data = scene_data_block.data;
+
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
@@ -122,13 +124,13 @@ void main() {
bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH);
- mat4 world_matrix = draw_call.transform;
+ mat4 model_matrix = draw_call.transform;
- mat3 world_normal_matrix;
+ mat3 model_normal_matrix;
if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
- world_normal_matrix = transpose(inverse(mat3(world_matrix)));
+ model_normal_matrix = transpose(inverse(mat3(model_matrix)));
} else {
- world_normal_matrix = mat3(world_matrix);
+ model_normal_matrix = mat3(model_matrix);
}
if (is_multimesh) {
@@ -221,8 +223,8 @@ void main() {
#endif
//transpose
matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
- world_normal_matrix = world_normal_matrix * mat3(matrix);
+ model_matrix = model_matrix * matrix;
+ model_normal_matrix = model_normal_matrix * mat3(matrix);
}
vec3 vertex = vertex_attrib;
@@ -259,24 +261,24 @@ void main() {
//using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (world_matrix * vec4(vertex, 1.0)).xyz;
+ vertex = (model_matrix * vec4(vertex, 1.0)).xyz;
#ifdef NORMAL_USED
- normal = world_normal_matrix * normal;
+ normal = model_normal_matrix * normal;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- tangent = world_normal_matrix * tangent;
- binormal = world_normal_matrix * binormal;
+ tangent = model_normal_matrix * tangent;
+ binormal = model_normal_matrix * binormal;
#endif
#endif
float roughness = 1.0;
- mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
- mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
+ mat4 modelview = scene_data.view_matrix * model_matrix;
+ mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix;
{
#CODE : VERTEX
@@ -303,14 +305,14 @@ void main() {
//using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz;
+ vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz;
#ifdef NORMAL_USED
- normal = (scene_data.inv_camera_matrix * vec4(normal, 0.0)).xyz;
+ normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- binormal = (scene_data.inv_camera_matrix * vec4(binormal, 0.0)).xyz;
- tangent = (scene_data.inv_camera_matrix * vec4(tangent, 0.0)).xyz;
+ binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz;
+ tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz;
#endif
#endif
@@ -458,7 +460,7 @@ layout(location = 8) highp in float dp_clip;
//defines to keep compatibility with vertex
-#define world_matrix draw_call.transform
+#define model_matrix draw_call.transform
#ifdef USE_MULTIVIEW
#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
#else
@@ -527,13 +529,13 @@ layout(location = 0) out mediump vec4 frag_color;
*/
vec4 fog_process(vec3 vertex) {
- vec3 fog_color = scene_data.fog_light_color;
+ vec3 fog_color = scene_data_block.data.fog_light_color;
- if (scene_data.fog_aerial_perspective > 0.0) {
+ if (scene_data_block.data.fog_aerial_perspective > 0.0) {
vec3 sky_fog_color = vec3(0.0);
- vec3 cube_view = scene_data.radiance_inverse_xform * vertex;
+ vec3 cube_view = scene_data_block.data.radiance_inverse_xform * vertex;
// mip_level always reads from the second mipmap and higher so the fog is always slightly blurred
- float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
+ float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data_block.data.z_near) / (scene_data_block.data.z_far - scene_data_block.data.z_near));
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod);
@@ -542,29 +544,29 @@ vec4 fog_process(vec3 vertex) {
#else
sky_fog_color = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_view, mip_level * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
- fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective);
+ fog_color = mix(fog_color, sky_fog_color, scene_data_block.data.fog_aerial_perspective);
}
- if (scene_data.fog_sun_scatter > 0.001) {
+ if (scene_data_block.data.fog_sun_scatter > 0.001) {
vec4 sun_scatter = vec4(0.0);
float sun_total = 0.0;
vec3 view = normalize(vertex);
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0);
- fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
+ fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter;
}
}
- float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
+ float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density));
- if (abs(scene_data.fog_height_density) >= 0.0001) {
- float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
+ if (abs(scene_data_block.data.fog_height_density) >= 0.0001) {
+ float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y;
- float y_dist = y - scene_data.fog_height;
+ float y_dist = y - scene_data_block.data.fog_height;
- float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data_block.data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
@@ -580,6 +582,7 @@ void main() {
if (dp_clip > 0.0)
discard;
#endif
+ SceneData scene_data = scene_data_block.data;
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
@@ -650,7 +653,7 @@ void main() {
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
+ vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size;
float sss_strength = 0.0;
@@ -924,7 +927,7 @@ void main() {
#endif // !USE_LIGHTMAP
#if defined(CUSTOM_IRRADIANCE_USED)
- ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a);
+ ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
#endif // CUSTOM_IRRADIANCE_USED
#ifdef LIGHT_CLEARCOAT_USED
@@ -967,7 +970,7 @@ void main() {
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;
+ vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal;
const float c1 = 0.429043;
const float c2 = 0.511664;
const float c3 = 0.743125;
@@ -1054,6 +1057,12 @@ void main() {
if (reflection_accum.a > 0.0) {
specular_light = reflection_accum.rgb / reflection_accum.a;
}
+
+#if !defined(USE_LIGHTMAP)
+ if (ambient_accum.a > 0.0) {
+ ambient_light = ambient_accum.rgb / ambient_accum.a;
+ }
+#endif
} //Reflection probes
// finalize ambient light here
@@ -1124,7 +1133,6 @@ void main() {
float depth_z = -vertex.z;
vec4 pssm_coord;
- vec3 shadow_color = vec3(0.0);
vec3 light_dir = directional_lights.data[i].direction;
#define BIAS_FUNC(m_var, m_idx) \
@@ -1150,9 +1158,6 @@ void main() {
} else {
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
-
- shadow_color = directional_lights.data[i].shadow_color1.rgb;
-
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
@@ -1170,8 +1175,6 @@ void main() {
} else {
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
-
- shadow_color = directional_lights.data[i].shadow_color2.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
@@ -1189,9 +1192,6 @@ void main() {
} else {
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
-
- shadow_color = directional_lights.data[i].shadow_color3.rgb;
-
} else {
vec4 v = vec4(vertex, 1.0);
@@ -1209,12 +1209,9 @@ void main() {
} else {
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
-
- shadow_color = directional_lights.data[i].shadow_color4.rgb;
}
if (directional_lights.data[i].blend_splits) {
- vec3 shadow_color_blend = vec3(0.0);
float pssm_blend;
float shadow2;
@@ -1235,7 +1232,6 @@ void main() {
}
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
- shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
@@ -1253,8 +1249,6 @@ void main() {
}
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
-
- shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
@@ -1271,7 +1265,6 @@ void main() {
}
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
- shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
}
@@ -1279,7 +1272,6 @@ void main() {
pssm_blend = sqrt(pssm_blend);
shadow = mix(shadow, shadow2, pssm_blend);
- shadow_color = mix(shadow_color, shadow_color_blend, pssm_blend);
}
shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
@@ -1293,6 +1285,7 @@ void main() {
float depth_z = -vertex.z;
vec4 pssm_coord;
+ float blur_factor;
vec3 light_dir = directional_lights.data[i].direction;
vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
@@ -1308,56 +1301,71 @@ void main() {
BIAS_FUNC(v, 0)
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ blur_factor = 1.0;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
+ ;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
-
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
}
pssm_coord /= pssm_coord.w;
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor, pssm_coord);
if (directional_lights.data[i].blend_splits) {
float pssm_blend;
+ float blur_factor2;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+ blur_factor2 = 1.0;
}
pssm_coord /= pssm_coord.w;
- float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor2, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 7a624c3b95..dd14a15837 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -125,11 +125,11 @@ global_variables;
/* Set 1: Render Pass (changes per render pass) */
-layout(set = 1, binding = 0, std140) uniform SceneData {
+struct SceneData {
highp mat4 projection_matrix;
highp mat4 inv_projection_matrix;
- highp mat4 camera_matrix;
- highp mat4 inv_camera_matrix;
+ highp mat4 inv_view_matrix;
+ highp mat4 view_matrix;
// only used for multiview
highp mat4 projection_matrix_view[MAX_VIEWS];
@@ -189,8 +189,12 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
uint pad1;
uint pad2;
uint pad3;
+};
+
+layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
+ SceneData data;
}
-scene_data;
+scene_data_block;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
index 5bda15236c..b95fad650e 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
@@ -70,8 +70,6 @@ struct Light {
float cos_spot_angle;
float inv_spot_attenuation;
float radius;
-
- vec4 shadow_color;
};
layout(set = 0, binding = 9, std140) buffer restrict readonly Lights {
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index 4ef6a26443..a893a66c94 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -160,7 +160,7 @@ void main() {
}
if (params.has_tangent) {
- blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb;
+ blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
}
blend_total += w;
@@ -174,8 +174,8 @@ void main() {
}
vertex += blend_vertex;
- normal += normalize(normal + blend_normal);
- tangent.rgb += normalize(tangent.rgb + blend_tangent);
+ normal = normalize(normal + blend_normal);
+ tangent.rgb = normalize(tangent.rgb + blend_tangent);
}
if (params.has_skeleton) {
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl
index b258e89c66..5b4594da99 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/sky.glsl
@@ -180,12 +180,11 @@ void main() {
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y;
cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w;
cube_normal = mat3(params.orientation) * cube_normal;
- cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal);
vec2 uv = uv_interp * 0.5 + 0.5;
- vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
+ vec2 panorama_coords = vec2(atan(cube_normal.x, -cube_normal.z), acos(cube_normal.y));
if (panorama_coords.x < 0.0) {
panorama_coords.x += M_PI * 2.0;
@@ -200,13 +199,11 @@ void main() {
vec4 custom_fog = vec4(0.0);
#ifdef USE_CUBEMAP_PASS
- vec3 inverted_cube_normal = cube_normal;
- inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
index ee21d46a74..47c56571f6 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
@@ -1,3 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 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
+// 2021-05-27: clayjohn: convert SSAO to SSIL
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
#[compute]
#version 450
diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
index 8818f8cada..6b6b02739d 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
@@ -15,6 +15,7 @@
// File changes (yyyy-mm-dd)
// 2016-09-07: filip.strugar@intel.com: first commit
// 2020-12-05: clayjohn: convert to Vulkan and Godot
+// 2021-05-27: clayjohn: convert SSAO to SSIL
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[compute]
diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
index fa4309353d..9e86ac0cf0 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
@@ -1,3 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 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
+// 2021-05-27: clayjohn: convert SSAO to SSIL
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
#[compute]
#version 450
diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
new file mode 100644
index 0000000000..a1a77b95aa
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
@@ -0,0 +1,393 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright(c) 2016-2022 Panos Karabelas
+//
+// 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)
+// 2022-05-06: Panos Karabelas: first commit
+// 2020-12-05: Joan Fons: convert to Vulkan and Godot
+///////////////////////////////////////////////////////////////////////////////////
+
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+// Based on Spartan Engine's TAA implementation https://github.com/PanosK92/SpartanEngine/blob/master/Data/shaders/temporal_antialiasing.hlsl
+
+#define USE_SUBGROUPS
+
+#define GROUP_SIZE 8
+#define FLT_MIN 0.00000001
+#define FLT_MAX 32767.0
+#define RPC_9 0.11111111111
+#define RPC_16 0.0625
+
+#ifdef USE_SUBGROUPS
+layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
+#endif
+
+layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D color_buffer;
+layout(set = 0, binding = 1) uniform sampler2D depth_buffer;
+layout(rg16f, set = 0, binding = 2) uniform restrict readonly image2D velocity_buffer;
+layout(rg16f, set = 0, binding = 3) uniform restrict readonly image2D last_velocity_buffer;
+layout(set = 0, binding = 4) uniform sampler2D history_buffer;
+layout(rgba16f, set = 0, binding = 5) uniform restrict writeonly image2D output_buffer;
+
+layout(push_constant, std430) uniform Params {
+ vec2 resolution;
+ float disocclusion_threshold; // 0.1 / max(params.resolution.x, params.resolution.y
+ float disocclusion_scale;
+}
+params;
+
+const ivec2 kOffsets3x3[9] = {
+ ivec2(-1, -1),
+ ivec2(0, -1),
+ ivec2(1, -1),
+ ivec2(-1, 0),
+ ivec2(0, 0),
+ ivec2(1, 0),
+ ivec2(-1, 1),
+ ivec2(0, 1),
+ ivec2(1, 1),
+};
+
+/*------------------------------------------------------------------------------
+ THREAD GROUP SHARED MEMORY (LDS)
+------------------------------------------------------------------------------*/
+
+const int kBorderSize = 1;
+const int kGroupSize = GROUP_SIZE;
+const int kTileDimension = kGroupSize + kBorderSize * 2;
+const int kTileDimension2 = kTileDimension * kTileDimension;
+
+vec3 reinhard(vec3 hdr) {
+ return hdr / (hdr + 1.0);
+}
+vec3 reinhard_inverse(vec3 sdr) {
+ return sdr / (1.0 - sdr);
+}
+
+float get_depth(ivec2 thread_id) {
+ return texelFetch(depth_buffer, thread_id, 0).r;
+}
+
+#ifdef USE_SUBGROUPS
+shared vec3 tile_color[kTileDimension][kTileDimension];
+shared float tile_depth[kTileDimension][kTileDimension];
+
+vec3 load_color(uvec2 group_thread_id) {
+ group_thread_id += kBorderSize;
+ return tile_color[group_thread_id.x][group_thread_id.y];
+}
+
+void store_color(uvec2 group_thread_id, vec3 color) {
+ tile_color[group_thread_id.x][group_thread_id.y] = color;
+}
+
+float load_depth(uvec2 group_thread_id) {
+ group_thread_id += kBorderSize;
+ return tile_depth[group_thread_id.x][group_thread_id.y];
+}
+
+void store_depth(uvec2 group_thread_id, float depth) {
+ tile_depth[group_thread_id.x][group_thread_id.y] = depth;
+}
+
+void store_color_depth(uvec2 group_thread_id, ivec2 thread_id) {
+ // out of bounds clamp
+ thread_id = clamp(thread_id, ivec2(0, 0), ivec2(params.resolution) - ivec2(1, 1));
+
+ store_color(group_thread_id, imageLoad(color_buffer, thread_id).rgb);
+ store_depth(group_thread_id, get_depth(thread_id));
+}
+
+void populate_group_shared_memory(uvec2 group_id, uint group_index) {
+ // Populate group shared memory
+ ivec2 group_top_left = ivec2(group_id) * kGroupSize - kBorderSize;
+ if (group_index < (kTileDimension2 >> 2)) {
+ ivec2 group_thread_id_1 = ivec2(group_index % kTileDimension, group_index / kTileDimension);
+ ivec2 group_thread_id_2 = ivec2((group_index + (kTileDimension2 >> 2)) % kTileDimension, (group_index + (kTileDimension2 >> 2)) / kTileDimension);
+ ivec2 group_thread_id_3 = ivec2((group_index + (kTileDimension2 >> 1)) % kTileDimension, (group_index + (kTileDimension2 >> 1)) / kTileDimension);
+ ivec2 group_thread_id_4 = ivec2((group_index + kTileDimension2 * 3 / 4) % kTileDimension, (group_index + kTileDimension2 * 3 / 4) / kTileDimension);
+
+ store_color_depth(group_thread_id_1, group_top_left + group_thread_id_1);
+ store_color_depth(group_thread_id_2, group_top_left + group_thread_id_2);
+ store_color_depth(group_thread_id_3, group_top_left + group_thread_id_3);
+ store_color_depth(group_thread_id_4, group_top_left + group_thread_id_4);
+ }
+
+ // Wait for group threads to load store data.
+ groupMemoryBarrier();
+ barrier();
+}
+#else
+vec3 load_color(uvec2 screen_pos) {
+ return imageLoad(color_buffer, ivec2(screen_pos)).rgb;
+}
+
+float load_depth(uvec2 screen_pos) {
+ return get_depth(ivec2(screen_pos));
+}
+#endif
+
+/*------------------------------------------------------------------------------
+ VELOCITY
+------------------------------------------------------------------------------*/
+
+void depth_test_min(uvec2 pos, inout float min_depth, inout uvec2 min_pos) {
+ float depth = load_depth(pos);
+
+ if (depth < min_depth) {
+ min_depth = depth;
+ min_pos = pos;
+ }
+}
+
+// Returns velocity with closest depth (3x3 neighborhood)
+void get_closest_pixel_velocity_3x3(in uvec2 group_pos, uvec2 group_top_left, out vec2 velocity) {
+ float min_depth = 1.0;
+ uvec2 min_pos = group_pos;
+
+ depth_test_min(group_pos + kOffsets3x3[0], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[1], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[2], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[3], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[4], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[5], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[6], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[7], min_depth, min_pos);
+ depth_test_min(group_pos + kOffsets3x3[8], min_depth, min_pos);
+
+ // Velocity out
+ velocity = imageLoad(velocity_buffer, ivec2(group_top_left + min_pos)).xy;
+}
+
+/*------------------------------------------------------------------------------
+ HISTORY SAMPLING
+------------------------------------------------------------------------------*/
+
+vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) {
+ // Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
+ // License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae
+
+ // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
+ // down the sample location to get the exact center of our "starting" texel. The starting texel will be at
+ // location [1, 1] in the grid, where [0, 0] is the top left corner.
+ vec2 sample_pos = uv * resolution;
+ vec2 texPos1 = floor(sample_pos - 0.5f) + 0.5f;
+
+ // Compute the fractional offset from our starting texel to our original sample location, which we'll
+ // feed into the Catmull-Rom spline function to get our filter weights.
+ vec2 f = sample_pos - texPos1;
+
+ // Compute the Catmull-Rom weights using the fractional offset that we calculated earlier.
+ // These equations are pre-expanded based on our knowledge of where the texels will be located,
+ // which lets us avoid having to evaluate a piece-wise function.
+ vec2 w0 = f * (-0.5f + f * (1.0f - 0.5f * f));
+ vec2 w1 = 1.0f + f * f * (-2.5f + 1.5f * f);
+ vec2 w2 = f * (0.5f + f * (2.0f - 1.5f * f));
+ vec2 w3 = f * f * (-0.5f + 0.5f * f);
+
+ // Work out weighting factors and sampling offsets that will let us use bilinear filtering to
+ // simultaneously evaluate the middle 2 samples from the 4x4 grid.
+ vec2 w12 = w1 + w2;
+ vec2 offset12 = w2 / (w1 + w2);
+
+ // Compute the final UV coordinates we'll use for sampling the texture
+ vec2 texPos0 = texPos1 - 1.0f;
+ vec2 texPos3 = texPos1 + 2.0f;
+ vec2 texPos12 = texPos1 + offset12;
+
+ texPos0 /= resolution;
+ texPos3 /= resolution;
+ texPos12 /= resolution;
+
+ vec3 result = vec3(0.0f, 0.0f, 0.0f);
+
+ result += textureLod(stex, vec2(texPos0.x, texPos0.y), 0.0).xyz * w0.x * w0.y;
+ result += textureLod(stex, vec2(texPos12.x, texPos0.y), 0.0).xyz * w12.x * w0.y;
+ result += textureLod(stex, vec2(texPos3.x, texPos0.y), 0.0).xyz * w3.x * w0.y;
+
+ result += textureLod(stex, vec2(texPos0.x, texPos12.y), 0.0).xyz * w0.x * w12.y;
+ result += textureLod(stex, vec2(texPos12.x, texPos12.y), 0.0).xyz * w12.x * w12.y;
+ result += textureLod(stex, vec2(texPos3.x, texPos12.y), 0.0).xyz * w3.x * w12.y;
+
+ result += textureLod(stex, vec2(texPos0.x, texPos3.y), 0.0).xyz * w0.x * w3.y;
+ result += textureLod(stex, vec2(texPos12.x, texPos3.y), 0.0).xyz * w12.x * w3.y;
+ result += textureLod(stex, vec2(texPos3.x, texPos3.y), 0.0).xyz * w3.x * w3.y;
+
+ return max(result, 0.0f);
+}
+
+/*------------------------------------------------------------------------------
+ HISTORY CLIPPING
+------------------------------------------------------------------------------*/
+
+// Based on "Temporal Reprojection Anti-Aliasing" - https://github.com/playdeadgames/temporal
+vec3 clip_aabb(vec3 aabb_min, vec3 aabb_max, vec3 p, vec3 q) {
+ vec3 r = q - p;
+ vec3 rmax = (aabb_max - p.xyz);
+ vec3 rmin = (aabb_min - p.xyz);
+
+ if (r.x > rmax.x + FLT_MIN)
+ r *= (rmax.x / r.x);
+ if (r.y > rmax.y + FLT_MIN)
+ r *= (rmax.y / r.y);
+ if (r.z > rmax.z + FLT_MIN)
+ r *= (rmax.z / r.z);
+
+ if (r.x < rmin.x - FLT_MIN)
+ r *= (rmin.x / r.x);
+ if (r.y < rmin.y - FLT_MIN)
+ r *= (rmin.y / r.y);
+ if (r.z < rmin.z - FLT_MIN)
+ r *= (rmin.z / r.z);
+
+ return p + r;
+}
+
+// Clip history to the neighbourhood of the current sample
+vec3 clip_history_3x3(uvec2 group_pos, vec3 color_history, vec2 velocity_closest) {
+ // Sample a 3x3 neighbourhood
+ vec3 s1 = load_color(group_pos + kOffsets3x3[0]);
+ vec3 s2 = load_color(group_pos + kOffsets3x3[1]);
+ vec3 s3 = load_color(group_pos + kOffsets3x3[2]);
+ vec3 s4 = load_color(group_pos + kOffsets3x3[3]);
+ vec3 s5 = load_color(group_pos + kOffsets3x3[4]);
+ vec3 s6 = load_color(group_pos + kOffsets3x3[5]);
+ vec3 s7 = load_color(group_pos + kOffsets3x3[6]);
+ vec3 s8 = load_color(group_pos + kOffsets3x3[7]);
+ vec3 s9 = load_color(group_pos + kOffsets3x3[8]);
+
+ // Compute min and max (with an adaptive box size, which greatly reduces ghosting)
+ vec3 color_avg = (s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9) * RPC_9;
+ vec3 color_avg2 = ((s1 * s1) + (s2 * s2) + (s3 * s3) + (s4 * s4) + (s5 * s5) + (s6 * s6) + (s7 * s7) + (s8 * s8) + (s9 * s9)) * RPC_9;
+ float box_size = mix(0.0f, 2.5f, smoothstep(0.02f, 0.0f, length(velocity_closest)));
+ vec3 dev = sqrt(abs(color_avg2 - (color_avg * color_avg))) * box_size;
+ vec3 color_min = color_avg - dev;
+ vec3 color_max = color_avg + dev;
+
+ // Variance clipping
+ vec3 color = clip_aabb(color_min, color_max, clamp(color_avg, color_min, color_max), color_history);
+
+ // Clamp to prevent NaNs
+ color = clamp(color, FLT_MIN, FLT_MAX);
+
+ return color;
+}
+
+/*------------------------------------------------------------------------------
+ TAA
+------------------------------------------------------------------------------*/
+
+const vec3 lumCoeff = vec3(0.299f, 0.587f, 0.114f);
+
+float luminance(vec3 color) {
+ return max(dot(color, lumCoeff), 0.0001f);
+}
+
+float get_factor_disocclusion(vec2 uv_reprojected, vec2 velocity) {
+ vec2 velocity_previous = imageLoad(last_velocity_buffer, ivec2(uv_reprojected * params.resolution)).xy;
+ vec2 velocity_texels = velocity * params.resolution;
+ vec2 prev_velocity_texels = velocity_previous * params.resolution;
+ float disocclusion = length(prev_velocity_texels - velocity_texels) - params.disocclusion_threshold;
+ return clamp(disocclusion * params.disocclusion_scale, 0.0, 1.0);
+}
+
+vec3 temporal_antialiasing(uvec2 pos_group_top_left, uvec2 pos_group, uvec2 pos_screen, vec2 uv, sampler2D tex_history) {
+ // Get the velocity of the current pixel
+ vec2 velocity = imageLoad(velocity_buffer, ivec2(pos_screen)).xy;
+
+ // Get reprojected uv
+ vec2 uv_reprojected = uv - velocity;
+
+ // Get input color
+ vec3 color_input = load_color(pos_group);
+
+ // Get history color (catmull-rom reduces a lot of the blurring that you get under motion)
+ vec3 color_history = sample_catmull_rom_9(tex_history, uv_reprojected, params.resolution).rgb;
+
+ // Clip history to the neighbourhood of the current sample (fixes a lot of the ghosting).
+ vec2 velocity_closest = vec2(0.0); // This is best done by using the velocity with the closest depth.
+ get_closest_pixel_velocity_3x3(pos_group, pos_group_top_left, velocity_closest);
+ color_history = clip_history_3x3(pos_group, color_history, velocity_closest);
+
+ // Compute blend factor
+ float blend_factor = RPC_16; // We want to be able to accumulate as many jitter samples as we generated, that is, 16.
+ {
+ // If re-projected UV is out of screen, converge to current color immediatel
+ float factor_screen = any(lessThan(uv_reprojected, vec2(0.0))) || any(greaterThan(uv_reprojected, vec2(1.0))) ? 1.0 : 0.0;
+
+ // Increase blend factor when there is disocclusion (fixes a lot of the remaining ghosting).
+ float factor_disocclusion = get_factor_disocclusion(uv_reprojected, velocity);
+
+ // Add to the blend factor
+ blend_factor = clamp(blend_factor + factor_screen + factor_disocclusion, 0.0, 1.0);
+ }
+
+ // Resolve
+ vec3 color_resolved = vec3(0.0);
+ {
+ // Tonemap
+ color_history = reinhard(color_history);
+ color_input = reinhard(color_input);
+
+ // Reduce flickering
+ float lum_color = luminance(color_input);
+ float lum_history = luminance(color_history);
+ float diff = abs(lum_color - lum_history) / max(lum_color, max(lum_history, 1.001));
+ diff = 1.0 - diff;
+ diff = diff * diff;
+ blend_factor = mix(0.0, blend_factor, diff);
+
+ // Lerp/blend
+ color_resolved = mix(color_history, color_input, blend_factor);
+
+ // Inverse tonemap
+ color_resolved = reinhard_inverse(color_resolved);
+ }
+
+ return color_resolved;
+}
+
+void main() {
+#ifdef USE_SUBGROUPS
+ populate_group_shared_memory(gl_WorkGroupID.xy, gl_LocalInvocationIndex);
+#endif
+
+ // Out of bounds check
+ if (any(greaterThanEqual(vec2(gl_GlobalInvocationID.xy), params.resolution))) {
+ return;
+ }
+
+#ifdef USE_SUBGROUPS
+ const uvec2 pos_group = gl_LocalInvocationID.xy;
+ const uvec2 pos_group_top_left = gl_WorkGroupID.xy * kGroupSize - kBorderSize;
+#else
+ const uvec2 pos_group = gl_GlobalInvocationID.xy;
+ const uvec2 pos_group_top_left = uvec2(0, 0);
+#endif
+ const uvec2 pos_screen = gl_GlobalInvocationID.xy;
+ const vec2 uv = (gl_GlobalInvocationID.xy + 0.5f) / params.resolution;
+
+ vec3 result = temporal_antialiasing(pos_group_top_left, pos_group, pos_screen, uv, history_buffer);
+ imageStore(output_buffer, ivec2(gl_GlobalInvocationID.xy), vec4(result, 1.0));
+}
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index a2a4c91894..eee609fb48 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -186,12 +186,31 @@ void main() {
float sdf = -1.0;
if (params.shape == 0) {
- //Ellipsoid
+ // Ellipsoid
// https://www.shadertoy.com/view/tdS3DG
float k0 = length(local_pos.xyz / params.extents);
float k1 = length(local_pos.xyz / (params.extents * params.extents));
sdf = k0 * (k0 - 1.0) / k1;
} else if (params.shape == 1) {
+ // Cone
+ // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
+
+ // Compute the cone angle automatically to fit within the volume's extents.
+ float inv_height = 1.0 / max(0.001, params.extents.y);
+ float radius = 1.0 / max(0.001, (min(params.extents.x, params.extents.z) * 0.5));
+ float hypotenuse = sqrt(radius * radius + inv_height * inv_height);
+ float rsin = radius / hypotenuse;
+ float rcos = inv_height / hypotenuse;
+ vec2 c = vec2(rsin, rcos);
+
+ float q = length(local_pos.xz);
+ sdf = max(dot(c, vec2(q, local_pos.y - params.extents.y)), -params.extents.y - local_pos.y);
+ } else if (params.shape == 2) {
+ // Cylinder
+ // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
+ vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(params.extents.x, params.extents.z), params.extents.y);
+ sdf = min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
+ } else if (params.shape == 3) {
// Box
// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
vec3 q = abs(local_pos.xyz) - params.extents;
@@ -199,7 +218,7 @@ void main() {
}
float cull_mask = 1.0; //used to cull cells that do not contribute
- if (params.shape <= 1) {
+ if (params.shape <= 3) {
#ifndef SDF_USED
cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf);
#endif
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
index 7a0cea421e..347fd13b28 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
@@ -382,7 +382,6 @@ void main() {
float depth_z = -view_pos.z;
vec4 pssm_coord;
- vec3 shadow_color = directional_lights.data[i].shadow_color1.rgb;
vec3 light_dir = directional_lights.data[i].direction;
vec4 v = vec4(view_pos, 1.0);
float z_range;
@@ -413,7 +412,7 @@ void main() {
shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
- shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+ shadow_attenuation = mix(vec3(0.0), vec3(1.0), shadow);
}
total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g);
diff --git a/servers/rendering/renderer_rd/storage_rd/SCsub b/servers/rendering/renderer_rd/storage_rd/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
new file mode 100644
index 0000000000..56a4525b8e
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -0,0 +1,788 @@
+/*************************************************************************/
+/* light_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "light_storage.h"
+#include "core/config/project_settings.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+LightStorage *LightStorage::singleton = nullptr;
+
+LightStorage *LightStorage::get_singleton() {
+ return singleton;
+}
+
+LightStorage::LightStorage() {
+ singleton = this;
+
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+
+ using_lightmap_array = true; // high end
+ if (using_lightmap_array) {
+ uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
+
+ if (textures_per_stage <= 256) {
+ lightmap_textures.resize(32);
+ } else {
+ lightmap_textures.resize(1024);
+ }
+
+ for (int i = 0; i < lightmap_textures.size(); i++) {
+ lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ }
+ }
+
+ lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
+}
+
+LightStorage::~LightStorage() {
+ singleton = nullptr;
+}
+
+/* LIGHT */
+
+void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
+ Light light;
+ light.type = p_type;
+
+ light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
+ light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ 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_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_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
+ light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
+
+ light_owner.initialize_rid(p_light, light);
+}
+
+RID LightStorage::directional_light_allocate() {
+ return light_owner.allocate_rid();
+}
+
+void LightStorage::directional_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
+}
+
+RID LightStorage::omni_light_allocate() {
+ return light_owner.allocate_rid();
+}
+
+void LightStorage::omni_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_OMNI);
+}
+
+RID LightStorage::spot_light_allocate() {
+ return light_owner.allocate_rid();
+}
+
+void LightStorage::spot_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_SPOT);
+}
+
+void LightStorage::light_free(RID p_rid) {
+ light_set_projector(p_rid, RID()); //clear projector
+
+ // delete the texture
+ Light *light = light_owner.get_or_null(p_rid);
+ light->dependency.deleted_notify(p_rid);
+ light_owner.free(p_rid);
+}
+
+void LightStorage::light_set_color(RID p_light, const Color &p_color) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->color = p_color;
+}
+
+void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+ ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
+
+ if (light->param[p_param] == p_value) {
+ return;
+ }
+
+ switch (p_param) {
+ case RS::LIGHT_PARAM_RANGE:
+ case RS::LIGHT_PARAM_SPOT_ANGLE:
+ case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
+ case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
+ case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
+ case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
+ case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+ case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
+ case RS::LIGHT_PARAM_SHADOW_BIAS: {
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ } break;
+ case RS::LIGHT_PARAM_SIZE: {
+ if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
+ //changing from no size to size and the opposite
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ }
+ } break;
+ default: {
+ }
+ }
+
+ light->param[p_param] = p_value;
+}
+
+void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+ light->shadow = p_enabled;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_projector(RID p_light, RID p_texture) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ if (light->projector == p_texture) {
+ return;
+ }
+
+ if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
+ texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
+
+ light->projector = p_texture;
+
+ if (light->type != RS::LIGHT_DIRECTIONAL) {
+ if (light->projector.is_valid()) {
+ texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ }
+}
+
+void LightStorage::light_set_negative(RID p_light, bool p_enable) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->negative = p_enable;
+}
+
+void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->cull_mask = p_mask;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->distance_fade = p_enabled;
+ light->distance_fade_begin = p_begin;
+ light->distance_fade_shadow = p_shadow;
+ light->distance_fade_length = p_length;
+}
+
+void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->reverse_cull = p_enabled;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->bake_mode = p_bake_mode;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->max_sdfgi_cascade = p_cascade;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->omni_shadow_mode = p_mode;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
+
+ return light->omni_shadow_mode;
+}
+
+void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_shadow_mode = p_mode;
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_blend_splits = p_enable;
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, false);
+
+ return light->directional_blend_splits;
+}
+
+void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_sky_mode = p_mode;
+}
+
+RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY);
+
+ return light->directional_sky_mode;
+}
+
+RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+
+ return light->directional_shadow_mode;
+}
+
+uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->max_sdfgi_cascade;
+}
+
+RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
+
+ return light->bake_mode;
+}
+
+uint64_t LightStorage::light_get_version(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->version;
+}
+
+AABB LightStorage::light_get_aabb(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, AABB());
+
+ switch (light->type) {
+ case RS::LIGHT_SPOT: {
+ float len = light->param[RS::LIGHT_PARAM_RANGE];
+ float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+ return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+ };
+ case RS::LIGHT_OMNI: {
+ float r = light->param[RS::LIGHT_PARAM_RANGE];
+ return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
+ };
+ case RS::LIGHT_DIRECTIONAL: {
+ return AABB();
+ };
+ }
+
+ ERR_FAIL_V(AABB());
+}
+
+/* REFLECTION PROBE */
+
+RID LightStorage::reflection_probe_allocate() {
+ return reflection_probe_owner.allocate_rid();
+}
+
+void LightStorage::reflection_probe_initialize(RID p_reflection_probe) {
+ reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
+}
+
+void LightStorage::reflection_probe_free(RID p_rid) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
+ reflection_probe->dependency.deleted_notify(p_rid);
+ reflection_probe_owner.free(p_rid);
+};
+
+void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->update_mode = p_mode;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->intensity = p_intensity;
+}
+
+void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->ambient_mode = p_mode;
+}
+
+void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->ambient_color = p_color;
+}
+
+void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->ambient_color_energy = p_energy;
+}
+
+void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->max_distance = p_distance;
+
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ if (reflection_probe->extents == p_extents) {
+ return;
+ }
+ reflection_probe->extents = p_extents;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->origin_offset = p_offset;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior = p_enable;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->box_projection = p_enable;
+}
+
+void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->enable_shadows = p_enable;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->cull_mask = p_layers;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+ ERR_FAIL_COND(p_resolution < 32);
+
+ reflection_probe->resolution = p_resolution;
+}
+
+void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->mesh_lod_threshold = p_ratio;
+
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, AABB());
+
+ AABB aabb;
+ aabb.position = -reflection_probe->extents;
+ aabb.size = reflection_probe->extents * 2.0;
+
+ return aabb;
+}
+
+RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
+
+ return reflection_probe->update_mode;
+}
+
+uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->cull_mask;
+}
+
+Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->extents;
+}
+
+Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->origin_offset;
+}
+
+bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->enable_shadows;
+}
+
+float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->max_distance;
+}
+
+float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->mesh_lod_threshold;
+}
+
+int LightStorage::reflection_probe_get_resolution(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->resolution;
+}
+
+float LightStorage::reflection_probe_get_intensity(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->intensity;
+}
+
+bool LightStorage::reflection_probe_is_interior(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->interior;
+}
+
+bool LightStorage::reflection_probe_is_box_projection(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->box_projection;
+}
+
+RS::ReflectionProbeAmbientMode LightStorage::reflection_probe_get_ambient_mode(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
+ return reflection_probe->ambient_mode;
+}
+
+Color LightStorage::reflection_probe_get_ambient_color(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Color());
+
+ return reflection_probe->ambient_color;
+}
+float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->ambient_color_energy;
+}
+
+/* LIGHTMAP API */
+
+RID LightStorage::lightmap_allocate() {
+ return lightmap_owner.allocate_rid();
+}
+
+void LightStorage::lightmap_initialize(RID p_lightmap) {
+ lightmap_owner.initialize_rid(p_lightmap, Lightmap());
+}
+
+void LightStorage::lightmap_free(RID p_rid) {
+ lightmap_set_textures(p_rid, RID(), false);
+ Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);
+ lightmap->dependency.deleted_notify(p_rid);
+ lightmap_owner.free(p_rid);
+}
+
+void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ lightmap_array_version++;
+
+ //erase lightmap users
+ if (lm->light_texture.is_valid()) {
+ RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
+ if (t) {
+ t->lightmap_users.erase(p_lightmap);
+ }
+ }
+
+ RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
+ lm->light_texture = p_light;
+ lm->uses_spherical_harmonics = p_uses_spherical_haromics;
+
+ RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ if (!t) {
+ if (using_lightmap_array) {
+ if (lm->array_index >= 0) {
+ lightmap_textures.write[lm->array_index] = default_2d_array;
+ lm->array_index = -1;
+ }
+ }
+
+ return;
+ }
+
+ t->lightmap_users.insert(p_lightmap);
+
+ if (using_lightmap_array) {
+ if (lm->array_index < 0) {
+ //not in array, try to put in array
+ for (int i = 0; i < lightmap_textures.size(); i++) {
+ if (lightmap_textures[i] == default_2d_array) {
+ lm->array_index = i;
+ break;
+ }
+ }
+ }
+ ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly.");
+
+ lightmap_textures.write[lm->array_index] = t->rd_texture;
+ }
+}
+
+void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+ lm->bounds = p_bounds;
+}
+
+void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+ lm->interior = p_interior;
+}
+
+void LightStorage::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.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ if (p_points.size()) {
+ ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());
+ ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
+ ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
+ }
+
+ lm->points = p_points;
+ lm->bsp_tree = p_bsp_tree;
+ lm->point_sh = p_point_sh;
+ lm->tetrahedra = p_tetrahedra;
+}
+
+PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedVector3Array());
+
+ return lm->points;
+}
+
+PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedColorArray());
+ return lm->point_sh;
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedInt32Array());
+ return lm->tetrahedra;
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedInt32Array());
+ return lm->bsp_tree;
+}
+
+void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
+ lightmap_probe_capture_update_speed = p_speed;
+}
+
+void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ for (int i = 0; i < 9; i++) {
+ r_sh[i] = Color(0, 0, 0, 0);
+ }
+
+ if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {
+ return;
+ }
+
+ static_assert(sizeof(Lightmap::BSP) == 24);
+
+ const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();
+ int32_t node = 0;
+ while (node >= 0) {
+ if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);
+#endif
+
+ node = bsp[node].over;
+ } else {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);
+#endif
+ node = bsp[node].under;
+ }
+ }
+
+ if (node == Lightmap::BSP::EMPTY_LEAF) {
+ return; //nothing could be done
+ }
+
+ node = ABS(node) - 1;
+
+ uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
+ Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
+ const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
+ Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
+
+ for (int i = 0; i < 4; i++) {
+ float c = CLAMP(barycentric[i], 0.0, 1.0);
+ for (int j = 0; j < 9; j++) {
+ r_sh[j] += sh_colors[i][j] * c;
+ }
+ }
+}
+
+bool LightStorage::lightmap_is_interior(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, false);
+ return lm->interior;
+}
+
+AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, AABB());
+ return lm->bounds;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
new file mode 100644
index 0000000000..3cc455692d
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -0,0 +1,370 @@
+/*************************************************************************/
+/* light_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIGHT_STORAGE_RD_H
+#define LIGHT_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/storage/light_storage.h"
+
+namespace RendererRD {
+
+/* LIGHT */
+
+struct Light {
+ RS::LightType type;
+ float param[RS::LIGHT_PARAM_MAX];
+ Color color = Color(1, 1, 1, 1);
+ RID projector;
+ bool shadow = false;
+ bool negative = false;
+ bool reverse_cull = false;
+ RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
+ uint32_t max_sdfgi_cascade = 2;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ bool distance_fade = false;
+ real_t distance_fade_begin = 40.0;
+ real_t distance_fade_shadow = 50.0;
+ real_t distance_fade_length = 10.0;
+ RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+ RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+ bool directional_blend_splits = false;
+ RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+ uint64_t version = 0;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* REFLECTION PROBE */
+
+struct ReflectionProbe {
+ RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
+ int resolution = 256;
+ float intensity = 1.0;
+ RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
+ Color ambient_color;
+ float ambient_color_energy = 1.0;
+ float max_distance = 0;
+ Vector3 extents = Vector3(1, 1, 1);
+ Vector3 origin_offset;
+ bool interior = false;
+ bool box_projection = false;
+ bool enable_shadows = false;
+ uint32_t cull_mask = (1 << 20) - 1;
+ float mesh_lod_threshold = 0.01;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* LIGHTMAP */
+
+struct Lightmap {
+ RID light_texture;
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+ AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ int32_t array_index = -1; //unassigned
+ PackedVector3Array points;
+ PackedColorArray point_sh;
+ PackedInt32Array tetrahedra;
+ PackedInt32Array bsp_tree;
+
+ struct BSP {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ float plane[4];
+ int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ };
+
+ RendererStorage::Dependency dependency;
+};
+
+class LightStorage : public RendererLightStorage {
+private:
+ static LightStorage *singleton;
+
+ /* LIGHT */
+ mutable RID_Owner<Light, true> light_owner;
+
+ /* REFLECTION PROBE */
+ mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
+
+ /* LIGHTMAP */
+
+ bool using_lightmap_array;
+ Vector<RID> lightmap_textures;
+ uint64_t lightmap_array_version = 0;
+ float lightmap_probe_capture_update_speed = 4;
+
+ mutable RID_Owner<Lightmap, true> lightmap_owner;
+
+public:
+ static LightStorage *get_singleton();
+
+ LightStorage();
+ virtual ~LightStorage();
+
+ /* LIGHT */
+
+ Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
+ bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
+
+ void _light_initialize(RID p_rid, RS::LightType p_type);
+
+ virtual RID directional_light_allocate() override;
+ virtual void directional_light_initialize(RID p_light) override;
+
+ virtual RID omni_light_allocate() override;
+ virtual void omni_light_initialize(RID p_light) override;
+
+ virtual RID spot_light_allocate() override;
+ virtual void spot_light_initialize(RID p_light) override;
+
+ virtual void light_free(RID p_rid) override;
+
+ virtual void light_set_color(RID p_light, const Color &p_color) override;
+ virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
+ virtual void light_set_shadow(RID p_light, bool p_enabled) override;
+ virtual void light_set_projector(RID p_light, RID p_texture) override;
+ virtual void light_set_negative(RID p_light, bool p_enable) override;
+ virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
+ virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
+ virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+ virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
+ virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
+
+ virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
+
+ virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
+ virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
+ virtual bool light_directional_get_blend_splits(RID p_light) const override;
+ virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
+
+ virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
+ virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
+
+ virtual RS::LightType light_get_type(RID p_light) const override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light->type;
+ }
+ virtual AABB light_get_aabb(RID p_light) const override;
+
+ virtual float light_get_param(RID p_light, RS::LightParam p_param) override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->param[p_param];
+ }
+
+ _FORCE_INLINE_ RID light_get_projector(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RID());
+
+ return light->projector;
+ }
+
+ virtual Color light_get_color(RID p_light) override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, Color());
+
+ return light->color;
+ }
+
+ _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->cull_mask;
+ }
+
+ _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade;
+ }
+
+ _FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade_begin;
+ }
+
+ _FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade_shadow;
+ }
+
+ _FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade_length;
+ }
+
+ virtual bool light_has_shadow(RID p_light) const override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light->shadow;
+ }
+
+ virtual bool light_has_projector(RID p_light) const override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light_owner.owns(light->projector);
+ }
+
+ _FORCE_INLINE_ bool light_is_negative(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light->negative;
+ }
+
+ _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0.0);
+
+ return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
+ }
+
+ _FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0.0);
+
+ return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
+ }
+
+ virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
+ virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
+ virtual uint64_t light_get_version(RID p_light) const override;
+
+ /* REFLECTION PROBE */
+
+ ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
+ bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
+
+ virtual RID reflection_probe_allocate() override;
+ virtual void reflection_probe_initialize(RID p_reflection_probe) override;
+ virtual void reflection_probe_free(RID p_rid) override;
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
+ virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
+ virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
+ virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
+ virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
+
+ int reflection_probe_get_resolution(RID p_probe) const;
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+
+ float reflection_probe_get_intensity(RID p_probe) const;
+ bool reflection_probe_is_interior(RID p_probe) const;
+ bool reflection_probe_is_box_projection(RID p_probe) const;
+ RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
+ Color reflection_probe_get_ambient_color(RID p_probe) const;
+ float reflection_probe_get_ambient_color_energy(RID p_probe) const;
+
+ /* LIGHTMAP */
+
+ Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
+ bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
+
+ virtual RID lightmap_allocate() override;
+ virtual void lightmap_initialize(RID p_lightmap) override;
+ virtual void lightmap_free(RID p_rid) override;
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
+ 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) override;
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const override;
+ virtual bool lightmap_is_interior(RID p_lightmap) const override;
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+
+ virtual float lightmap_get_probe_capture_update_speed() const override {
+ return lightmap_probe_capture_update_speed;
+ }
+ _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(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.get_or_null(p_lightmap);
+ return lm->array_index;
+ }
+ _FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
+ ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ return lm->uses_spherical_harmonics;
+ }
+ _FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+ return lightmap_array_version;
+ }
+
+ _FORCE_INLINE_ int lightmap_array_get_size() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+ return lightmap_textures.size();
+ }
+
+ _FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
+ return lightmap_textures;
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !LIGHT_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
new file mode 100644
index 0000000000..096d371b8d
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -0,0 +1,2646 @@
+/*************************************************************************/
+/* material_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "material_storage.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/io/resource_loader.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+///////////////////////////////////////////////////////////////////////////
+// UBI helper functions
+
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = (r[i] != 0) ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ bool v = value;
+ gui[0] = v ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 2 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v & 1 ? 1 : 0;
+ gui[1] = v & 2 ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 3 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ gui[j + 2] = r[i + 2] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i] ? 1 : 0;
+ gui[i + 1] = r[i + 1] ? 1 : 0;
+ gui[i + 2] = r[i + 2] ? 1 : 0;
+ gui[i + 3] = r[i + 3] ? 1 : 0;
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ gui[3] = (v & 8) ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ float v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ const PackedVector2Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector2 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
+ const PackedColorArray &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ Color color = a[i];
+ if (p_linear_color) {
+ color = color.srgb_to_linear();
+ }
+ gui[j] = color.r;
+ gui[j + 1] = color.g;
+ gui[j + 2] = color.b;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ const PackedVector3Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ gui[j + 2] = a[i].z;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ }
+ } else {
+ if (value.get_type() == Variant::COLOR) {
+ Color v = value;
+
+ if (p_linear_color) {
+ v = v.srgb_to_linear();
+ }
+
+ gui[0] = v.r;
+ gui[1] = v.g;
+ gui[2] = v.b;
+ } else {
+ Vector3 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
+ const PackedColorArray &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ Color color = a[i];
+ if (p_linear_color) {
+ color = color.srgb_to_linear();
+ }
+ gui[j] = color.r;
+ gui[j + 1] = color.g;
+ gui[j + 2] = color.b;
+ gui[j + 3] = color.a;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ gui[j + 3] = 0;
+ }
+ }
+ } else {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i + 3 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ }
+ } else {
+ if (value.get_type() == Variant::COLOR) {
+ Color v = value;
+
+ if (p_linear_color) {
+ v = v.srgb_to_linear();
+ }
+
+ gui[0] = v.r;
+ gui[1] = v.g;
+ gui[2] = v.b;
+ gui[3] = v.a;
+ } else if (value.get_type() == Variant::RECT2) {
+ Rect2 v = value;
+
+ gui[0] = v.position.x;
+ gui[1] = v.position.y;
+ gui[2] = v.size.x;
+ gui[3] = v.size.y;
+ } else if (value.get_type() == Variant::QUATERNION) {
+ Quaternion v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
+ } else {
+ Plane v = value;
+
+ gui[0] = v.normal.x;
+ gui[1] = v.normal.y;
+ gui[2] = v.normal.z;
+ gui[3] = v.d;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
+ if (i + 3 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+
+ gui[j + 4] = a[i + 2];
+ gui[j + 5] = a[i + 3];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ gui[j + 6] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ }
+ } else {
+ Transform2D v = value;
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = v.columns[0][0];
+ gui[1] = v.columns[0][1];
+ gui[2] = 0; // ignored
+ gui[3] = 0; // ignored
+
+ gui[4] = v.columns[1][0];
+ gui[5] = v.columns[1][1];
+ gui[6] = 0; // ignored
+ gui[7] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
+ if (i + 8 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+ gui[j + 2] = a[i + 2];
+
+ gui[j + 4] = a[i + 3];
+ gui[j + 5] = a[i + 4];
+ gui[j + 6] = a[i + 5];
+
+ gui[j + 8] = a[i + 6];
+ gui[j + 9] = a[i + 7];
+ gui[j + 10] = a[i + 8];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ gui[j + 6] = 0;
+
+ gui[j + 8] = 0;
+ gui[j + 9] = 0;
+ gui[j + 10] = 1;
+ }
+ gui[j + 3] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ gui[j + 11] = 0; // ignored
+ }
+ } else {
+ Basis v = value;
+ gui[0] = v.rows[0][0];
+ gui[1] = v.rows[1][0];
+ gui[2] = v.rows[2][0];
+ gui[3] = 0; // ignored
+
+ gui[4] = v.rows[0][1];
+ gui[5] = v.rows[1][1];
+ gui[6] = v.rows[2][1];
+ gui[7] = 0; // ignored
+
+ gui[8] = v.rows[0][2];
+ gui[9] = v.rows[1][2];
+ gui[10] = v.rows[2][2];
+ gui[11] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0; i < p_array_size * 16; i += 16) {
+ if (i + 15 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+
+ gui[i + 4] = a[i + 4];
+ gui[i + 5] = a[i + 5];
+ gui[i + 6] = a[i + 6];
+ gui[i + 7] = a[i + 7];
+
+ gui[i + 8] = a[i + 8];
+ gui[i + 9] = a[i + 9];
+ gui[i + 10] = a[i + 10];
+ gui[i + 11] = a[i + 11];
+
+ gui[i + 12] = a[i + 12];
+ gui[i + 13] = a[i + 13];
+ gui[i + 14] = a[i + 14];
+ gui[i + 15] = a[i + 15];
+ } else {
+ gui[i] = 1;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+
+ gui[i + 4] = 0;
+ gui[i + 5] = 1;
+ gui[i + 6] = 0;
+ gui[i + 7] = 0;
+
+ gui[i + 8] = 0;
+ gui[i + 9] = 0;
+ gui[i + 10] = 1;
+ gui[i + 11] = 0;
+
+ gui[i + 12] = 0;
+ gui[i + 13] = 0;
+ gui[i + 14] = 0;
+ gui[i + 15] = 1;
+ }
+ }
+ } else {
+ Transform3D v = value;
+ gui[0] = v.basis.rows[0][0];
+ gui[1] = v.basis.rows[1][0];
+ gui[2] = v.basis.rows[2][0];
+ gui[3] = 0;
+
+ gui[4] = v.basis.rows[0][1];
+ gui[5] = v.basis.rows[1][1];
+ gui[6] = v.basis.rows[2][1];
+ gui[7] = 0;
+
+ gui[8] = v.basis.rows[0][2];
+ gui[9] = v.basis.rows[1][2];
+ gui[10] = v.basis.rows[2][2];
+ gui[11] = 0;
+
+ gui[12] = v.origin.x;
+ gui[13] = v.origin.y;
+ gui[14] = v.origin.z;
+ gui[15] = 1;
+ }
+ } break;
+ default: {
+ }
+ }
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ uint32_t *gui = (uint32_t *)data;
+ *gui = value[0].boolean ? 1 : 0;
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+ gui[2] = value[2].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+ gui[2] = value[2].boolean ? 1 : 0;
+ gui[3] = value[3].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+ int32_t *gui = (int32_t *)data;
+ gui[0] = value[0].sint;
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].uint;
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].uint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float *gui = reinterpret_cast<float *>(data);
+ gui[0] = value[0].real;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].real;
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = value[0].real;
+ gui[1] = value[1].real;
+ gui[2] = 0;
+ gui[3] = 0;
+ gui[4] = value[2].real;
+ gui[5] = value[3].real;
+ gui[6] = 0;
+ gui[7] = 0;
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ gui[0] = value[0].real;
+ gui[1] = value[1].real;
+ gui[2] = value[2].real;
+ gui[3] = 0;
+ gui[4] = value[3].real;
+ gui[5] = value[4].real;
+ gui[6] = value[5].real;
+ gui[7] = 0;
+ gui[8] = value[6].real;
+ gui[9] = value[7].real;
+ gui[10] = value[8].real;
+ gui[11] = 0;
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ float *gui = reinterpret_cast<float *>(data);
+
+ for (int i = 0; i < 16; i++) {
+ gui[i] = value[i].real;
+ }
+ } break;
+ default: {
+ }
+ }
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL:
+ case ShaderLanguage::TYPE_INT:
+ case ShaderLanguage::TYPE_UINT:
+ case ShaderLanguage::TYPE_FLOAT: {
+ memset(data, 0, 4 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_BVEC2:
+ case ShaderLanguage::TYPE_IVEC2:
+ case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_VEC2: {
+ memset(data, 0, 8 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_BVEC3:
+ case ShaderLanguage::TYPE_IVEC3:
+ case ShaderLanguage::TYPE_UVEC3:
+ case ShaderLanguage::TYPE_VEC3:
+ case ShaderLanguage::TYPE_BVEC4:
+ case ShaderLanguage::TYPE_IVEC4:
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_VEC4: {
+ memset(data, 0, 16 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ memset(data, 0, 32 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ memset(data, 0, 48 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ memset(data, 0, 64 * p_array_size);
+ } break;
+
+ default: {
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialData
+
+void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ bool uses_global_buffer = false;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
+ if (E.value.order < 0) {
+ continue; // texture, does not go here
+ }
+
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue; //instance uniforms don't appear in the buffer
+ }
+
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+ //this is a global variable, get the index to it
+ GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ uint32_t index = 0;
+ if (gv) {
+ index = gv->buffer_index;
+ } else {
+ WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
+ }
+
+ uint32_t offset = p_uniform_offsets[E.value.order];
+ uint32_t *intptr = (uint32_t *)&p_buffer[offset];
+ *intptr = index;
+ uses_global_buffer = true;
+ continue;
+ }
+
+ //regular uniform
+ uint32_t offset = p_uniform_offsets[E.value.order];
+#ifdef DEBUG_ENABLED
+ uint32_t size = 0U;
+ // The following code enforces a 16-byte alignment of uniform arrays.
+ if (E.value.array_size > 0) {
+ size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
+ int m = (16 * E.value.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ } else {
+ size = ShaderLanguage::get_datatype_size(E.value.type);
+ }
+ ERR_CONTINUE(offset + size > p_buffer_size);
+#endif
+ uint8_t *data = &p_buffer[offset];
+ HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(E.key);
+
+ if (V) {
+ //user provided
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data, p_use_linear_color);
+
+ } else if (E.value.default_value.size()) {
+ //default value
+ _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
+ //value=E.value.default_value;
+ } else {
+ //zero because it was not provided
+ if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
+ //colors must be set as black, with alpha as 1.0
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
+ } else {
+ //else just zero it out
+ _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
+ }
+ }
+ }
+
+ if (uses_global_buffer != (global_buffer_E != nullptr)) {
+ if (uses_global_buffer) {
+ global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ } else {
+ material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ global_buffer_E = nullptr;
+ }
+ }
+}
+
+MaterialData::~MaterialData() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ if (global_buffer_E) {
+ //unregister global buffers
+ material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ }
+
+ if (global_texture_E) {
+ //unregister global textures
+
+ for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ //unregister material from those using global textures
+ material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ }
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
+}
+
+void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+#ifdef TOOLS_ENABLED
+ Texture *roughness_detect_texture = nullptr;
+ RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
+ Texture *normal_detect_texture = nullptr;
+#endif
+
+ bool uses_global_textures = false;
+ global_textures_pass++;
+
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const StringName &uniform_name = p_texture_uniforms[i].name;
+ int uniform_array_size = p_texture_uniforms[i].array_size;
+
+ Vector<RID> textures;
+
+ if (p_texture_uniforms[i].global) {
+ uses_global_textures = true;
+
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ if (v) {
+ if (v->buffer_index >= 0) {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
+
+ } else {
+ HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name);
+ if (!E) {
+ E = used_global_textures.insert(uniform_name, global_textures_pass);
+ v->texture_materials.insert(self);
+ } else {
+ E->value = global_textures_pass;
+ }
+
+ textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
+ }
+
+ } else {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
+ }
+ } else {
+ HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name);
+ if (V) {
+ if (V->value.is_array()) {
+ Array array = (Array)V->value;
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < array.size(); j++) {
+ textures.push_back(array[j]);
+ }
+ } else {
+ if (array.size() > 0) {
+ textures.push_back(array[0]);
+ }
+ }
+ } else {
+ textures.push_back(V->value);
+ }
+ }
+
+ if (uniform_array_size > 0) {
+ if (textures.size() < uniform_array_size) {
+ HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name);
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ if (W && W->value.has(j)) {
+ textures.push_back(W->value[j]);
+ } else {
+ textures.push_back(RID());
+ }
+ }
+ }
+ } else if (textures.is_empty()) {
+ HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name);
+ if (W && W->value.has(0)) {
+ textures.push_back(W->value[0]);
+ }
+ }
+ }
+
+ RID rd_texture;
+
+ if (textures.is_empty()) {
+ //check default usage
+ switch (p_texture_uniforms[i].type) {
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER2D: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ default: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ } break;
+ }
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ } break;
+ default: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ } break;
+ }
+ } break;
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER3D: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ } break;
+
+ default: {
+ }
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < uniform_array_size; j++) {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color;
+
+ for (int j = 0; j < textures.size(); j++) {
+ Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
+
+ if (tex) {
+ rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+#ifdef TOOLS_ENABLED
+ if (tex->detect_3d_callback && p_use_linear_color) {
+ tex->detect_3d_callback(tex->detect_3d_callback_ud);
+ }
+ if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
+ normal_detect_texture = tex;
+ }
+ tex->detect_normal_callback(tex->detect_normal_callback_ud);
+ }
+ if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
+ //find the normal texture
+ roughness_detect_texture = tex;
+ roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
+ }
+#endif
+ }
+ if (rd_texture.is_null()) {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ p_textures[k++] = rd_texture;
+ }
+ }
+ }
+ {
+ //for textures no longer used, unregister them
+ List<StringName> to_delete;
+ for (KeyValue<StringName, uint64_t> &E : used_global_textures) {
+ if (E.value != global_textures_pass) {
+ to_delete.push_back(E.key);
+
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ }
+
+ while (to_delete.front()) {
+ used_global_textures.erase(to_delete.front()->get());
+ to_delete.pop_front();
+ }
+ //handle registering/unregistering global textures
+ if (uses_global_textures != (global_texture_E != nullptr)) {
+ if (uses_global_textures) {
+ global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ } else {
+ material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ global_texture_E = nullptr;
+ }
+ }
+ }
+}
+
+void MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+ if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(p_uniform_set);
+ }
+}
+
+bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+ if ((uint32_t)ubo_data.size() != p_ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(p_ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
+ }
+
+ uint32_t tex_uniform_count = 0U;
+ for (int i = 0; i < p_texture_uniforms.size(); i++) {
+ tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
+ }
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+ update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
+ }
+
+ if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return false;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return false;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ if (p_ubo_size) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.append_id(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const int array_size = p_texture_uniforms[i].array_size;
+
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + k;
+ if (array_size > 0) {
+ for (int j = 0; j < array_size; j++) {
+ u.append_id(textures[k++]);
+ }
+ } else {
+ u.append_id(textures[k++]);
+ }
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
+
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialStorage
+
+MaterialStorage *MaterialStorage::singleton = nullptr;
+
+MaterialStorage *MaterialStorage::get_singleton() {
+ return singleton;
+}
+
+MaterialStorage::MaterialStorage() {
+ singleton = this;
+
+ //default samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+
+ //custom sampler
+ sampler_rd_configure_custom(0.0f);
+
+ // buffers
+ { //create index array for copy shaders
+ Vector<uint8_t> pv;
+ pv.resize(6 * 4);
+ {
+ uint8_t *w = pv.ptrw();
+ int *p32 = (int *)w;
+ p32[0] = 0;
+ p32[1] = 1;
+ p32[2] = 2;
+ p32[3] = 0;
+ p32[4] = 2;
+ p32[5] = 3;
+ }
+ quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ quad_index_array = RD::get_singleton()->index_array_create(quad_index_buffer, 0, 6);
+ }
+
+ // Shaders
+ for (int i = 0; i < SHADER_TYPE_MAX; i++) {
+ shader_data_request_func[i] = nullptr;
+ }
+
+ static_assert(sizeof(GlobalVariables::Value) == 16);
+
+ global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
+ memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
+ global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+}
+
+MaterialStorage::~MaterialStorage() {
+ memdelete_arr(global_variables.buffer_values);
+ memdelete_arr(global_variables.buffer_usage);
+ memdelete_arr(global_variables.buffer_dirty_regions);
+ RD::get_singleton()->free(global_variables.buffer);
+
+ // buffers
+
+ RD::get_singleton()->free(quad_index_buffer); //array gets freed as dependency
+
+ //def samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::get_singleton()->free(default_rd_samplers[i][j]);
+ }
+ }
+
+ //custom samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+ }
+ }
+
+ singleton = nullptr;
+}
+
+/* Samplers */
+
+void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+
+ custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+}
+
+/* GLOBAL VARIABLE API */
+
+int32_t MaterialStorage::_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) {
+ bool valid = true;
+ for (uint32_t i = 1; i < p_elements; i++) {
+ if (global_variables.buffer_usage[idx + i].elements > 0) {
+ valid = false;
+ idx += i + global_variables.buffer_usage[idx + i].elements;
+ break;
+ }
+ }
+
+ if (!valid) {
+ continue; //if not valid, idx is in new position
+ }
+
+ return idx;
+ } else {
+ idx += global_variables.buffer_usage[idx].elements;
+ }
+ }
+
+ return -1;
+}
+
+void MaterialStorage::_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];
+ bool b = p_value;
+ bv.x = b ? 1.0 : 0.0;
+ bv.y = 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = (bvec & 8) ? 1.0 : 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_INT: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ int32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC2: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC3: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC4: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2I: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Rect2i v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UINT: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ uint32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC2: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC3: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC4: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_FLOAT: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ float v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector2 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector3 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Plane v = p_value;
+ bv.x = v.normal.x;
+ bv.y = v.normal.y;
+ bv.z = v.normal.z;
+ bv.w = v.d;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_COLOR: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Color v = p_value;
+ bv.x = v.r;
+ bv.y = v.g;
+ bv.z = v.b;
+ bv.w = v.a;
+
+ GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ v = v.srgb_to_linear();
+ bv_linear.x = v.r;
+ bv_linear.y = v.g;
+ bv_linear.z = v.b;
+ bv_linear.w = v.a;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Rect2 v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT2: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Vector<float> m2 = p_value;
+ if (m2.size() < 4) {
+ m2.resize(4);
+ }
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = m2[2];
+ bv[1].y = m2[3];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT3: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Basis v = p_value;
+ bv[0].x = v.rows[0][0];
+ bv[0].y = v.rows[1][0];
+ bv[0].z = v.rows[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.rows[0][1];
+ bv[1].y = v.rows[1][1];
+ bv[1].z = v.rows[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.rows[0][2];
+ bv[2].y = v.rows[1][2];
+ bv[2].z = v.rows[2][2];
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT4: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+
+ Vector<float> m2 = p_value;
+ if (m2.size() < 16) {
+ m2.resize(16);
+ }
+
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = m2[2];
+ bv[0].w = m2[3];
+
+ bv[1].x = m2[4];
+ bv[1].y = m2[5];
+ bv[1].z = m2[6];
+ bv[1].w = m2[7];
+
+ bv[2].x = m2[8];
+ bv[2].y = m2[9];
+ bv[2].z = m2[10];
+ bv[2].w = m2[11];
+
+ bv[3].x = m2[12];
+ bv[3].y = m2[13];
+ bv[3].z = m2[14];
+ bv[3].w = m2[15];
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform2D v = p_value;
+ bv[0].x = v.columns[0][0];
+ bv[0].y = v.columns[0][1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = v.columns[1][0];
+ bv[1].y = v.columns[1][1];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ bv[2].x = v.columns[2][0];
+ bv[2].y = v.columns[2][1];
+ bv[2].z = 1;
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform3D v = p_value;
+ bv[0].x = v.basis.rows[0][0];
+ bv[0].y = v.basis.rows[1][0];
+ bv[0].z = v.basis.rows[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.basis.rows[0][1];
+ bv[1].y = v.basis.rows[1][1];
+ bv[1].z = v.basis.rows[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.basis.rows[0][2];
+ bv[2].y = v.basis.rows[1][2];
+ bv[2].z = v.basis.rows[2][2];
+ bv[2].w = 0;
+
+ bv[3].x = v.origin.x;
+ bv[3].y = v.origin.y;
+ bv[3].z = v.origin.z;
+ bv[3].w = 1;
+
+ } break;
+ default: {
+ ERR_FAIL();
+ }
+ }
+}
+
+void MaterialStorage::_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++) {
+ int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (chunk != prev_chunk) {
+ if (!global_variables.buffer_dirty_regions[chunk]) {
+ global_variables.buffer_dirty_regions[chunk] = true;
+ global_variables.buffer_dirty_region_count++;
+ }
+ }
+
+ prev_chunk = chunk;
+ }
+}
+
+void MaterialStorage::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;
+ gv.value = p_value;
+ gv.buffer_index = -1;
+
+ if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //is texture
+ global_variables.must_update_texture_materials = true; //normally there are none
+ } else {
+ gv.buffer_elements = 1;
+ if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 2;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 3;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 4;
+ }
+
+ //is vector, allocate in buffer and update index
+ gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
+ global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+
+ global_variables.must_update_buffer_materials = true; //normally there are none
+ }
+
+ global_variables.variables[p_name] = gv;
+}
+
+void MaterialStorage::global_variable_remove(const StringName &p_name) {
+ if (!global_variables.variables.has(p_name)) {
+ return;
+ }
+ const GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ if (gv.buffer_index >= 0) {
+ global_variables.buffer_usage[gv.buffer_index].elements = 0;
+ global_variables.must_update_buffer_materials = true;
+ } else {
+ global_variables.must_update_texture_materials = true;
+ }
+
+ global_variables.variables.erase(p_name);
+}
+
+Vector<StringName> MaterialStorage::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.");
+ }
+
+ Vector<StringName> names;
+ for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ names.push_back(E.key);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+ return names;
+}
+
+void MaterialStorage::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;
+ if (gv.override.get_type() == Variant::NIL) {
+ if (gv.buffer_index >= 0) {
+ //buffer
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ for (const RID &E : gv.texture_materials) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material);
+ material_storage->_material_queue_update(material, false, true);
+ }
+ }
+ }
+}
+
+void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_variables.variables.has(p_name)) {
+ return; //variable may not exist
+ }
+
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
+
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ gv.override = p_value;
+
+ if (gv.buffer_index >= 0) {
+ //buffer
+ if (gv.override.get_type() == Variant::NIL) {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ } else {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ }
+
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ for (const RID &E : gv.texture_materials) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material);
+ material_storage->_material_queue_update(material, false, true);
+ }
+ }
+}
+
+Variant MaterialStorage::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.");
+ }
+
+ if (!global_variables.variables.has(p_name)) {
+ return Variant();
+ }
+
+ return global_variables.variables[p_name].value;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
+ if (!global_variables.variables.has(p_name)) {
+ return RS::GLOBAL_VAR_TYPE_MAX;
+ }
+
+ return global_variables.variables[p_name].type;
+}
+
+RS::GlobalVariableType MaterialStorage::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.");
+ }
+
+ return global_variable_get_type_internal(p_name);
+}
+
+void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+ List<PropertyInfo> settings;
+ ProjectSettings::get_singleton()->get_property_list(&settings);
+
+ for (const PropertyInfo &E : settings) {
+ if (E.name.begins_with("shader_globals/")) {
+ StringName name = E.name.get_slice("/", 1);
+ Dictionary d = ProjectSettings::get_singleton()->get(E.name);
+
+ ERR_CONTINUE(!d.has("type"));
+ ERR_CONTINUE(!d.has("value"));
+
+ String type = d["type"];
+
+ static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
+ "bool",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "int",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "rect2i",
+ "uint",
+ "uvec2",
+ "uvec3",
+ "uvec4",
+ "float",
+ "vec2",
+ "vec3",
+ "vec4",
+ "color",
+ "rect2",
+ "mat2",
+ "mat3",
+ "mat4",
+ "transform_2d",
+ "transform",
+ "sampler2D",
+ "sampler2DArray",
+ "sampler3D",
+ "samplerCube",
+ };
+
+ RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+
+ for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
+ if (global_var_type_names[i] == type) {
+ gvtype = RS::GlobalVariableType(i);
+ break;
+ }
+ }
+
+ ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
+
+ Variant value = d["value"];
+
+ if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //textire
+ if (!p_load_textures) {
+ value = RID();
+ continue;
+ }
+
+ String path = value;
+ Ref<Resource> resource = ResourceLoader::load(path);
+ ERR_CONTINUE(resource.is_null());
+ value = resource;
+ }
+
+ if (global_variables.variables.has(name)) {
+ //has it, update it
+ global_variable_set(name, value);
+ } else {
+ global_variable_add(name, gvtype, value);
+ }
+ }
+ }
+}
+
+void MaterialStorage::global_variables_clear() {
+ global_variables.variables.clear(); //not right but for now enough
+}
+
+RID MaterialStorage::global_variables_get_storage_buffer() const {
+ return global_variables.buffer;
+}
+
+int32_t MaterialStorage::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
+ ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
+ global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ return pos;
+}
+
+void MaterialStorage::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) {
+ global_variables.buffer_usage[pos].elements = 0;
+ }
+ global_variables.instance_buffer_pos.erase(p_instance);
+}
+
+void MaterialStorage::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
+ }
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+
+ if (pos < 0) {
+ return; //again, not allocated, ignore
+ }
+ ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ const ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
+ ShaderLanguage::TYPE_MAX, //nil
+ ShaderLanguage::TYPE_BOOL, //bool
+ ShaderLanguage::TYPE_INT, //int
+ ShaderLanguage::TYPE_FLOAT, //float
+ ShaderLanguage::TYPE_MAX, //string
+ ShaderLanguage::TYPE_VEC2, //vec2
+ ShaderLanguage::TYPE_IVEC2, //vec2i
+ ShaderLanguage::TYPE_VEC4, //rect2
+ ShaderLanguage::TYPE_IVEC4, //rect2i
+ ShaderLanguage::TYPE_VEC3, // vec3
+ ShaderLanguage::TYPE_IVEC3, //vec3i
+ ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //plane
+ ShaderLanguage::TYPE_VEC4, //quat
+ ShaderLanguage::TYPE_MAX, //aabb not supported here
+ ShaderLanguage::TYPE_MAX, //basis not supported here
+ ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_VEC4 //color
+ };
+
+ ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
+
+ ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ pos += p_index;
+
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_variable_mark_buffer_dirty(pos, 1);
+}
+
+void MaterialStorage::_update_global_variables() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ 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) {
+ // 25% of regions dirty, just update all buffer
+ RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
+ memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ } else {
+ uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+
+ for (uint32_t i = 0; i < total_regions; i++) {
+ if (global_variables.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+
+ global_variables.buffer_dirty_regions[i] = false;
+ }
+ }
+ }
+
+ global_variables.buffer_dirty_region_count = 0;
+ }
+
+ if (global_variables.must_update_buffer_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (const RID &E : global_variables.materials_using_buffer) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material); //wtf
+
+ material_storage->_material_queue_update(material, true, false);
+ }
+
+ global_variables.must_update_buffer_materials = false;
+ }
+
+ if (global_variables.must_update_texture_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (const RID &E : global_variables.materials_using_texture) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material); //wtf
+
+ material_storage->_material_queue_update(material, false, true);
+ }
+
+ global_variables.must_update_texture_materials = false;
+ }
+}
+
+/* SHADER API */
+
+RID MaterialStorage::shader_allocate() {
+ return shader_owner.allocate_rid();
+}
+
+void MaterialStorage::shader_initialize(RID p_rid) {
+ Shader shader;
+ shader.data = nullptr;
+ shader.type = SHADER_TYPE_MAX;
+
+ shader_owner.initialize_rid(p_rid, shader);
+}
+
+void MaterialStorage::shader_free(RID p_rid) {
+ Shader *shader = shader_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!shader);
+
+ //make material unreference this
+ while (shader->owners.size()) {
+ material_set_shader((*shader->owners.begin())->self, RID());
+ }
+
+ //clear data if exists
+ if (shader->data) {
+ memdelete(shader->data);
+ }
+ shader_owner.free(p_rid);
+}
+
+void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->code = p_code;
+ String mode_string = ShaderLanguage::get_shader_type(p_code);
+
+ ShaderType new_type;
+ if (mode_string == "canvas_item") {
+ new_type = SHADER_TYPE_2D;
+ } else if (mode_string == "particles") {
+ new_type = SHADER_TYPE_PARTICLES;
+ } else if (mode_string == "spatial") {
+ new_type = SHADER_TYPE_3D;
+ } else if (mode_string == "sky") {
+ new_type = SHADER_TYPE_SKY;
+ } else if (mode_string == "fog") {
+ new_type = SHADER_TYPE_FOG;
+ } else {
+ new_type = SHADER_TYPE_MAX;
+ }
+
+ if (new_type != shader->type) {
+ if (shader->data) {
+ memdelete(shader->data);
+ shader->data = nullptr;
+ }
+
+ for (Material *E : shader->owners) {
+ Material *material = E;
+ material->shader_type = new_type;
+ if (material->data) {
+ memdelete(material->data);
+ material->data = nullptr;
+ }
+ }
+
+ shader->type = new_type;
+
+ if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
+ shader->data = shader_data_request_func[new_type]();
+ } else {
+ shader->type = SHADER_TYPE_MAX; //invalid
+ }
+
+ for (Material *E : shader->owners) {
+ Material *material = E;
+ if (shader->data) {
+ material->data = material_get_data_request_function(new_type)(shader->data);
+ material->data->self = material->self;
+ material->data->set_next_pass(material->next_pass);
+ material->data->set_render_priority(material->priority);
+ }
+ material->shader_type = new_type;
+ }
+
+ if (shader->data) {
+ for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<int, RID> &E2 : E.value) {
+ shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ }
+ }
+ }
+ }
+
+ if (shader->data) {
+ shader->data->set_code(p_code);
+ }
+
+ for (Material *E : shader->owners) {
+ Material *material = E;
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ _material_queue_update(material, true, true);
+ }
+}
+
+String MaterialStorage::shader_get_code(RID p_shader) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, String());
+ return shader->code;
+}
+
+void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+ if (shader->data) {
+ return shader->data->get_param_list(p_param_list);
+ }
+}
+
+void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) {
+ if (!shader->default_texture_parameter.has(p_name)) {
+ shader->default_texture_parameter[p_name] = HashMap<int, RID>();
+ }
+ shader->default_texture_parameter[p_name][p_index] = p_texture;
+ } else {
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ shader->default_texture_parameter[p_name].erase(p_index);
+
+ if (shader->default_texture_parameter[p_name].is_empty()) {
+ shader->default_texture_parameter.erase(p_name);
+ }
+ }
+ }
+ if (shader->data) {
+ shader->data->set_default_texture_param(p_name, p_texture, p_index);
+ }
+ for (Material *E : shader->owners) {
+ Material *material = E;
+ _material_queue_update(material, false, true);
+ }
+}
+
+RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RID());
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ return shader->default_texture_parameter[p_name][p_index];
+ }
+
+ return RID();
+}
+
+Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, Variant());
+ if (shader->data) {
+ return shader->data->get_default_parameter(p_param);
+ }
+ return Variant();
+}
+
+void MaterialStorage::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 MaterialStorage::shader_get_native_source_code(RID p_shader) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
+ if (shader->data) {
+ return shader->data->get_native_source_code();
+ }
+ return RS::ShaderNativeSourceCode();
+}
+
+/* MATERIAL API */
+
+void MaterialStorage::_material_uniform_set_erased(void *p_material) {
+ RID rid = *(RID *)p_material;
+ Material *material = MaterialStorage::get_singleton()->get_material(rid);
+ if (material) {
+ if (material->data) {
+ // Uniform set may be gone because a dependency was erased. This happens
+ // if a texture is deleted, so re-create it.
+ MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
+ }
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ }
+}
+
+void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
+ material->uniform_dirty = material->uniform_dirty || p_uniform;
+ material->texture_dirty = material->texture_dirty || p_texture;
+
+ if (material->update_element.in_list()) {
+ return;
+ }
+
+ material_update_list.add(&material->update_element);
+}
+
+void MaterialStorage::_update_queued_materials() {
+ while (material_update_list.first()) {
+ Material *material = material_update_list.first()->self();
+ bool uniforms_changed = false;
+
+ if (material->data) {
+ uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
+ }
+ material->texture_dirty = false;
+ material->uniform_dirty = false;
+
+ material_update_list.remove(&material->update_element);
+
+ if (uniforms_changed) {
+ //some implementations such as 3D renderer cache the matreial uniform set, so update is required
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ }
+ }
+}
+
+RID MaterialStorage::material_allocate() {
+ return material_owner.allocate_rid();
+}
+
+void MaterialStorage::material_initialize(RID p_rid) {
+ material_owner.initialize_rid(p_rid);
+ Material *material = material_owner.get_or_null(p_rid);
+ material->self = p_rid;
+}
+
+void MaterialStorage::material_free(RID p_rid) {
+ Material *material = material_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!material);
+
+ material_set_shader(p_rid, RID()); //clean up shader
+ material->dependency.deleted_notify(p_rid);
+
+ material_owner.free(p_rid);
+}
+
+void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (material->data) {
+ memdelete(material->data);
+ material->data = nullptr;
+ }
+
+ if (material->shader) {
+ material->shader->owners.erase(material);
+ material->shader = nullptr;
+ material->shader_type = SHADER_TYPE_MAX;
+ }
+
+ if (p_shader.is_null()) {
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->shader_id = 0;
+ return;
+ }
+
+ Shader *shader = get_shader(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) {
+ return;
+ }
+
+ ERR_FAIL_COND(shader->data == nullptr);
+
+ material->data = material_data_request_func[shader->type](shader->data);
+ material->data->self = p_material;
+ material->data->set_next_pass(material->next_pass);
+ material->data->set_render_priority(material->priority);
+ //updating happens later
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ _material_queue_update(material, true, true);
+}
+
+void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (p_value.get_type() == Variant::NIL) {
+ material->params.erase(p_param);
+ } else {
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
+ material->params[p_param] = p_value;
+ }
+
+ if (material->shader && material->shader->data) { //shader is valid
+ bool is_texture = material->shader->data->is_param_texture(p_param);
+ _material_queue_update(material, !is_texture, is_texture);
+ } else {
+ _material_queue_update(material, true, true);
+ }
+}
+
+Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, Variant());
+ if (material->params.has(p_param)) {
+ return material->params[p_param];
+ } else {
+ return Variant();
+ }
+}
+
+void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (material->next_pass == p_next_material) {
+ return;
+ }
+
+ material->next_pass = p_next_material;
+ if (material->data) {
+ material->data->set_next_pass(p_next_material);
+ }
+
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+}
+
+void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ material->priority = priority;
+ if (material->data) {
+ material->data->set_render_priority(priority);
+ }
+}
+
+bool MaterialStorage::material_is_animated(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, false);
+ if (material->shader && material->shader->data) {
+ if (material->shader->data->is_animated()) {
+ return true;
+ } else if (material->next_pass.is_valid()) {
+ return material_is_animated(material->next_pass);
+ }
+ }
+ return false; //by default nothing is animated
+}
+
+bool MaterialStorage::material_casts_shadows(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, true);
+ if (material->shader && material->shader->data) {
+ if (material->shader->data->casts_shadows()) {
+ return true;
+ } else if (material->next_pass.is_valid()) {
+ return material_casts_shadows(material->next_pass);
+ }
+ }
+ return true; //by default everything casts shadows
+}
+
+void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ if (material->shader && material->shader->data) {
+ material->shader->data->get_instance_param_list(r_parameters);
+
+ if (material->next_pass.is_valid()) {
+ material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ }
+ }
+}
+
+void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ p_instance->update_dependency(&material->dependency);
+ if (material->next_pass.is_valid()) {
+ material_update_dependency(material->next_pass, p_instance);
+ }
+}
+
+void MaterialStorage::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;
+}
+
+MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
+ ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
+ return material_data_request_func[p_shader_type];
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
new file mode 100644
index 0000000000..f83df05355
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -0,0 +1,342 @@
+/*************************************************************************/
+/* material_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MATERIAL_STORAGE_RD_H
+#define MATERIAL_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererRD {
+
+class MaterialStorage;
+
+/* SHADER Structs */
+
+enum ShaderType {
+ SHADER_TYPE_2D,
+ SHADER_TYPE_3D,
+ SHADER_TYPE_PARTICLES,
+ SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
+ SHADER_TYPE_MAX
+};
+
+struct ShaderData {
+ virtual void set_code(const String &p_Code) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
+ virtual bool is_param_texture(const StringName &p_param) const = 0;
+ 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() {}
+};
+
+typedef ShaderData *(*ShaderDataRequestFunction)();
+
+struct Material;
+
+struct Shader {
+ ShaderData *data = nullptr;
+ String code;
+ ShaderType type;
+ HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
+ HashSet<Material *> owners;
+};
+
+/* Material structs */
+
+struct MaterialData {
+ void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+ void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+
+ virtual void set_render_priority(int p_priority) = 0;
+ virtual void set_next_pass(RID p_pass) = 0;
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual ~MaterialData();
+
+ //to be used internally by update_parameters, in the most common configuration of material parameters
+ bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void free_parameters_uniform_set(RID p_uniform_set);
+
+private:
+ friend class MaterialStorage;
+ RID self;
+ List<RID>::Element *global_buffer_E = nullptr;
+ List<RID>::Element *global_texture_E = nullptr;
+ uint64_t global_textures_pass = 0;
+ HashMap<StringName, uint64_t> used_global_textures;
+
+ //internally by update_parameters_uniform_set
+ Vector<uint8_t> ubo_data;
+ RID uniform_buffer;
+ Vector<RID> texture_cache;
+};
+
+typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+
+struct Material {
+ RID self;
+ MaterialData *data = nullptr;
+ Shader *shader = nullptr;
+ //shortcut to shader data and type
+ ShaderType shader_type = SHADER_TYPE_MAX;
+ uint32_t shader_id = 0;
+ bool uniform_dirty = false;
+ bool texture_dirty = false;
+ HashMap<StringName, Variant> params;
+ int32_t priority = 0;
+ RID next_pass;
+ SelfList<Material> update_element;
+
+ RendererStorage::Dependency dependency;
+
+ Material() :
+ update_element(this) {}
+};
+
+/* Global variable structs */
+struct GlobalVariables {
+ enum {
+ BUFFER_DIRTY_REGION_SIZE = 1024
+ };
+ struct Variable {
+ HashSet<RID> texture_materials; // materials using this
+
+ RS::GlobalVariableType type;
+ Variant value;
+ Variant override;
+ int32_t buffer_index; //for vectors
+ int32_t buffer_elements; //for vectors
+ };
+
+ HashMap<StringName, Variable> variables;
+
+ struct Value {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct ValueInt {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ struct ValueUInt {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ uint32_t w;
+ };
+
+ struct ValueUsage {
+ uint32_t elements = 0;
+ };
+
+ List<RID> materials_using_buffer;
+ List<RID> materials_using_texture;
+
+ RID buffer;
+ Value *buffer_values = nullptr;
+ ValueUsage *buffer_usage = nullptr;
+ bool *buffer_dirty_regions = nullptr;
+ uint32_t buffer_dirty_region_count = 0;
+
+ uint32_t buffer_size;
+
+ bool must_update_texture_materials = false;
+ bool must_update_buffer_materials = false;
+
+ HashMap<RID, int32_t> instance_buffer_pos;
+};
+
+class MaterialStorage : public RendererMaterialStorage {
+private:
+ friend struct MaterialData;
+ static MaterialStorage *singleton;
+
+ /* Samplers */
+
+ RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+ RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
+ /* Buffers */
+
+ RID quad_index_buffer;
+ RID quad_index_array;
+
+ /* GLOBAL VARIABLE API */
+
+ GlobalVariables global_variables;
+
+ int32_t _global_variable_allocate(uint32_t p_elements);
+ void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
+ void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+
+ /* SHADER API */
+
+ ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
+ mutable RID_Owner<Shader, true> shader_owner;
+
+ /* MATERIAL API */
+ MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
+ mutable RID_Owner<Material, true> material_owner;
+
+ SelfList<Material>::List material_update_list;
+
+ static void _material_uniform_set_erased(void *p_material);
+
+public:
+ static MaterialStorage *get_singleton();
+
+ MaterialStorage();
+ virtual ~MaterialStorage();
+
+ /* Samplers */
+
+ _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return default_rd_samplers[p_filter][p_repeat];
+ }
+ _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return custom_rd_samplers[p_filter][p_repeat];
+ }
+
+ void sampler_rd_configure_custom(float mipmap_bias);
+
+ // void sampler_rd_set_default(float p_mipmap_bias);
+
+ /* Buffers */
+
+ RID get_quad_index_array() { return quad_index_array; }
+
+ /* GLOBAL VARIABLE API */
+
+ void _update_global_variables();
+
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
+ virtual void global_variable_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_variable_get_list() const override;
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_variable_get(const StringName &p_name) const override;
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
+ RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+
+ virtual void global_variables_load_settings(bool p_load_textures = true) override;
+ virtual void global_variables_clear() override;
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance) override;
+ virtual void global_variables_instance_free(RID p_instance) override;
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+
+ RID global_variables_get_storage_buffer() const;
+
+ /* SHADER API */
+
+ Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
+ bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
+
+ virtual RID shader_allocate() override;
+ virtual void shader_initialize(RID p_shader) override;
+ virtual void shader_free(RID p_rid) override;
+
+ virtual void shader_set_code(RID p_shader, const String &p_code) override;
+ virtual String shader_get_code(RID p_shader) const override;
+ virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
+ virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override;
+ 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 override;
+
+ /* MATERIAL API */
+
+ Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
+ bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
+
+ void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
+ void _update_queued_materials();
+
+ virtual RID material_allocate() override;
+ virtual void material_initialize(RID p_material) override;
+ virtual void material_free(RID p_rid) override;
+
+ virtual void material_set_shader(RID p_material, RID p_shader) override;
+
+ virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
+ virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
+
+ virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
+ virtual void material_set_render_priority(RID p_material, int priority) override;
+
+ virtual bool material_is_animated(RID p_material) override;
+ virtual bool material_casts_shadows(RID p_material) override;
+
+ virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
+
+ virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override;
+
+ void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
+ MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
+
+ _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ return material->shader_id;
+ }
+
+ _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
+ Material *material = material_owner.get_or_null(p_material);
+ if (!material || material->shader_type != p_shader_type) {
+ return nullptr;
+ } else {
+ return material->data;
+ }
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !MATERIAL_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
new file mode 100644
index 0000000000..1e0d67f269
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -0,0 +1,1921 @@
+/*************************************************************************/
+/* mesh_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "mesh_storage.h"
+
+using namespace RendererRD;
+
+MeshStorage *MeshStorage::singleton = nullptr;
+
+MeshStorage *MeshStorage::get_singleton() {
+ return singleton;
+}
+
+MeshStorage::MeshStorage() {
+ singleton = this;
+
+ default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
+
+ //default rd buffers
+ {
+ Vector<uint8_t> buffer;
+ {
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(w);
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //normal
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(w);
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tangent
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(w);
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //color
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(w);
+ fptr[0] = 1.0;
+ fptr[1] = 1.0;
+ fptr[2] = 1.0;
+ fptr[3] = 1.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tex uv 1
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(w);
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ { //tex uv 2
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(w);
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ 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 = reinterpret_cast<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);
+ {
+ uint8_t *w = buffer.ptrw();
+ uint32_t *fptr = reinterpret_cast<uint32_t *>(w);
+ fptr[0] = 0;
+ fptr[1] = 0;
+ fptr[2] = 0;
+ fptr[3] = 0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //weights
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = reinterpret_cast<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_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ }
+
+ {
+ 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.append_id(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);
+ }
+ }
+}
+
+MeshStorage::~MeshStorage() {
+ //def buffers
+ for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
+ RD::get_singleton()->free(mesh_default_rd_buffers[i]);
+ }
+
+ skeleton_shader.shader.version_free(skeleton_shader.version);
+
+ RD::get_singleton()->free(default_rd_storage_buffer);
+
+ singleton = nullptr;
+}
+
+/* MESH API */
+
+RID MeshStorage::mesh_allocate() {
+ return mesh_owner.allocate_rid();
+}
+
+void MeshStorage::mesh_initialize(RID p_rid) {
+ mesh_owner.initialize_rid(p_rid, Mesh());
+}
+
+void MeshStorage::mesh_free(RID p_rid) {
+ mesh_clear(p_rid);
+ mesh_set_shadow_mesh(p_rid, RID());
+ Mesh *mesh = mesh_owner.get_or_null(p_rid);
+ mesh->dependency.deleted_notify(p_rid);
+ if (mesh->instances.size()) {
+ ERR_PRINT("deleting mesh with active instances");
+ }
+ if (mesh->shadow_owners.size()) {
+ for (Mesh *E : mesh->shadow_owners) {
+ Mesh *shadow_owner = E;
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+ }
+ mesh_owner.free(p_rid);
+}
+
+void MeshStorage::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.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
+
+ mesh->blend_shape_count = p_blend_shape_count;
+}
+
+/// Returns stride
+void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
+
+#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))) {
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ stride += sizeof(float) * 2;
+ } else {
+ stride += sizeof(float) * 3;
+ }
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ stride += sizeof(int32_t);
+
+ } break;
+ case RS::ARRAY_TANGENT: {
+ stride += sizeof(int32_t);
+
+ } break;
+ case RS::ARRAY_COLOR: {
+ attrib_stride += sizeof(uint32_t);
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ attrib_stride += sizeof(float) * 2;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ attrib_stride += sizeof(float) * 2;
+
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ int idx = i - RS::ARRAY_CUSTOM0;
+ const 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;
+ const 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 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
+
+ Mesh::Surface *s = memnew(Mesh::Surface);
+
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+
+ 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;
+
+ s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
+ s->index_count = p_surface.index_count;
+ s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
+ if (p_surface.lods.size()) {
+ s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
+ s->lod_count = p_surface.lods.size();
+
+ for (int i = 0; i < p_surface.lods.size(); i++) {
+ uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
+ s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
+ s->lods[i].edge_length = p_surface.lods[i].edge_length;
+ s->lods[i].index_count = indices;
+ }
+ }
+ }
+
+ s->aabb = p_surface.aabb;
+ s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
+
+ 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);
+ }
+
+ if (use_as_storage) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(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.append_id(s->skin_buffer);
+ } else {
+ u.append_id(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.append_id(s->blend_shape_buffer);
+ } else {
+ u.append_id(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]);
+ }
+ mesh->aabb.merge_with(p_surface.aabb);
+ }
+
+ s->material = p_surface.material;
+
+ mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
+ mesh->surfaces[mesh->surface_count] = s;
+ mesh->surface_count++;
+
+ for (MeshInstance *mi : mesh->instances) {
+ _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
+ }
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+
+ for (Mesh *E : mesh->shadow_owners) {
+ Mesh *shadow_owner = E;
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+
+ mesh->material_cache.clear();
+}
+
+int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const {
+ const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, -1);
+ return mesh->blend_shape_count;
+}
+
+void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX((int)p_mode, 2);
+
+ mesh->blend_shape_mode = p_mode;
+}
+
+RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
+ return mesh->blend_shape_mode;
+}
+
+void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
+ Mesh *mesh = mesh_owner.get_or_null(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->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ mesh->material_cache.clear();
+}
+
+RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
+
+ return mesh->surfaces[p_surface]->material;
+}
+
+RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
+
+ Mesh::Surface &s = *mesh->surfaces[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;
+
+ if (sd.index_count) {
+ sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
+ }
+ sd.aabb = s.aabb;
+ for (uint32_t i = 0; i < s.lod_count; i++) {
+ RS::SurfaceData::LOD lod;
+ lod.edge_length = s.lods[i].edge_length;
+ lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ sd.lods.push_back(lod);
+ }
+
+ sd.bone_aabbs = s.bone_aabbs;
+
+ if (s.blend_shape_buffer.is_valid()) {
+ sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
+ }
+
+ return sd;
+}
+
+int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, 0);
+ return mesh->surface_count;
+}
+
+void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ mesh->custom_aabb = p_aabb;
+}
+
+AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+ return mesh->custom_aabb;
+}
+
+AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+
+ if (mesh->custom_aabb != AABB()) {
+ return mesh->custom_aabb;
+ }
+
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ if (!skeleton || skeleton->size == 0) {
+ return mesh->aabb;
+ }
+
+ AABB aabb;
+
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ AABB laabb;
+ if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
+ int bs = mesh->surfaces[i]->bone_aabbs.size();
+ const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
+
+ int sbs = skeleton->size;
+ ERR_CONTINUE(bs > sbs);
+ const float *baseptr = skeleton->data.ptr();
+
+ bool first = true;
+
+ if (skeleton->use_2d) {
+ for (int j = 0; j < bs; j++) {
+ if (skbones[0].size == Vector3()) {
+ continue; //bone is unused
+ }
+
+ const float *dataptr = baseptr + j * 8;
+
+ Transform3D mtx;
+
+ mtx.basis.rows[0].x = dataptr[0];
+ mtx.basis.rows[1].x = dataptr[1];
+ mtx.origin.x = dataptr[3];
+
+ mtx.basis.rows[0].y = dataptr[4];
+ mtx.basis.rows[1].y = dataptr[5];
+ mtx.origin.y = dataptr[7];
+
+ AABB baabb = mtx.xform(skbones[j]);
+
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ } else {
+ for (int j = 0; j < bs; j++) {
+ if (skbones[0].size == Vector3()) {
+ continue; //bone is unused
+ }
+
+ const float *dataptr = baseptr + j * 12;
+
+ Transform3D mtx;
+
+ mtx.basis.rows[0][0] = dataptr[0];
+ mtx.basis.rows[0][1] = dataptr[1];
+ mtx.basis.rows[0][2] = dataptr[2];
+ mtx.origin.x = dataptr[3];
+ mtx.basis.rows[1][0] = dataptr[4];
+ mtx.basis.rows[1][1] = dataptr[5];
+ mtx.basis.rows[1][2] = dataptr[6];
+ mtx.origin.y = dataptr[7];
+ mtx.basis.rows[2][0] = dataptr[8];
+ mtx.basis.rows[2][1] = dataptr[9];
+ mtx.basis.rows[2][2] = dataptr[10];
+ mtx.origin.z = dataptr[11];
+
+ AABB baabb = mtx.xform(skbones[j]);
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ }
+
+ if (laabb.size == Vector3()) {
+ laabb = mesh->surfaces[i]->aabb;
+ }
+ } else {
+ laabb = mesh->surfaces[i]->aabb;
+ }
+
+ if (i == 0) {
+ aabb = laabb;
+ } else {
+ aabb.merge_with(laabb);
+ }
+ }
+
+ return aabb;
+}
+
+void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.erase(mesh);
+ }
+ mesh->shadow_mesh = p_shadow_mesh;
+
+ shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
+
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.insert(mesh);
+ }
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+}
+
+void MeshStorage::mesh_clear(RID p_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(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.
+ }
+
+ if (s.index_buffer.is_valid()) {
+ RD::get_singleton()->free(s.index_buffer);
+ }
+
+ if (s.lod_count) {
+ for (uint32_t j = 0; j < s.lod_count; j++) {
+ RD::get_singleton()->free(s.lods[j].index_buffer);
+ }
+ memdelete_arr(s.lods);
+ }
+
+ if (s.blend_shape_buffer.is_valid()) {
+ RD::get_singleton()->free(s.blend_shape_buffer);
+ }
+
+ memdelete(mesh->surfaces[i]);
+ }
+ if (mesh->surfaces) {
+ memfree(mesh->surfaces);
+ }
+
+ mesh->surfaces = nullptr;
+ mesh->surface_count = 0;
+ mesh->material_cache.clear();
+ //clear instance data
+ for (MeshInstance *mi : mesh->instances) {
+ _mesh_instance_clear(mi);
+ }
+ mesh->has_bone_weights = false;
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+
+ for (Mesh *E : mesh->shadow_owners) {
+ Mesh *shadow_owner = E;
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+}
+
+bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, false);
+
+ return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
+}
+
+/* MESH INSTANCE */
+
+RID MeshStorage::mesh_instance_create(RID p_base) {
+ Mesh *mesh = mesh_owner.get_or_null(p_base);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ RID rid = mesh_instance_owner.make_rid();
+ MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
+
+ 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 rid;
+}
+
+void MeshStorage::mesh_instance_free(RID p_rid) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
+ _mesh_instance_clear(mi);
+ mi->mesh->instances.erase(mi->I);
+ mi->I = nullptr;
+
+ mesh_instance_owner.free(p_rid);
+}
+
+void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ if (mi->skeleton == p_skeleton) {
+ return;
+ }
+ mi->skeleton = p_skeleton;
+ mi->skeleton_version = 0;
+ mi->dirty = true;
+}
+
+void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(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 MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
+ for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
+ 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);
+ }
+ if (mi->surfaces[i].vertex_buffer.is_valid()) {
+ RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
+ }
+ }
+ 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 MeshStorage::_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.append_id(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.append_id(mi->blend_weights_buffer);
+ } else {
+ u.append_id(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 MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(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.get_or_null(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 MeshStorage::update_mesh_instances() {
+ while (dirty_mesh_instance_weights.first()) {
+ MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
+
+ 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());
+ }
+ 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.get_or_null(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);
+ }
+
+ 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 MeshStorage::_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_INDEX; i++) {
+ RD::VertexAttribute vd;
+ RID buffer;
+ vd.location = i;
+
+ 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;
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ case RS::ARRAY_COLOR: {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+
+ } break;
+ 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_SFLOAT;
+ } break;
+ }
+ } else {
+ //Supplied, use it
+
+ 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;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ stride += sizeof(float) * 3;
+ }
+
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.offset = stride;
+
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+
+ stride += sizeof(uint32_t);
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.offset = stride;
+
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+ stride += sizeof(uint32_t);
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+ } break;
+ case RS::ARRAY_COLOR: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ attribute_stride += sizeof(int8_t) * 4;
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ 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: {
+ 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;
+ const 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;
+ const uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ const 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: {
+ vd.offset = skin_stride;
+
+ 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 (but computing stride was important anyway)
+ }
+
+ attributes.push_back(vd);
+ buffers.push_back(buffer);
+ }
+
+ //update final stride
+ for (int i = 0; i < attributes.size(); i++) {
+ 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;
+ }
+ }
+
+ v.input_mask = p_input_mask;
+ v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
+ v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
+}
+
+////////////////// MULTIMESH
+
+RID MeshStorage::multimesh_allocate() {
+ return multimesh_owner.allocate_rid();
+}
+void MeshStorage::multimesh_initialize(RID p_rid) {
+ multimesh_owner.initialize_rid(p_rid, MultiMesh());
+}
+
+void MeshStorage::multimesh_free(RID p_rid) {
+ _update_dirty_multimeshes();
+ multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
+ multimesh->dependency.deleted_notify(p_rid);
+ multimesh_owner.free(p_rid);
+}
+
+void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+
+ if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
+ return;
+ }
+
+ if (multimesh->buffer.is_valid()) {
+ RD::get_singleton()->free(multimesh->buffer);
+ multimesh->buffer = RID();
+ multimesh->uniform_set_2d = RID(); //cleared by dependency
+ multimesh->uniform_set_3d = RID(); //cleared by dependency
+ }
+
+ if (multimesh->data_cache_dirty_regions) {
+ memdelete_arr(multimesh->data_cache_dirty_regions);
+ multimesh->data_cache_dirty_regions = nullptr;
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ multimesh->instances = p_instances;
+ multimesh->xform_format = p_transform_format;
+ multimesh->uses_colors = p_use_colors;
+ multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ multimesh->uses_custom_data = p_use_custom_data;
+ multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
+ multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
+ multimesh->buffer_set = false;
+
+ //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
+ multimesh->data_cache = Vector<float>();
+ multimesh->aabb = AABB();
+ multimesh->aabb_dirty = false;
+ multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
+
+ if (multimesh->instances) {
+ multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
+ }
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH);
+}
+
+int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, 0);
+ return multimesh->instances;
+}
+
+void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ if (multimesh->mesh == p_mesh) {
+ return;
+ }
+ multimesh->mesh = p_mesh;
+
+ if (multimesh->instances == 0) {
+ return;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //we have a data cache, just mark it dirt
+ _multimesh_mark_all_dirty(multimesh, false, true);
+ } else if (multimesh->instances) {
+ //need to re-create AABB unfortunately, calling this has a penalty
+ if (multimesh->buffer_set) {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ const uint8_t *r = buffer.ptr();
+ const float *data = reinterpret_cast<const float *>(r);
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ }
+ }
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+}
+
+#define MULTIMESH_DIRTY_REGION_SIZE 512
+
+void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
+ if (multimesh->data_cache.size() > 0) {
+ return; //already local
+ }
+ ERR_FAIL_COND(multimesh->data_cache.size() > 0);
+ // this means that the user wants to load/save individual elements,
+ // for this, the data must reside on CPU, so just copy it there.
+ multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ if (multimesh->buffer_set) {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ {
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+ } else {
+ memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
+ }
+ }
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+ multimesh->data_cache_used_dirty_regions = 0;
+}
+
+void MeshStorage::_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;
+ ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
+#endif
+ if (!multimesh->data_cache_dirty_regions[region_index]) {
+ multimesh->data_cache_dirty_regions[region_index] = true;
+ multimesh->data_cache_used_dirty_regions++;
+ }
+
+ if (p_aabb) {
+ multimesh->aabb_dirty = true;
+ }
+
+ if (!multimesh->dirty) {
+ multimesh->dirty_list = multimesh_dirty_list;
+ multimesh_dirty_list = multimesh;
+ multimesh->dirty = true;
+ }
+}
+
+void MeshStorage::_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;
+
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ if (!multimesh->data_cache_dirty_regions[i]) {
+ multimesh->data_cache_dirty_regions[i] = true;
+ multimesh->data_cache_used_dirty_regions++;
+ }
+ }
+ }
+
+ if (p_aabb) {
+ multimesh->aabb_dirty = true;
+ }
+
+ if (!multimesh->dirty) {
+ multimesh->dirty_list = multimesh_dirty_list;
+ multimesh_dirty_list = multimesh;
+ multimesh->dirty = true;
+ }
+}
+
+void MeshStorage::_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);
+ for (int i = 0; i < p_instances; i++) {
+ const float *data = p_data + multimesh->stride_cache * i;
+ Transform3D t;
+
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ t.basis.rows[0][0] = data[0];
+ t.basis.rows[0][1] = data[1];
+ t.basis.rows[0][2] = data[2];
+ t.origin.x = data[3];
+ t.basis.rows[1][0] = data[4];
+ t.basis.rows[1][1] = data[5];
+ t.basis.rows[1][2] = data[6];
+ t.origin.y = data[7];
+ t.basis.rows[2][0] = data[8];
+ t.basis.rows[2][1] = data[9];
+ t.basis.rows[2][2] = data[10];
+ t.origin.z = data[11];
+
+ } else {
+ t.basis.rows[0].x = data[0];
+ t.basis.rows[1].x = data[1];
+ t.origin.x = data[3];
+
+ t.basis.rows[0].y = data[4];
+ t.basis.rows[1].y = data[5];
+ t.origin.y = data[7];
+ }
+
+ if (i == 0) {
+ aabb = t.xform(mesh_aabb);
+ } else {
+ aabb.merge_with(t.xform(mesh_aabb));
+ }
+ }
+
+ multimesh->aabb = aabb;
+}
+
+void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache;
+
+ dataptr[0] = p_transform.basis.rows[0][0];
+ dataptr[1] = p_transform.basis.rows[0][1];
+ dataptr[2] = p_transform.basis.rows[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.rows[1][0];
+ dataptr[5] = p_transform.basis.rows[1][1];
+ dataptr[6] = p_transform.basis.rows[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.rows[2][0];
+ dataptr[9] = p_transform.basis.rows[2][1];
+ dataptr[10] = p_transform.basis.rows[2][2];
+ dataptr[11] = p_transform.origin.z;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, true);
+}
+
+void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache;
+
+ dataptr[0] = p_transform.columns[0][0];
+ dataptr[1] = p_transform.columns[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.columns[2][0];
+ dataptr[4] = p_transform.columns[0][1];
+ dataptr[5] = p_transform.columns[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.columns[2][1];
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, true);
+}
+
+void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(!multimesh->uses_colors);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+
+ dataptr[0] = p_color.r;
+ dataptr[1] = p_color.g;
+ dataptr[2] = p_color.b;
+ dataptr[3] = p_color.a;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, false);
+}
+
+void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(!multimesh->uses_custom_data);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+
+ dataptr[0] = p_color.r;
+ dataptr[1] = p_color.g;
+ dataptr[2] = p_color.b;
+ dataptr[3] = p_color.a;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, false);
+}
+
+RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, RID());
+
+ return multimesh->mesh;
+}
+
+Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Transform3D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
+
+ _multimesh_make_local(multimesh);
+
+ Transform3D t;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache;
+
+ t.basis.rows[0][0] = dataptr[0];
+ t.basis.rows[0][1] = dataptr[1];
+ t.basis.rows[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.rows[1][0] = dataptr[4];
+ t.basis.rows[1][1] = dataptr[5];
+ t.basis.rows[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.rows[2][0] = dataptr[8];
+ t.basis.rows[2][1] = dataptr[9];
+ t.basis.rows[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+ }
+
+ return t;
+}
+
+Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Transform2D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
+
+ _multimesh_make_local(multimesh);
+
+ Transform2D t;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache;
+
+ t.columns[0][0] = dataptr[0];
+ t.columns[1][0] = dataptr[1];
+ t.columns[2][0] = dataptr[3];
+ t.columns[0][1] = dataptr[4];
+ t.columns[1][1] = dataptr[5];
+ t.columns[2][1] = dataptr[7];
+ }
+
+ return t;
+}
+
+Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
+ ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
+
+ _multimesh_make_local(multimesh);
+
+ Color c;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+ }
+
+ return c;
+}
+
+Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
+ ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
+
+ _multimesh_make_local(multimesh);
+
+ Color c;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+ }
+
+ return c;
+}
+
+void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
+
+ {
+ const float *r = p_buffer.ptr();
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
+ multimesh->buffer_set = true;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //if we have a data cache, just update it
+ multimesh->data_cache = p_buffer;
+ {
+ //clear dirty since nothing will be dirty anymore
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
+ } else if (multimesh->mesh.is_valid()) {
+ //if we have a mesh set, we need to re-generate the AABB from the new data
+ const float *data = p_buffer.ptr();
+
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+}
+
+Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Vector<float>());
+ if (multimesh->buffer.is_null()) {
+ return Vector<float>();
+ } else if (multimesh->data_cache.size()) {
+ return multimesh->data_cache;
+ } else {
+ //get from memory
+
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ Vector<float> ret;
+ ret.resize(multimesh->instances * multimesh->stride_cache);
+ {
+ float *w = ret.ptrw();
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+
+ return ret;
+ }
+}
+
+void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
+ if (multimesh->visible_instances == p_visible) {
+ return;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //there is a data cache..
+ _multimesh_mark_all_dirty(multimesh, false, true);
+ }
+
+ multimesh->visible_instances = p_visible;
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
+}
+
+int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, 0);
+ return multimesh->visible_instances;
+}
+
+AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, AABB());
+ if (multimesh->aabb_dirty) {
+ const_cast<MeshStorage *>(this)->_update_dirty_multimeshes();
+ }
+ return multimesh->aabb;
+}
+
+void MeshStorage::_update_dirty_multimeshes() {
+ while (multimesh_dirty_list) {
+ MultiMesh *multimesh = multimesh_dirty_list;
+
+ if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
+ const float *data = multimesh->data_cache.ptr();
+
+ uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
+
+ if (multimesh->data_cache_used_dirty_regions) {
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+
+ uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
+
+ if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
+ //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
+ } else {
+ //not that many regions? update them all
+ for (uint32_t i = 0; i < visible_region_count; i++) {
+ if (multimesh->data_cache_dirty_regions[i]) {
+ uint32_t offset = i * region_size;
+ uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
+ uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
+ RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ if (multimesh->aabb_dirty) {
+ //aabb is dirty..
+ _multimesh_re_create_aabb(multimesh, data, visible_instances);
+ multimesh->aabb_dirty = false;
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+ }
+
+ multimesh_dirty_list = multimesh->dirty_list;
+
+ multimesh->dirty_list = nullptr;
+ multimesh->dirty = false;
+ }
+
+ multimesh_dirty_list = nullptr;
+}
+
+/* SKELETON API */
+
+RID MeshStorage::skeleton_allocate() {
+ return skeleton_owner.allocate_rid();
+}
+void MeshStorage::skeleton_initialize(RID p_rid) {
+ skeleton_owner.initialize_rid(p_rid, Skeleton());
+}
+
+void MeshStorage::skeleton_free(RID p_rid) {
+ _update_dirty_skeletons();
+ skeleton_allocate_data(p_rid, 0);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
+ skeleton->dependency.deleted_notify(p_rid);
+ skeleton_owner.free(p_rid);
+}
+
+void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) {
+ if (!skeleton->dirty) {
+ skeleton->dirty = true;
+ skeleton->dirty_list = skeleton_dirty_list;
+ skeleton_dirty_list = skeleton;
+ }
+}
+
+void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_COND(p_bones < 0);
+
+ if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
+ return;
+ }
+
+ skeleton->size = p_bones;
+ skeleton->use_2d = p_2d_skeleton;
+ skeleton->uniform_set_3d = RID();
+
+ if (skeleton->buffer.is_valid()) {
+ RD::get_singleton()->free(skeleton->buffer);
+ skeleton->buffer = RID();
+ skeleton->data.clear();
+ skeleton->uniform_set_mi = RID();
+ }
+
+ if (skeleton->size) {
+ skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
+ skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
+ memset(skeleton->data.ptrw(), 0, 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.append_id(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(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA);
+}
+
+int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, 0);
+
+ return skeleton->size;
+}
+
+void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 12;
+
+ dataptr[0] = p_transform.basis.rows[0][0];
+ dataptr[1] = p_transform.basis.rows[0][1];
+ dataptr[2] = p_transform.basis.rows[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.rows[1][0];
+ dataptr[5] = p_transform.basis.rows[1][1];
+ dataptr[6] = p_transform.basis.rows[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.rows[2][0];
+ dataptr[9] = p_transform.basis.rows[2][1];
+ dataptr[10] = p_transform.basis.rows[2][2];
+ dataptr[11] = p_transform.origin.z;
+
+ _skeleton_make_dirty(skeleton);
+}
+
+Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform3D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
+ ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 12;
+
+ Transform3D t;
+
+ t.basis.rows[0][0] = dataptr[0];
+ t.basis.rows[0][1] = dataptr[1];
+ t.basis.rows[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.rows[1][0] = dataptr[4];
+ t.basis.rows[1][1] = dataptr[5];
+ t.basis.rows[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.rows[2][0] = dataptr[8];
+ t.basis.rows[2][1] = dataptr[9];
+ t.basis.rows[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+
+ return t;
+}
+
+void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 8;
+
+ dataptr[0] = p_transform.columns[0][0];
+ dataptr[1] = p_transform.columns[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.columns[2][0];
+ dataptr[4] = p_transform.columns[0][1];
+ dataptr[5] = p_transform.columns[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.columns[2][1];
+
+ _skeleton_make_dirty(skeleton);
+}
+
+Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform2D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
+ ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 8;
+
+ Transform2D t;
+ t.columns[0][0] = dataptr[0];
+ t.columns[1][0] = dataptr[1];
+ t.columns[2][0] = dataptr[3];
+ t.columns[0][1] = dataptr[4];
+ t.columns[1][1] = dataptr[5];
+ t.columns[2][1] = dataptr[7];
+
+ return t;
+}
+
+void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ skeleton->base_transform_2d = p_base_transform;
+}
+
+void MeshStorage::_update_dirty_skeletons() {
+ while (skeleton_dirty_list) {
+ Skeleton *skeleton = skeleton_dirty_list;
+
+ if (skeleton->size) {
+ RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr());
+ }
+
+ skeleton_dirty_list = skeleton->dirty_list;
+
+ skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES);
+
+ skeleton->version++;
+
+ skeleton->dirty = false;
+ skeleton->dirty_list = nullptr;
+ }
+
+ skeleton_dirty_list = nullptr;
+}
+
+void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+
+ p_instance->update_dependency(&skeleton->dependency);
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
new file mode 100644
index 0000000000..7ce019cf98
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -0,0 +1,706 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_RD_H
+#define MESH_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace RendererRD {
+
+/* Mesh */
+
+enum DefaultRDBuffer {
+ DEFAULT_RD_BUFFER_VERTEX,
+ DEFAULT_RD_BUFFER_NORMAL,
+ DEFAULT_RD_BUFFER_TANGENT,
+ 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,
+};
+
+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
+ // material.
+ // There are never that many geometry/material
+ // combinations, so a simple array is the most
+ // cache-efficient structure.
+
+ struct Version {
+ uint32_t input_mask = 0;
+ RD::VertexFormatID vertex_format = 0;
+ RID vertex_array;
+ };
+
+ SpinLock version_lock; //needed to access versions
+ Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+
+ RID index_buffer;
+ RID index_array;
+ uint32_t index_count = 0;
+
+ struct LOD {
+ float edge_length = 0.0;
+ uint32_t index_count = 0;
+ RID index_buffer;
+ RID index_array;
+ };
+
+ LOD *lods = nullptr;
+ uint32_t lod_count = 0;
+
+ AABB aabb;
+
+ Vector<AABB> bone_aabbs;
+
+ RID blend_shape_buffer;
+
+ RID material;
+
+ uint32_t render_index = 0;
+ uint64_t render_pass = 0;
+
+ uint32_t multimesh_render_index = 0;
+ uint64_t multimesh_render_pass = 0;
+
+ uint32_t particles_render_index = 0;
+ uint64_t particles_render_pass = 0;
+
+ RID uniform_set;
+ };
+
+ uint32_t blend_shape_count = 0;
+ RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
+
+ Surface **surfaces = nullptr;
+ uint32_t surface_count = 0;
+
+ Vector<AABB> bone_aabbs;
+
+ bool has_bone_weights = false;
+
+ AABB aabb;
+ AABB custom_aabb;
+
+ Vector<RID> material_cache;
+
+ List<MeshInstance *> instances;
+
+ RID shadow_mesh;
+ HashSet<Mesh *> shadow_owners;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* Mesh Instance */
+
+struct MeshInstance {
+ Mesh *mesh = nullptr;
+ 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) {}
+};
+
+/* MultiMesh */
+
+struct MultiMesh {
+ RID mesh;
+ int instances = 0;
+ RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
+ bool uses_colors = false;
+ bool uses_custom_data = false;
+ int visible_instances = -1;
+ AABB aabb;
+ bool aabb_dirty = false;
+ bool buffer_set = false;
+ uint32_t stride_cache = 0;
+ uint32_t color_offset_cache = 0;
+ uint32_t custom_data_offset_cache = 0;
+
+ Vector<float> data_cache; //used if individual setting is used
+ bool *data_cache_dirty_regions = nullptr;
+ uint32_t data_cache_used_dirty_regions = 0;
+
+ RID buffer; //storage buffer
+ RID uniform_set_3d;
+ RID uniform_set_2d;
+
+ bool dirty = false;
+ MultiMesh *dirty_list = nullptr;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* Skeleton */
+
+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;
+};
+
+struct Skeleton {
+ bool use_2d = false;
+ int size = 0;
+ Vector<float> data;
+ RID buffer;
+
+ bool dirty = false;
+ Skeleton *dirty_list = nullptr;
+ Transform2D base_transform_2d;
+
+ RID uniform_set_3d;
+ RID uniform_set_mi;
+
+ uint64_t version = 1;
+
+ RendererStorage::Dependency dependency;
+};
+
+class MeshStorage : public RendererMeshStorage {
+private:
+ static MeshStorage *singleton;
+
+ RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
+ RID default_rd_storage_buffer;
+
+ /* Mesh */
+
+ mutable RID_Owner<Mesh, true> mesh_owner;
+
+ void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
+
+ /* Mesh Instance API */
+
+ void _mesh_instance_clear(MeshInstance *mi);
+ void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
+
+ mutable RID_Owner<MeshInstance> mesh_instance_owner;
+
+ SelfList<MeshInstance>::List dirty_mesh_instance_weights;
+ SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
+
+ /* MultiMesh */
+
+ mutable RID_Owner<MultiMesh, true> multimesh_owner;
+
+ MultiMesh *multimesh_dirty_list = nullptr;
+
+ _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
+ _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
+
+ /* Skeleton */
+
+ SkeletonShader skeleton_shader;
+
+ mutable RID_Owner<Skeleton, true> skeleton_owner;
+
+ _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
+
+ Skeleton *skeleton_dirty_list = nullptr;
+
+public:
+ static MeshStorage *get_singleton();
+
+ MeshStorage();
+ virtual ~MeshStorage();
+
+ RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
+
+ /* MESH API */
+
+ Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+
+ virtual RID mesh_allocate() override;
+ virtual void mesh_initialize(RID p_mesh) override;
+ virtual void mesh_free(RID p_rid) override;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override;
+
+ /// Return stride
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override;
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override;
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override;
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override;
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override;
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override;
+
+ virtual int mesh_get_surface_count(RID p_mesh) const override;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override;
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override;
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
+
+ virtual void mesh_clear(RID p_mesh) override;
+
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override;
+
+ _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+ r_surface_count = mesh->surface_count;
+ if (r_surface_count == 0) {
+ return nullptr;
+ }
+ 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;
+ }
+ }
+
+ return mesh->material_cache.ptr();
+ }
+
+ _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
+
+ return mesh->surfaces[p_surface_index];
+ }
+
+ _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ return mesh->shadow_mesh;
+ }
+
+ _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
+ Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return surface->primitive;
+ }
+
+ _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_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return s->index_count ? s->index_count : s->vertex_count;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ int32_t current_lod = -1;
+ if (r_index_count) {
+ *r_index_count = s->index_count;
+ }
+ 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_mesh_lod_threshold) {
+ break;
+ }
+ current_lod = i;
+ }
+ if (current_lod == -1) {
+ return 0;
+ } else {
+ if (r_index_count) {
+ *r_index_count = s->lods[current_lod].index_count;
+ }
+ return current_lod + 1;
+ }
+ }
+
+ _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ if (p_lod == 0) {
+ return s->index_array;
+ } else {
+ return s->lods[p_lod - 1].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();
+
+ //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
+
+ for (uint32_t i = 0; i < s->version_count; i++) {
+ if (s->versions[i].input_mask != p_input_mask) {
+ continue;
+ }
+ //we have this version, hooray
+ r_vertex_format = s->versions[i].vertex_format;
+ r_vertex_array_rd = s->versions[i].vertex_array;
+ s->version_lock.unlock();
+ return;
+ }
+
+ 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->versions[version], s, p_input_mask);
+
+ r_vertex_format = s->versions[version].vertex_format;
+ r_vertex_array_rd = s->versions[version].vertex_array;
+
+ 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.get_or_null(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];
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->render_pass != p_render_pass) {
+ (*r_index)++;
+ s->render_pass = p_render_pass;
+ s->render_index = *r_index;
+ }
+
+ return s->render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->multimesh_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->multimesh_render_pass = p_render_pass;
+ s->multimesh_render_index = *r_index;
+ }
+
+ return s->multimesh_render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->particles_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->particles_render_pass = p_render_pass;
+ s->particles_render_index = *r_index;
+ }
+
+ return s->particles_render_index;
+ }
+
+ /* MESH INSTANCE API */
+
+ MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
+ bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
+
+ virtual RID mesh_instance_create(RID p_base) override;
+ virtual void mesh_instance_free(RID p_rid) override;
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
+ virtual void update_mesh_instances() override;
+
+ /* MULTIMESH API */
+
+ MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
+ bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
+
+ virtual RID multimesh_allocate() override;
+ virtual void multimesh_initialize(RID p_multimesh) override;
+ virtual void multimesh_free(RID p_rid) override;
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override;
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override;
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
+
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override;
+
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
+
+ void _update_dirty_multimeshes();
+
+ _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->xform_format;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_colors;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_custom_data;
+ }
+
+ _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh->visible_instances >= 0) {
+ return multimesh->visible_instances;
+ }
+ return multimesh->instances;
+ }
+
+ _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh == nullptr) {
+ return RID();
+ }
+ if (!multimesh->uniform_set_3d.is_valid()) {
+ if (!multimesh->buffer.is_valid()) {
+ return RID();
+ }
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(multimesh->buffer);
+ uniforms.push_back(u);
+ multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return multimesh->uniform_set_3d;
+ }
+
+ _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh == nullptr) {
+ return RID();
+ }
+ if (!multimesh->uniform_set_2d.is_valid()) {
+ if (!multimesh->buffer.is_valid()) {
+ return RID();
+ }
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(multimesh->buffer);
+ uniforms.push_back(u);
+ multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return multimesh->uniform_set_2d;
+ }
+
+ /* SKELETON API */
+
+ Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
+ bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
+
+ virtual RID skeleton_allocate() override;
+ virtual void skeleton_initialize(RID p_skeleton) override;
+ virtual void skeleton_free(RID p_rid) override;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
+ void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
+
+ virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override;
+
+ void _update_dirty_skeletons();
+
+ _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
+ return skeleton_owner.get_or_null(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.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, RID());
+ ERR_FAIL_COND_V(skeleton->size == 0, RID());
+ if (skeleton->use_2d) {
+ return RID();
+ }
+ if (!skeleton->uniform_set_3d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(skeleton->buffer);
+ uniforms.push_back(u);
+ skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return skeleton->uniform_set_3d;
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !MESH_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
new file mode 100644
index 0000000000..58a96ed1f9
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -0,0 +1,1890 @@
+/*************************************************************************/
+/* particles_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "particles_storage.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/rendering_server_globals.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+ParticlesStorage *ParticlesStorage::singleton = nullptr;
+
+ParticlesStorage *ParticlesStorage::get_singleton() {
+ return singleton;
+}
+
+ParticlesStorage::ParticlesStorage() {
+ singleton = this;
+
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ /* Particles */
+
+ {
+ // Initialize particles
+ Vector<String> particles_modes;
+ particles_modes.push_back("");
+ particles_shader.shader.initialize(particles_modes, String());
+ }
+ MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+ MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+
+ {
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["COLOR"] = "PARTICLE.color";
+ actions.renames["VELOCITY"] = "PARTICLE.velocity";
+ //actions.renames["MASS"] = "mass"; ?
+ actions.renames["ACTIVE"] = "particle_active";
+ actions.renames["RESTART"] = "restart";
+ actions.renames["CUSTOM"] = "PARTICLE.custom";
+ for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ String udname = "USERDATA" + itos(i + 1);
+ actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
+ actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
+ }
+ actions.renames["TRANSFORM"] = "PARTICLE.xform";
+ actions.renames["TIME"] = "frame_history.data[0].time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["LIFETIME"] = "params.lifetime";
+ actions.renames["DELTA"] = "local_delta";
+ actions.renames["NUMBER"] = "particle_number";
+ actions.renames["INDEX"] = "index";
+ //actions.renames["GRAVITY"] = "current_gravity";
+ actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
+ actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
+ actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
+ actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
+ actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
+ actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR";
+ actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM";
+ actions.renames["RESTART_POSITION"] = "restart_position";
+ actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale";
+ actions.renames["RESTART_VELOCITY"] = "restart_velocity";
+ actions.renames["RESTART_COLOR"] = "restart_color";
+ actions.renames["RESTART_CUSTOM"] = "restart_custom";
+ actions.renames["emit_subparticle"] = "emit_subparticle";
+ actions.renames["COLLIDED"] = "collided";
+ actions.renames["COLLISION_NORMAL"] = "collision_normal";
+ actions.renames["COLLISION_DEPTH"] = "collision_depth";
+ actions.renames["ATTRACTOR_FORCE"] = "attractor_force";
+
+ actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
+ actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
+ actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
+ actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = 3;
+ actions.base_uniform_string = "material.";
+ actions.base_varying_index = 10;
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ particles_shader.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for particles shader
+ particles_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(particles_shader.default_shader);
+ material_storage->shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
+shader_type particles;
+
+void process() {
+ COLOR = vec4(1.0);
+}
+)");
+ particles_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(particles_shader.default_material);
+ material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+
+ ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(material_storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
+ }
+
+ {
+ Vector<String> copy_modes;
+ for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
+ if (i == 0) {
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n");
+ copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n");
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n");
+ } else {
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n");
+ copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
+ }
+ }
+
+ particles_shader.copy_shader.initialize(copy_modes);
+
+ particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
+
+ for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
+ for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
+ particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
+ }
+ }
+ }
+}
+
+ParticlesStorage::~ParticlesStorage() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
+
+ material_storage->material_free(particles_shader.default_material);
+ material_storage->shader_free(particles_shader.default_shader);
+
+ singleton = nullptr;
+}
+
+/* PARTICLES */
+
+RID ParticlesStorage::particles_allocate() {
+ return particles_owner.allocate_rid();
+}
+
+void ParticlesStorage::particles_initialize(RID p_rid) {
+ particles_owner.initialize_rid(p_rid, Particles());
+}
+
+void ParticlesStorage::particles_free(RID p_rid) {
+ update_particles();
+ Particles *particles = particles_owner.get_or_null(p_rid);
+ particles->dependency.deleted_notify(p_rid);
+ _particles_free_data(particles);
+ particles_owner.free(p_rid);
+}
+
+void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ if (particles->mode == p_mode) {
+ return;
+ }
+
+ _particles_free_data(particles);
+
+ particles->mode = p_mode;
+}
+
+void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->emitting = p_emitting;
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->emitting;
+}
+
+void ParticlesStorage::_particles_free_data(Particles *particles) {
+ if (particles->particle_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->particle_buffer);
+ particles->particle_buffer = RID();
+ RD::get_singleton()->free(particles->particle_instance_buffer);
+ particles->particle_instance_buffer = RID();
+ }
+
+ particles->userdata_count = 0;
+
+ if (particles->frame_params_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->frame_params_buffer);
+ particles->frame_params_buffer = RID();
+ }
+ particles->particles_transforms_buffer_uniform_set = RID();
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) {
+ RD::get_singleton()->free(particles->trail_bind_pose_uniform_set);
+ }
+ particles->trail_bind_pose_uniform_set = RID();
+
+ if (particles->trail_bind_pose_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->trail_bind_pose_buffer);
+ particles->trail_bind_pose_buffer = RID();
+ }
+ if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) {
+ RD::get_singleton()->free(particles->collision_textures_uniform_set);
+ }
+ particles->collision_textures_uniform_set = RID();
+
+ if (particles->particles_sort_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->particles_sort_buffer);
+ particles->particles_sort_buffer = RID();
+ particles->particles_sort_uniform_set = RID();
+ }
+
+ if (particles->emission_buffer != nullptr) {
+ particles->emission_buffer = nullptr;
+ particles->emission_buffer_data.clear();
+ RD::get_singleton()->free(particles->emission_storage_buffer);
+ particles->emission_storage_buffer = RID();
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+ //will need to be re-created
+ RD::get_singleton()->free(particles->particles_material_uniform_set);
+ }
+ particles->particles_material_uniform_set = RID();
+}
+
+void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->amount == p_amount) {
+ return;
+ }
+
+ _particles_free_data(particles);
+
+ particles->amount = p_amount;
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->lifetime = p_lifetime;
+}
+
+void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->one_shot = p_one_shot;
+}
+
+void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->pre_process_time = p_time;
+}
+void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->explosiveness = p_ratio;
+}
+void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->randomness = p_ratio;
+}
+
+void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->custom_aabb = p_aabb;
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->speed_scale = p_scale;
+}
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->use_local_coords = p_enable;
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fixed_fps = p_fps;
+
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->interpolate = p_enable;
+}
+
+void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fractional_delta = p_enable;
+}
+
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_COND(p_length < 0.1);
+ p_length = MIN(10.0, p_length);
+
+ particles->trails_enabled = p_enable;
+ particles->trail_length = p_length;
+
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ }
+ particles->trail_bind_poses = p_bind_poses;
+ particles->trail_bind_poses_dirty = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->collision_base_size = p_size;
+}
+
+void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->transform_align = p_transform_align;
+}
+
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->process_material = p_material;
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
+}
+
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+
+ return particles->process_material;
+}
+
+void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_order = p_order;
+}
+
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_passes.resize(p_passes);
+}
+
+void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
+ particles->draw_passes.write[p_pass] = p_mesh;
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->restart_request = true;
+}
+
+void ParticlesStorage::_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);
+ memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size());
+ particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw());
+ particles->emission_buffer->particle_max = particles->amount;
+
+ particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data);
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+ //will need to be re-created
+ RD::get_singleton()->free(particles->particles_material_uniform_set);
+ particles->particles_material_uniform_set = RID();
+ }
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_COND(p_particles == p_subemitter_particles);
+
+ particles->sub_emitter = p_subemitter_particles;
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+ RD::get_singleton()->free(particles->particles_material_uniform_set);
+ particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting
+ }
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_COND(particles->amount == 0);
+
+ if (particles->emitting) {
+ particles->clear = true;
+ particles->emitting = false;
+ }
+
+ if (particles->emission_buffer == nullptr) {
+ _particles_allocate_emission_buffer(particles);
+ }
+
+ particles->inactive = false;
+ particles->inactive_time = 0;
+
+ int32_t idx = particles->emission_buffer->particle_count;
+ if (idx < particles->emission_buffer->particle_max) {
+ RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
+
+ particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
+ particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
+ particles->emission_buffer->data[idx].velocity[2] = p_velocity.z;
+
+ particles->emission_buffer->data[idx].custom[0] = p_custom.r;
+ particles->emission_buffer->data[idx].custom[1] = p_custom.g;
+ particles->emission_buffer->data[idx].custom[2] = p_custom.b;
+ particles->emission_buffer->data[idx].custom[3] = p_custom.a;
+
+ particles->emission_buffer->data[idx].color[0] = p_color.r;
+ particles->emission_buffer->data[idx].color[1] = p_color.g;
+ particles->emission_buffer->data[idx].color[2] = p_color.b;
+ particles->emission_buffer->data[idx].color[3] = p_color.a;
+
+ particles->emission_buffer->data[idx].flags = p_emit_flags;
+ particles->emission_buffer->particle_count++;
+ }
+}
+
+void ParticlesStorage::particles_request_process(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (!particles->dirty) {
+ particles->dirty = true;
+ particles->update_list = particle_update_list;
+ particle_update_list = particles;
+ }
+}
+
+AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
+ }
+
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
+ ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB());
+
+ Transform3D inv = particles->emission_transform.affine_inverse();
+
+ AABB aabb;
+ if (buffer.size()) {
+ bool first = true;
+
+ const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
+ uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count;
+
+ for (int i = 0; i < total_amount; i++) {
+ const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i];
+ if (particle_data.active) {
+ Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]);
+ if (!particles->use_local_coords) {
+ pos = inv.xform(pos);
+ }
+ if (first) {
+ aabb.position = pos;
+ first = false;
+ } else {
+ aabb.expand_to(pos);
+ }
+ }
+ }
+ }
+
+ float longest_axis_size = 0;
+ for (int i = 0; i < particles->draw_passes.size(); i++) {
+ if (particles->draw_passes[i].is_valid()) {
+ AABB maabb = MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
+ longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
+ }
+ }
+
+ aabb.grow_by(longest_axis_size);
+
+ return aabb;
+}
+
+AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ return particles->custom_aabb;
+}
+
+void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->emission_transform = p_transform;
+}
+
+int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->draw_passes.size();
+}
+
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+ ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
+
+ return particles->draw_passes[p_pass];
+}
+
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.insert(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.erase(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->has_sdf_collision = p_enable;
+ particles->sdf_collision_transform = p_xform;
+ particles->sdf_collision_to_screen = p_to_screen;
+ particles->sdf_collision_texture = p_texture;
+}
+
+void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ 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.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(p_particles->frame_params_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.append_id(p_particles->particle_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ if (p_particles->emission_storage_buffer.is_valid()) {
+ u.append_id(p_particles->emission_storage_buffer);
+ } else {
+ u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
+ if (sub_emitter) {
+ if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
+ _particles_allocate_emission_buffer(sub_emitter);
+ }
+ u.append_id(sub_emitter->emission_storage_buffer);
+ } else {
+ u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+ }
+ uniforms.push_back(u);
+ }
+
+ p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
+ }
+
+ double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
+
+ //move back history (if there is any)
+ for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
+ p_particles->frame_history[i] = p_particles->frame_history[i - 1];
+ }
+ //update current frame
+ ParticlesFrameParams &frame_params = p_particles->frame_history[0];
+
+ if (p_particles->clear) {
+ p_particles->cycle_number = 0;
+ p_particles->random_seed = Math::rand();
+ } else if (new_phase < p_particles->phase) {
+ if (p_particles->one_shot) {
+ p_particles->emitting = false;
+ }
+ p_particles->cycle_number++;
+ }
+
+ frame_params.emitting = p_particles->emitting;
+ frame_params.system_phase = new_phase;
+ frame_params.prev_system_phase = p_particles->phase;
+
+ p_particles->phase = new_phase;
+
+ 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;
+ frame_params.randomness = p_particles->randomness;
+
+ if (p_particles->use_local_coords) {
+ RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform);
+ } else {
+ RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+ }
+
+ frame_params.cycle = p_particles->cycle_number;
+ frame_params.frame = p_particles->frame_counter++;
+ frame_params.pad0 = 0;
+ frame_params.pad1 = 0;
+ frame_params.pad2 = 0;
+
+ { //collision and attractors
+
+ frame_params.collider_count = 0;
+ frame_params.attractor_count = 0;
+ frame_params.particle_size = p_particles->collision_base_size;
+
+ RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+ RID collision_heightmap_texture;
+
+ Transform3D to_particles;
+ if (p_particles->use_local_coords) {
+ to_particles = p_particles->emission_transform.affine_inverse();
+ }
+
+ if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) {
+ //2D collision
+
+ Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+ Transform2D revert = xform.affine_inverse();
+ frame_params.collider_count = 1;
+ frame_params.colliders[0].transform[0] = xform.columns[0][0];
+ frame_params.colliders[0].transform[1] = xform.columns[0][1];
+ frame_params.colliders[0].transform[2] = 0;
+ frame_params.colliders[0].transform[3] = xform.columns[2][0];
+
+ frame_params.colliders[0].transform[4] = xform.columns[1][0];
+ frame_params.colliders[0].transform[5] = xform.columns[1][1];
+ frame_params.colliders[0].transform[6] = 0;
+ frame_params.colliders[0].transform[7] = xform.columns[2][1];
+
+ frame_params.colliders[0].transform[8] = revert.columns[0][0];
+ frame_params.colliders[0].transform[9] = revert.columns[0][1];
+ frame_params.colliders[0].transform[10] = 0;
+ frame_params.colliders[0].transform[11] = revert.columns[2][0];
+
+ frame_params.colliders[0].transform[12] = revert.columns[1][0];
+ frame_params.colliders[0].transform[13] = revert.columns[1][1];
+ frame_params.colliders[0].transform[14] = 0;
+ frame_params.colliders[0].transform[15] = revert.columns[2][1];
+
+ frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
+ frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
+ frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
+ frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
+ frame_params.colliders[0].texture_index = 0;
+ frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
+
+ collision_heightmap_texture = p_particles->sdf_collision_texture;
+
+ //replace in all other history frames where used because parameters are no longer valid if screen moves
+ for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
+ if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
+ p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
+ }
+ }
+ }
+
+ uint32_t collision_3d_textures_used = 0;
+ for (const RID &E : p_particles->collisions) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E);
+ if (!pci || !pci->active) {
+ continue;
+ }
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
+ ERR_CONTINUE(!pc);
+
+ Transform3D to_collider = pci->transform;
+ if (p_particles->use_local_coords) {
+ to_collider = to_particles * to_collider;
+ }
+ Vector3 scale = to_collider.basis.get_scale();
+ to_collider.basis.orthonormalize();
+
+ if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
+ //attractor
+ if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
+
+ RendererStorageRD::store_transform(to_collider, attr.transform);
+ attr.strength = pc->attractor_strength;
+ attr.attenuation = pc->attractor_attenuation;
+ attr.directionality = pc->attractor_directionality;
+
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ attr.extents[0] = radius;
+ attr.extents[1] = radius;
+ attr.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ attr.extents[0] = extents.x;
+ attr.extents[1] = extents.y;
+ attr.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
+ if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
+ continue;
+ }
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD;
+ Vector3 extents = pc->extents * scale;
+ attr.extents[0] = extents.x;
+ attr.extents[1] = extents.y;
+ attr.extents[2] = extents.z;
+ attr.texture_index = collision_3d_textures_used;
+
+ collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
+ collision_3d_textures_used++;
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.attractor_count++;
+ } else {
+ //collider
+ if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
+
+ RendererStorageRD::store_transform(to_collider, col.transform);
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ col.extents[0] = radius;
+ col.extents[1] = radius;
+ col.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
+ if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
+ continue;
+ }
+ col.type = ParticlesFrameParams::COLLISION_TYPE_SDF;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ col.texture_index = collision_3d_textures_used;
+ col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported
+
+ collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
+ collision_3d_textures_used++;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
+ if (collision_heightmap_texture != RID()) { //already taken
+ continue;
+ }
+
+ col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ collision_heightmap_texture = pc->heightfield_texture;
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.collider_count++;
+ }
+ }
+
+ bool different = false;
+ if (collision_3d_textures_used == p_particles->collision_3d_textures_used) {
+ for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
+ if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) {
+ different = true;
+ break;
+ }
+ }
+ }
+
+ if (collision_heightmap_texture != p_particles->collision_heightmap_texture) {
+ different = true;
+ }
+
+ bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set);
+
+ if (different || !uniform_set_valid) {
+ if (uniform_set_valid) {
+ RD::get_singleton()->free(p_particles->collision_textures_uniform_set);
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
+ RID rd_tex;
+ if (i < collision_3d_textures_used) {
+ Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]);
+ if (t && t->type == Texture::TYPE_3D) {
+ rd_tex = t->rd_texture;
+ }
+ }
+
+ if (rd_tex == RID()) {
+ rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ }
+ u.append_id(rd_tex);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ if (collision_heightmap_texture.is_valid()) {
+ u.append_id(collision_heightmap_texture);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK));
+ }
+ uniforms.push_back(u);
+ }
+ p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
+ }
+ }
+
+ ParticlesShader::PushConstant push_constant;
+
+ int process_amount = p_particles->amount;
+
+ if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
+ process_amount *= p_particles->trail_bind_poses.size();
+ }
+ push_constant.clear = p_particles->clear;
+ push_constant.total_particles = p_particles->amount;
+ push_constant.lifetime = p_particles->lifetime;
+ push_constant.trail_size = p_particles->trail_params.size();
+ push_constant.use_fractional_delta = p_particles->fractional_delta;
+ push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit);
+ push_constant.trail_pass = false;
+
+ p_particles->force_sub_emit = false; //reset
+
+ Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
+
+ if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) {
+ // print_line("updating subemitter buffer");
+ int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 };
+ RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero);
+ push_constant.can_emit = true;
+
+ if (sub_emitter->emitting) {
+ sub_emitter->emitting = false;
+ sub_emitter->clear = true; //will need to clear if it was emitting, sorry
+ }
+ //make sure the sub emitter processes particles too
+ sub_emitter->inactive = false;
+ sub_emitter->inactive_time = 0;
+
+ sub_emitter->force_sub_emit = true;
+
+ } else {
+ push_constant.can_emit = false;
+ }
+
+ if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) {
+ RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer);
+ p_particles->emission_buffer->particle_count = 0;
+ }
+
+ p_particles->clear = false;
+
+ if (p_particles->trail_params.size() > 1) {
+ //fill the trail params
+ for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) {
+ uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size();
+ p_particles->trail_params[i] = p_particles->frame_history[src_idx];
+ }
+ } else {
+ p_particles->trail_params[0] = p_particles->frame_history[0];
+ }
+
+ RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
+
+ ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES));
+ if (!m) {
+ m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ }
+
+ ERR_FAIL_COND(!m);
+
+ p_particles->has_collision_cache = m->shader_data->uses_collision;
+
+ //todo should maybe compute all particle systems together?
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2);
+
+ if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
+
+ if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
+ //trails requires two passes in order to catch particle starts
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ push_constant.trail_pass = true;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1);
+ } else {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ return;
+ }
+
+ if (particles->particle_buffer.is_null()) {
+ return; //particles have not processed yet
+ }
+
+ bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
+
+ //copy to sort buffer
+ if (do_sort && particles->particles_sort_buffer == RID()) {
+ uint32_t size = particles->amount;
+ if (size & 1) {
+ size++; //make multiple of 16
+ }
+ size *= sizeof(float) * 2;
+ particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size);
+
+ {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(particles->particles_sort_buffer);
+ uniforms.push_back(u);
+ }
+
+ particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1);
+ }
+ }
+
+ ParticlesShader::CopyPushConstant copy_push_constant;
+
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ int fixed_fps = 60.0;
+ if (particles->fixed_fps > 0) {
+ fixed_fps = particles->fixed_fps;
+ }
+
+ copy_push_constant.trail_size = particles->trail_bind_poses.size();
+ copy_push_constant.trail_total = particles->frame_history.size();
+ copy_push_constant.frame_delta = 1.0 / fixed_fps;
+ } else {
+ copy_push_constant.trail_size = 1;
+ copy_push_constant.trail_total = 1;
+ copy_push_constant.frame_delta = 0.0;
+ }
+
+ copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
+ copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
+ copy_push_constant.total_particles = particles->amount;
+ copy_push_constant.copy_mode_2d = false;
+
+ Vector3 axis = -p_axis; // cameras look to z negative
+
+ if (particles->use_local_coords) {
+ axis = particles->emission_transform.basis.xform_inv(axis).normalized();
+ }
+
+ copy_push_constant.sort_direction[0] = axis.x;
+ copy_push_constant.sort_direction[1] = axis.y;
+ copy_push_constant.sort_direction[2] = axis.z;
+
+ copy_push_constant.align_up[0] = p_up_axis.x;
+ copy_push_constant.align_up[1] = p_up_axis.y;
+ copy_push_constant.align_up[2] = p_up_axis.z;
+
+ copy_push_constant.align_mode = particles->transform_align;
+
+ if (do_sort) {
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
+
+ RD::get_singleton()->compute_list_end();
+ RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
+ }
+
+ copy_push_constant.total_particles *= copy_push_constant.total_particles;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
+ copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX;
+ copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+ if (do_sort) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void ParticlesStorage::_particles_update_buffers(Particles *particles) {
+ uint32_t userdata_count = 0;
+
+ const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material);
+ if (material && material->shader && material->shader->data) {
+ const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
+ userdata_count = shader_data->userdata_count;
+ }
+
+ if (userdata_count != particles->userdata_count) {
+ // Mismatch userdata, re-create buffers.
+ _particles_free_data(particles);
+ }
+
+ if (particles->amount > 0 && particles->particle_buffer.is_null()) {
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
+
+ particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
+
+ particles->userdata_count = userdata_count;
+
+ particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount);
+ //needs to clear it
+
+ {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.append_id(particles->particle_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(particles->particle_instance_buffer);
+ uniforms.push_back(u);
+ }
+
+ particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0);
+ }
+ }
+}
+void ParticlesStorage::update_particles() {
+ while (particle_update_list) {
+ //use transform feedback to process particles
+
+ Particles *particles = particle_update_list;
+
+ //take and remove
+ particle_update_list = particles->update_list;
+ particles->update_list = nullptr;
+ particles->dirty = false;
+
+ _particles_update_buffers(particles);
+
+ if (particles->restart_request) {
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ particles->restart_request = false;
+ }
+
+ if (particles->inactive && !particles->emitting) {
+ //go next
+ continue;
+ }
+
+ if (particles->emitting) {
+ if (particles->inactive) {
+ //restart system from scratch
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ }
+ particles->inactive = false;
+ particles->inactive_time = 0;
+ } else {
+ particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time();
+ if (particles->inactive_time > particles->lifetime * 1.2) {
+ particles->inactive = true;
+ continue;
+ }
+ }
+
+#ifndef _MSC_VER
+#warning Should use display refresh rate for all this
+#endif
+
+ float screen_hz = 60;
+
+ int fixed_fps = 0;
+ if (particles->fixed_fps > 0) {
+ fixed_fps = particles->fixed_fps;
+ } else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ fixed_fps = screen_hz;
+ }
+ {
+ //update trails
+ int history_size = 1;
+ int trail_steps = 1;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ history_size = MAX(1, int(particles->trail_length * fixed_fps));
+ trail_steps = particles->trail_bind_poses.size();
+ }
+
+ if (uint32_t(history_size) != particles->frame_history.size()) {
+ particles->frame_history.resize(history_size);
+ memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size);
+ }
+
+ if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) {
+ particles->trail_params.resize(trail_steps);
+ if (particles->frame_params_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->frame_params_buffer);
+ }
+ particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps);
+ }
+
+ if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) {
+ particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size());
+ particles->trail_bind_poses_dirty = true;
+ }
+
+ if (particles->trail_bind_pose_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ if (particles->trail_bind_pose_buffer.is_valid()) {
+ u.append_id(particles->trail_bind_pose_buffer);
+ } else {
+ u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+ }
+ uniforms.push_back(u);
+ }
+
+ particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2);
+ }
+
+ if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) {
+ if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) {
+ particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16);
+ }
+
+ for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
+ RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
+ }
+
+ RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
+ }
+ }
+
+ bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
+
+ if (particles->clear && particles->pre_process_time > 0.0) {
+ double frame_time;
+ if (fixed_fps > 0) {
+ frame_time = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / 30.0;
+ }
+
+ double todo = particles->pre_process_time;
+
+ while (todo >= 0) {
+ _particles_process(particles, frame_time);
+ todo -= frame_time;
+ }
+ }
+
+ if (fixed_fps > 0) {
+ double frame_time;
+ double decr;
+ if (zero_time_scale) {
+ frame_time = 0.0;
+ decr = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / fixed_fps;
+ decr = frame_time;
+ }
+ double 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..
+ delta = 0.001;
+ }
+ double todo = particles->frame_remainder + delta;
+
+ while (todo >= frame_time) {
+ _particles_process(particles, frame_time);
+ todo -= decr;
+ }
+
+ particles->frame_remainder = todo;
+
+ } else {
+ if (zero_time_scale) {
+ _particles_process(particles, 0.0);
+ } else {
+ _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
+ }
+ }
+
+ //copy particles to instance buffer
+
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ //does not need view dependent operation, do copy here
+ ParticlesShader::CopyPushConstant copy_push_constant;
+
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ // Affect 2D only.
+ if (particles->use_local_coords) {
+ // In local mode, particle positions are calculated locally (relative to the node position)
+ // and they're also drawn locally.
+ // It works as expected, so we just pass an identity transform.
+ RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
+ } else {
+ // In global mode, particle positions are calculated globally (relative to the canvas origin)
+ // but they're drawn locally.
+ // So, we need to pass the inverse of the emission transform to bring the
+ // particles to local coordinates before drawing.
+ Transform3D inv = particles->emission_transform.affine_inverse();
+ RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform);
+ }
+
+ copy_push_constant.total_particles = total_amount;
+ copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
+ copy_push_constant.align_mode = particles->transform_align;
+ copy_push_constant.align_up[0] = 0;
+ copy_push_constant.align_up[1] = 0;
+ copy_push_constant.align_up[2] = 0;
+
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ copy_push_constant.trail_size = particles->trail_bind_poses.size();
+ copy_push_constant.trail_total = particles->frame_history.size();
+ copy_push_constant.frame_delta = 1.0 / fixed_fps;
+ } else {
+ copy_push_constant.trail_size = 1;
+ copy_push_constant.trail_total = 1;
+ copy_push_constant.frame_delta = 0.0;
+ }
+
+ copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1);
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+}
+
+bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+ return !particles->emitting && particles->inactive;
+}
+
+/* Particles SHADER */
+
+void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
+ ParticlesStorage *particles_storage = ParticlesStorage::get_singleton();
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+ uses_collision = false;
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE;
+ actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE;
+
+ /*
+ uses_time = false;
+
+ actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
+ actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+*/
+
+ actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
+ userdata_count = 0;
+ for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ userdatas_used[i] = false;
+ actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
+ }
+
+ actions.uniforms = &uniforms;
+
+ Error err = particles_storage->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+ if (version.is_null()) {
+ version = particles_storage->particles_shader.shader.version_create();
+ }
+
+ for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ if (userdatas_used[i]) {
+ userdata_count++;
+ }
+ }
+
+ particles_storage->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!particles_storage->particles_shader.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ //update pipelines
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(particles_storage->particles_shader.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ HashMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool ParticlesStorage::ParticlesShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool ParticlesStorage::ParticlesShaderData::is_animated() const {
+ return false;
+}
+
+bool ParticlesStorage::ParticlesShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant ParticlesStorage::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;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode ParticlesStorage::ParticlesShaderData::get_native_source_code() const {
+ return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version);
+}
+
+ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ ParticlesStorage::get_singleton()->particles_shader.shader.version_free(version);
+ }
+}
+
+ShaderData *ParticlesStorage::_create_particles_shader_func() {
+ ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
+ return shader_data;
+}
+
+bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
+}
+
+ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
+ ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
+ material_data->shader_data = p_shader;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+////////
+
+/* PARTICLES COLLISION API */
+
+RID ParticlesStorage::particles_collision_allocate() {
+ return particles_collision_owner.allocate_rid();
+}
+void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+ particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
+}
+
+void ParticlesStorage::particles_collision_free(RID p_rid) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
+
+ if (particles_collision->heightfield_texture.is_valid()) {
+ RD::get_singleton()->free(particles_collision->heightfield_texture);
+ }
+ particles_collision->dependency.deleted_notify(p_rid);
+ particles_collision_owner.free(p_rid);
+}
+
+RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, RID());
+ ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID());
+
+ if (particles_collision->heightfield_texture == RID()) {
+ //create
+ const int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
+ Size2i size;
+ if (particles_collision->extents.x > particles_collision->extents.z) {
+ size.x = resolutions[particles_collision->heightfield_resolution];
+ size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
+ } else {
+ size.y = resolutions[particles_collision->heightfield_resolution];
+ size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
+ }
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_D32_SFLOAT;
+ tf.width = size.x;
+ tf.height = size.y;
+ 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());
+
+ Vector<RID> fb_tex;
+ fb_tex.push_back(particles_collision->heightfield_texture);
+ particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ particles_collision->heightfield_fb_size = size;
+ }
+
+ return particles_collision->heightfield_fb;
+}
+
+void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ if (p_type == particles_collision->type) {
+ return;
+ }
+
+ if (particles_collision->heightfield_texture.is_valid()) {
+ RD::get_singleton()->free(particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = RID();
+ }
+ particles_collision->type = p_type;
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->cull_mask = p_cull_mask;
+}
+
+void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->radius = p_radius;
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->extents = p_extents;
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_strength = p_strength;
+}
+
+void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_directionality = p_directionality;
+}
+
+void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_attenuation = p_curve;
+}
+
+void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->field_texture = p_texture;
+}
+
+void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+
+ if (particles_collision->heightfield_resolution == p_resolution) {
+ return;
+ }
+
+ particles_collision->heightfield_resolution = p_resolution;
+
+ if (particles_collision->heightfield_texture.is_valid()) {
+ RD::get_singleton()->free(particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = RID();
+ }
+}
+
+AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, AABB());
+
+ switch (particles_collision->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ AABB aabb;
+ aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
+ aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
+ return aabb;
+ }
+ default: {
+ AABB aabb;
+ aabb.position = -particles_collision->extents;
+ aabb.size = particles_collision->extents * 2;
+ return aabb;
+ }
+ }
+
+ return AABB();
+}
+
+Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const {
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, Vector3());
+ return particles_collision->extents;
+}
+
+bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, false);
+ return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
+}
+
+RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
+ ParticlesCollisionInstance pci;
+ pci.collision = p_collision;
+ return particles_collision_instance_owner.make_rid(pci);
+}
+
+void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+ particles_collision_instance_owner.free(p_rid);
+}
+
+void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->transform = p_transform;
+}
+
+void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->active = p_active;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
new file mode 100644
index 0000000000..115633d17a
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -0,0 +1,564 @@
+/*************************************************************************/
+/* particles_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PARTICLES_STORAGE_RD_H
+#define PARTICLES_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.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/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace RendererRD {
+
+/* PARTICLES */
+
+struct ParticleData {
+ float xform[16];
+ float velocity[3];
+ uint32_t active;
+ float color[4];
+ float custom[3];
+ float lifetime;
+};
+
+struct ParticlesFrameParams {
+ enum {
+ MAX_ATTRACTORS = 32,
+ MAX_COLLIDERS = 32,
+ MAX_3D_TEXTURES = 7
+ };
+
+ enum AttractorType {
+ ATTRACTOR_TYPE_SPHERE,
+ ATTRACTOR_TYPE_BOX,
+ ATTRACTOR_TYPE_VECTOR_FIELD,
+ };
+
+ struct Attractor {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
+
+ uint32_t texture_index; //texture index for vector field
+ float strength;
+ float attenuation;
+ float directionality;
+ };
+
+ enum CollisionType {
+ COLLISION_TYPE_SPHERE,
+ COLLISION_TYPE_BOX,
+ COLLISION_TYPE_SDF,
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
+
+ };
+
+ struct Collider {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
+
+ uint32_t texture_index; //texture index for vector field
+ real_t scale;
+ uint32_t pad[2];
+ };
+
+ uint32_t emitting;
+ float system_phase;
+ float prev_system_phase;
+ uint32_t cycle;
+
+ real_t explosiveness;
+ real_t randomness;
+ float time;
+ float delta;
+
+ uint32_t frame;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
+
+ uint32_t random_seed;
+ uint32_t attractor_count;
+ uint32_t collider_count;
+ float particle_size;
+
+ float emission_transform[16];
+
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
+};
+
+struct ParticleEmissionBufferData {
+};
+
+struct ParticleEmissionBuffer {
+ struct Data {
+ float xform[16];
+ float velocity[3];
+ uint32_t flags;
+ float color[4];
+ float custom[4];
+ };
+
+ int32_t particle_count;
+ int32_t particle_max;
+ uint32_t pad1;
+ uint32_t pad2;
+ Data data[1]; //its 2020 and empty arrays are still non standard in C++
+};
+
+struct Particles {
+ RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
+ bool inactive = true;
+ double inactive_time = 0.0;
+ bool emitting = false;
+ bool one_shot = false;
+ int amount = 0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness = 0.0;
+ real_t randomness = 0.0;
+ bool restart_request = false;
+ AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+ bool use_local_coords = true;
+ bool has_collision_cache = false;
+
+ bool has_sdf_collision = false;
+ Transform2D sdf_collision_transform;
+ Rect2 sdf_collision_to_screen;
+ RID sdf_collision_texture;
+
+ RID process_material;
+ uint32_t frame_counter = 0;
+ RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
+
+ RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
+
+ Vector<RID> draw_passes;
+ Vector<Transform3D> trail_bind_poses;
+ bool trail_bind_poses_dirty = false;
+ RID trail_bind_pose_buffer;
+ RID trail_bind_pose_uniform_set;
+
+ RID particle_buffer;
+ RID particle_instance_buffer;
+ RID frame_params_buffer;
+
+ uint32_t userdata_count = 0;
+
+ RID particles_material_uniform_set;
+ RID particles_copy_uniform_set;
+ RID particles_transforms_buffer_uniform_set;
+ RID collision_textures_uniform_set;
+
+ RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+ uint32_t collision_3d_textures_used = 0;
+ RID collision_heightmap_texture;
+
+ RID particles_sort_buffer;
+ RID particles_sort_uniform_set;
+
+ bool dirty = false;
+ Particles *update_list = nullptr;
+
+ RID sub_emitter;
+
+ double phase = 0.0;
+ double prev_phase = 0.0;
+ uint64_t prev_ticks = 0;
+ uint32_t random_seed = 0;
+
+ uint32_t cycle_number = 0;
+
+ double speed_scale = 1.0;
+
+ int fixed_fps = 30;
+ bool interpolate = true;
+ bool fractional_delta = false;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
+
+ bool clear = true;
+
+ bool force_sub_emit = false;
+
+ Transform3D emission_transform;
+
+ Vector<uint8_t> emission_buffer_data;
+
+ ParticleEmissionBuffer *emission_buffer = nullptr;
+ RID emission_storage_buffer;
+
+ HashSet<RID> collisions;
+
+ RendererStorage::Dependency dependency;
+
+ double trail_length = 1.0;
+ bool trails_enabled = false;
+ LocalVector<ParticlesFrameParams> frame_history;
+ LocalVector<ParticlesFrameParams> trail_params;
+
+ Particles() {
+ }
+};
+
+/* Particles Collision */
+
+struct ParticlesCollision {
+ RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ float radius = 1.0;
+ Vector3 extents = Vector3(1, 1, 1);
+ float attractor_strength = 1.0;
+ float attractor_attenuation = 1.0;
+ float attractor_directionality = 0.0;
+ RID field_texture;
+ RID heightfield_texture;
+ RID heightfield_fb;
+ Size2i heightfield_fb_size;
+
+ RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+
+ RendererStorage::Dependency dependency;
+};
+
+struct ParticlesCollisionInstance {
+ RID collision;
+ Transform3D transform;
+ bool active = false;
+};
+
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+ static ParticlesStorage *singleton;
+
+ /* PARTICLES */
+
+ void _particles_process(Particles *p_particles, double p_delta);
+ void _particles_allocate_emission_buffer(Particles *particles);
+ void _particles_free_data(Particles *particles);
+ void _particles_update_buffers(Particles *particles);
+
+ struct ParticlesShader {
+ struct PushConstant {
+ float lifetime;
+ uint32_t clear;
+ uint32_t total_particles;
+ uint32_t trail_size;
+
+ uint32_t use_fractional_delta;
+ uint32_t sub_emitter_mode;
+ uint32_t can_emit;
+ uint32_t trail_pass;
+ };
+
+ ParticlesShaderRD shader;
+ ShaderCompiler compiler;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ struct CopyPushConstant {
+ float sort_direction[3];
+ uint32_t total_particles;
+
+ uint32_t trail_size;
+ uint32_t trail_total;
+ float frame_delta;
+ float frame_remainder;
+
+ float align_up[3];
+ uint32_t align_mode;
+
+ uint32_t order_by_lifetime;
+ uint32_t lifetime_split;
+ uint32_t lifetime_reverse;
+ uint32_t copy_mode_2d;
+
+ float inv_emission_transform[16];
+ };
+
+ enum {
+ MAX_USERDATAS = 6
+ };
+ enum {
+ COPY_MODE_FILL_INSTANCES,
+ COPY_MODE_FILL_SORT_BUFFER,
+ COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
+ COPY_MODE_MAX,
+ };
+
+ ParticlesCopyShaderRD copy_shader;
+ RID copy_shader_version;
+ RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
+
+ LocalVector<float> pose_update_buffer;
+
+ } particles_shader;
+
+ Particles *particle_update_list = nullptr;
+
+ mutable RID_Owner<Particles, true> particles_owner;
+
+ /* Particle Shader */
+
+ struct ParticlesShaderData : public ShaderData {
+ bool valid = false;
+ RID version;
+ bool uses_collision = false;
+
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size = 0;
+
+ String path;
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ RID pipeline;
+
+ bool uses_time = false;
+
+ bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
+ uint32_t userdata_count = 0;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ ParticlesShaderData() {}
+ virtual ~ParticlesShaderData();
+ };
+
+ ShaderData *_create_particles_shader_func();
+ static ShaderData *_create_particles_shader_funcs() {
+ return ParticlesStorage::get_singleton()->_create_particles_shader_func();
+ }
+
+ struct ParticlesMaterialData : public MaterialData {
+ ParticlesShaderData *shader_data = nullptr;
+ RID uniform_set;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~ParticlesMaterialData();
+ };
+
+ MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+ static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+ return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
+ }
+
+ /* Particles Collision */
+
+ mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
+
+ mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
+public:
+ static ParticlesStorage *get_singleton();
+
+ ParticlesStorage();
+ virtual ~ParticlesStorage();
+
+ /* PARTICLES */
+
+ Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); }
+ bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
+
+ virtual RID particles_allocate() override;
+ virtual void particles_initialize(RID p_particles_collision) override;
+ virtual void particles_free(RID p_rid) override;
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
+ virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
+ virtual void particles_set_amount(RID p_particles, int p_amount) override;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
+ virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) override;
+ virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
+ virtual void particles_set_process_material(RID p_particles, RID p_material) override;
+ virtual RID particles_get_process_material(RID p_particles) const override;
+
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override;
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
+
+ virtual void particles_restart(RID p_particles) override;
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
+
+ virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
+
+ virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
+
+ virtual void particles_set_draw_passes(RID p_particles, int p_count) override;
+ virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
+
+ virtual void particles_request_process(RID p_particles) override;
+ virtual AABB particles_get_current_aabb(RID p_particles) override;
+ virtual AABB particles_get_aabb(RID p_particles) const override;
+
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
+
+ virtual bool particles_get_emitting(RID p_particles) override;
+ virtual int particles_get_draw_passes(RID p_particles) const override;
+ virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
+
+ virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
+
+ virtual bool particles_is_inactive(RID p_particles) const override;
+
+ _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
+ return particles->mode;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ r_trail_divisor = particles->trail_bind_poses.size();
+ } else {
+ r_trail_divisor = 1;
+ }
+
+ return particles->amount * r_trail_divisor;
+ }
+
+ _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->has_collision_cache;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->use_local_coords;
+ }
+
+ _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+ if (particles->particles_transforms_buffer_uniform_set.is_null()) {
+ _particles_update_buffers(particles);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(particles->particle_instance_buffer);
+ uniforms.push_back(u);
+ }
+
+ particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return particles->particles_transforms_buffer_uniform_set;
+ }
+
+ virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
+ virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+
+ virtual void update_particles() override;
+
+ /* Particles Collision */
+
+ ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); }
+ bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
+
+ virtual RID particles_collision_allocate() override;
+ virtual void particles_collision_initialize(RID p_particles_collision) override;
+ virtual void particles_collision_free(RID p_rid) override;
+
+ virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
+ virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; //for spheres
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; //for non-spheres
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; //for SDF and vector field, heightfield is dynamic
+ virtual void particles_collision_height_field_update(RID p_particles_collision) override; //for SDF and vector field
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; //for SDF and vector field
+ virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+ Vector3 particles_collision_get_extents(RID p_particles_collision) const;
+ virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
+ virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+
+ //used from 2D and 3D
+ ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); }
+ bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
+
+ virtual RID particles_collision_instance_create(RID p_collision) override;
+ virtual void particles_collision_instance_free(RID p_rid) override;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
+};
+
+} // namespace RendererRD
+
+#endif // !PARTICLES_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
new file mode 100644
index 0000000000..329c23bad0
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -0,0 +1,2753 @@
+/*************************************************************************/
+/* texture_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "texture_storage.h"
+#include "../effects/copy_effects.h"
+#include "material_storage.h"
+
+using namespace RendererRD;
+
+///////////////////////////////////////////////////////////////////////////
+// CanvasTexture
+
+void CanvasTexture::clear_sets() {
+ if (cleared_cache) {
+ return;
+ }
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
+ RD::get_singleton()->free(uniform_sets[i][j]);
+ uniform_sets[i][j] = RID();
+ }
+ }
+ }
+ cleared_cache = true;
+}
+
+CanvasTexture::~CanvasTexture() {
+ clear_sets();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Texture
+
+void Texture::cleanup() {
+ if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) {
+ //erase this first, as it's a dependency of the one below
+ RD::get_singleton()->free(rd_texture_srgb);
+ }
+ if (RD::get_singleton()->texture_is_valid(rd_texture)) {
+ RD::get_singleton()->free(rd_texture);
+ }
+ if (canvas_texture) {
+ memdelete(canvas_texture);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// TextureStorage
+
+TextureStorage *TextureStorage::singleton = nullptr;
+
+TextureStorage *TextureStorage::get_singleton() {
+ return singleton;
+}
+
+TextureStorage::TextureStorage() {
+ singleton = this;
+
+ { //create default textures
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 128);
+ pv.set(i * 4 + 1, 128);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 128);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_D16_UNORM;
+ tf.width = 4;
+ tf.height = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> sv;
+ sv.resize(16 * 2);
+ uint16_t *ptr = (uint16_t *)sv.ptrw();
+ for (int i = 0; i < 16; i++) {
+ ptr[i] = Math::make_half_float(1.0f);
+ }
+
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(sv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_DEPTH] = RD::get_singleton()->texture_create(tf, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv);
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ {
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default cubemap
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 6;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ for (int i = 0; i < 6; i++) {
+ vpv.push_back(pv);
+ }
+ default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default cubemap array
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 6;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_CUBE;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ for (int i = 0; i < 6; i++) {
+ vpv.push_back(pv);
+ }
+ default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default cubemap white array
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 6;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_CUBE;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ for (int i = 0; i < 6; i++) {
+ vpv.push_back(pv);
+ }
+ default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default 3D
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.depth = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_3D;
+
+ Vector<uint8_t> pv;
+ pv.resize(64 * 4);
+ for (int i = 0; i < 64; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ for (int i = 0; i < 64; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default array
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 1;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { // default atlas texture
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ //take the chance and initialize decal atlas to something
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ decal_atlas.texture_srgb = decal_atlas.texture;
+ }
+ }
+
+ {
+ Vector<String> sdf_modes;
+ sdf_modes.push_back("\n#define MODE_LOAD\n");
+ sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
+ sdf_modes.push_back("\n#define MODE_PROCESS\n");
+ sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
+ sdf_modes.push_back("\n#define MODE_STORE\n");
+ sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
+
+ rt_sdf.shader.initialize(sdf_modes);
+
+ rt_sdf.shader_version = rt_sdf.shader.version_create();
+
+ for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
+ rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
+ }
+ }
+}
+
+TextureStorage::~TextureStorage() {
+ rt_sdf.shader.version_free(rt_sdf.shader_version);
+
+ if (decal_atlas.textures.size()) {
+ ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
+ }
+
+ if (decal_atlas.texture.is_valid()) {
+ RD::get_singleton()->free(decal_atlas.texture);
+ }
+
+ //def textures
+ for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
+ if (default_rd_textures[i].is_valid()) {
+ RD::get_singleton()->free(default_rd_textures[i]);
+ }
+ }
+
+ singleton = nullptr;
+}
+
+bool TextureStorage::can_create_resources_async() const {
+ return true;
+}
+
+/* Canvas Texture API */
+
+RID TextureStorage::canvas_texture_allocate() {
+ return canvas_texture_owner.allocate_rid();
+}
+
+void TextureStorage::canvas_texture_initialize(RID p_rid) {
+ canvas_texture_owner.initialize_rid(p_rid);
+}
+
+void TextureStorage::canvas_texture_free(RID p_rid) {
+ canvas_texture_owner.free(p_rid);
+}
+
+void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
+ switch (p_channel) {
+ case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
+ ct->diffuse = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
+ ct->normal_map = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
+ ct->specular = p_texture;
+ } break;
+ }
+
+ ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
+ ct->specular_color.r = p_specular_color.r;
+ ct->specular_color.g = p_specular_color.g;
+ ct->specular_color.b = p_specular_color.b;
+ ct->specular_color.a = p_shininess;
+ ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
+ ct->texture_filter = p_filter;
+ ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+ ct->texture_repeat = p_repeat;
+ ct->clear_sets();
+}
+
+bool TextureStorage::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) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ CanvasTexture *ct = nullptr;
+ Texture *t = get_texture(p_texture);
+
+ // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
+
+ if (t) {
+ //regular texture
+ if (!t->canvas_texture) {
+ t->canvas_texture = memnew(CanvasTexture);
+ t->canvas_texture->diffuse = p_texture;
+ }
+
+ ct = t->canvas_texture;
+ } else {
+ ct = get_canvas_texture(p_texture);
+ }
+
+ if (!ct) {
+ return false; //invalid texture RID
+ }
+
+ RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
+ ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
+
+ RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
+ ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
+
+ RID uniform_set = ct->uniform_sets[filter][repeat];
+ if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //create and update
+ Vector<RD::Uniform> uniforms;
+ { //diffuse
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+
+ t = get_texture(ct->diffuse);
+ if (!t) {
+ u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+ ct->size_cache = Size2i(1, 1);
+ } else {
+ u.append_id(t->rd_texture);
+ ct->size_cache = Size2i(t->width_2d, t->height_2d);
+ }
+ uniforms.push_back(u);
+ }
+ { //normal
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+
+ t = get_texture(ct->normal_map);
+ if (!t) {
+ u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
+ ct->use_normal_cache = false;
+ } else {
+ u.append_id(t->rd_texture);
+ ct->use_normal_cache = true;
+ }
+ uniforms.push_back(u);
+ }
+ { //specular
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+
+ t = get_texture(ct->specular);
+ if (!t) {
+ u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+ ct->use_specular_cache = false;
+ } else {
+ u.append_id(t->rd_texture);
+ ct->use_specular_cache = true;
+ }
+ uniforms.push_back(u);
+ }
+ { //sampler
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 3;
+ u.append_id(material_storage->sampler_rd_get_default(filter, repeat));
+ uniforms.push_back(u);
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
+ ct->uniform_sets[filter][repeat] = uniform_set;
+ ct->cleared_cache = false;
+ }
+
+ r_uniform_set = uniform_set;
+ r_size = ct->size_cache;
+ r_specular_shininess = ct->specular_color;
+ r_use_normal = ct->use_normal_cache;
+ r_use_specular = ct->use_specular_cache;
+
+ return true;
+}
+
+/* Texture API */
+
+RID TextureStorage::texture_allocate() {
+ return texture_owner.allocate_rid();
+}
+
+void TextureStorage::texture_free(RID p_texture) {
+ Texture *t = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!t);
+ ERR_FAIL_COND(t->is_render_target);
+
+ t->cleanup();
+
+ if (t->is_proxy && t->proxy_to.is_valid()) {
+ Texture *proxy_to = texture_owner.get_or_null(t->proxy_to);
+ if (proxy_to) {
+ proxy_to->proxies.erase(p_texture);
+ }
+ }
+
+ decal_atlas_remove_texture(p_texture);
+
+ for (int i = 0; i < t->proxies.size(); i++) {
+ Texture *p = texture_owner.get_or_null(t->proxies[i]);
+ ERR_CONTINUE(!p);
+ p->proxy_to = RID();
+ p->rd_texture = RID();
+ p->rd_texture_srgb = RID();
+ }
+
+ texture_owner.free(p_texture);
+}
+
+void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+ TextureToRDFormat ret_format;
+ Ref<Image> image = _validate_texture_format(p_image, ret_format);
+
+ Texture texture;
+
+ texture.type = Texture::TYPE_2D;
+
+ texture.width = p_image->get_width();
+ texture.height = p_image->get_height();
+ texture.layers = 1;
+ texture.mipmaps = p_image->get_mipmap_count() + 1;
+ texture.depth = 1;
+ texture.format = p_image->get_format();
+ texture.validated_format = image->get_format();
+
+ texture.rd_type = RD::TEXTURE_TYPE_2D;
+ texture.rd_format = ret_format.format;
+ texture.rd_format_srgb = ret_format.format_srgb;
+
+ RD::TextureFormat rd_format;
+ RD::TextureView rd_view;
+ { //attempt register
+ rd_format.format = texture.rd_format;
+ rd_format.width = texture.width;
+ rd_format.height = texture.height;
+ rd_format.depth = 1;
+ rd_format.array_layers = 1;
+ rd_format.mipmaps = texture.mipmaps;
+ 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) {
+ rd_format.shareable_formats.push_back(texture.rd_format);
+ rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+ }
+ }
+ {
+ rd_view.swizzle_r = ret_format.swizzle_r;
+ rd_view.swizzle_g = ret_format.swizzle_g;
+ rd_view.swizzle_b = ret_format.swizzle_b;
+ rd_view.swizzle_a = ret_format.swizzle_a;
+ }
+ Vector<uint8_t> data = image->get_data(); //use image data
+ Vector<Vector<uint8_t>> data_slices;
+ data_slices.push_back(data);
+ texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+ ERR_FAIL_COND(texture.rd_texture.is_null());
+ if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+ rd_view.format_override = texture.rd_format_srgb;
+ texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+ if (texture.rd_texture_srgb.is_null()) {
+ RD::get_singleton()->free(texture.rd_texture);
+ ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
+ }
+ }
+
+ //used for 2D, overridable
+ texture.width_2d = texture.width;
+ texture.height_2d = texture.height;
+ texture.is_render_target = false;
+ texture.rd_view = rd_view;
+ texture.is_proxy = false;
+
+ texture_owner.initialize_rid(p_texture, texture);
+}
+
+void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+ ERR_FAIL_COND(p_layers.size() == 0);
+
+ ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
+ ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0));
+
+ TextureToRDFormat ret_format;
+ Vector<Ref<Image>> images;
+ {
+ int valid_width = 0;
+ int valid_height = 0;
+ bool valid_mipmaps = false;
+ Image::Format valid_format = Image::FORMAT_MAX;
+
+ for (int i = 0; i < p_layers.size(); i++) {
+ ERR_FAIL_COND(p_layers[i]->is_empty());
+
+ if (i == 0) {
+ valid_width = p_layers[i]->get_width();
+ valid_height = p_layers[i]->get_height();
+ valid_format = p_layers[i]->get_format();
+ valid_mipmaps = p_layers[i]->has_mipmaps();
+ } else {
+ ERR_FAIL_COND(p_layers[i]->get_width() != valid_width);
+ ERR_FAIL_COND(p_layers[i]->get_height() != valid_height);
+ ERR_FAIL_COND(p_layers[i]->get_format() != valid_format);
+ ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps);
+ }
+
+ images.push_back(_validate_texture_format(p_layers[i], ret_format));
+ }
+ }
+
+ Texture texture;
+
+ texture.type = Texture::TYPE_LAYERED;
+ texture.layered_type = p_layered_type;
+
+ texture.width = p_layers[0]->get_width();
+ texture.height = p_layers[0]->get_height();
+ texture.layers = p_layers.size();
+ texture.mipmaps = p_layers[0]->get_mipmap_count() + 1;
+ texture.depth = 1;
+ texture.format = p_layers[0]->get_format();
+ texture.validated_format = images[0]->get_format();
+
+ switch (p_layered_type) {
+ case RS::TEXTURE_LAYERED_2D_ARRAY: {
+ texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } break;
+ case RS::TEXTURE_LAYERED_CUBEMAP: {
+ texture.rd_type = RD::TEXTURE_TYPE_CUBE;
+ } break;
+ case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: {
+ texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ } break;
+ }
+
+ texture.rd_format = ret_format.format;
+ texture.rd_format_srgb = ret_format.format_srgb;
+
+ RD::TextureFormat rd_format;
+ RD::TextureView rd_view;
+ { //attempt register
+ rd_format.format = texture.rd_format;
+ rd_format.width = texture.width;
+ rd_format.height = texture.height;
+ rd_format.depth = 1;
+ rd_format.array_layers = texture.layers;
+ rd_format.mipmaps = texture.mipmaps;
+ 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) {
+ rd_format.shareable_formats.push_back(texture.rd_format);
+ rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+ }
+ }
+ {
+ rd_view.swizzle_r = ret_format.swizzle_r;
+ rd_view.swizzle_g = ret_format.swizzle_g;
+ rd_view.swizzle_b = ret_format.swizzle_b;
+ rd_view.swizzle_a = ret_format.swizzle_a;
+ }
+ Vector<Vector<uint8_t>> data_slices;
+ for (int i = 0; i < images.size(); i++) {
+ Vector<uint8_t> data = images[i]->get_data(); //use image data
+ data_slices.push_back(data);
+ }
+ texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+ ERR_FAIL_COND(texture.rd_texture.is_null());
+ if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+ rd_view.format_override = texture.rd_format_srgb;
+ texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+ if (texture.rd_texture_srgb.is_null()) {
+ RD::get_singleton()->free(texture.rd_texture);
+ ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
+ }
+ }
+
+ //used for 2D, overridable
+ texture.width_2d = texture.width;
+ texture.height_2d = texture.height;
+ texture.is_render_target = false;
+ texture.rd_view = rd_view;
+ texture.is_proxy = false;
+
+ texture_owner.initialize_rid(p_texture, texture);
+}
+
+void TextureStorage::texture_3d_initialize(RID p_texture, 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(p_data.size() == 0);
+
+ 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) {
+ ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
+ }
+
+ TextureToRDFormat ret_format;
+ Image::Format validated_format = Image::FORMAT_MAX;
+ Vector<uint8_t> all_data;
+ uint32_t mipmap_count = 0;
+ Vector<Texture::BufferSlice3D> slices;
+ {
+ Vector<Ref<Image>> images;
+ uint32_t all_data_size = 0;
+ images.resize(p_data.size());
+ for (int i = 0; i < p_data.size(); i++) {
+ TextureToRDFormat f;
+ images.write[i] = _validate_texture_format(p_data[i], f);
+ if (i == 0) {
+ ret_format = f;
+ validated_format = images[0]->get_format();
+ }
+
+ all_data_size += images[i]->get_data().size();
+ }
+
+ all_data.resize(all_data_size); //consolidate all data here
+ uint32_t offset = 0;
+ Size2i prev_size;
+ for (int i = 0; i < p_data.size(); i++) {
+ uint32_t s = images[i]->get_data().size();
+
+ memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s);
+ {
+ Texture::BufferSlice3D slice;
+ slice.size.width = images[i]->get_width();
+ slice.size.height = images[i]->get_height();
+ slice.offset = offset;
+ slice.buffer_size = s;
+ slices.push_back(slice);
+ }
+ offset += s;
+
+ Size2i img_size(images[i]->get_width(), images[i]->get_height());
+ if (img_size != prev_size) {
+ mipmap_count++;
+ }
+ prev_size = img_size;
+ }
+ }
+
+ Texture texture;
+
+ texture.type = Texture::TYPE_3D;
+ texture.width = p_width;
+ texture.height = p_height;
+ texture.depth = p_depth;
+ texture.mipmaps = mipmap_count;
+ texture.format = p_data[0]->get_format();
+ texture.validated_format = validated_format;
+
+ texture.buffer_size_3d = all_data.size();
+ texture.buffer_slices_3d = slices;
+
+ texture.rd_type = RD::TEXTURE_TYPE_3D;
+ texture.rd_format = ret_format.format;
+ texture.rd_format_srgb = ret_format.format_srgb;
+
+ RD::TextureFormat rd_format;
+ RD::TextureView rd_view;
+ { //attempt register
+ rd_format.format = texture.rd_format;
+ rd_format.width = texture.width;
+ rd_format.height = texture.height;
+ rd_format.depth = texture.depth;
+ rd_format.array_layers = 1;
+ rd_format.mipmaps = texture.mipmaps;
+ 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) {
+ rd_format.shareable_formats.push_back(texture.rd_format);
+ rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+ }
+ }
+ {
+ rd_view.swizzle_r = ret_format.swizzle_r;
+ rd_view.swizzle_g = ret_format.swizzle_g;
+ rd_view.swizzle_b = ret_format.swizzle_b;
+ rd_view.swizzle_a = ret_format.swizzle_a;
+ }
+ Vector<Vector<uint8_t>> data_slices;
+ data_slices.push_back(all_data); //one slice
+
+ texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+ ERR_FAIL_COND(texture.rd_texture.is_null());
+ if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+ rd_view.format_override = texture.rd_format_srgb;
+ texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+ if (texture.rd_texture_srgb.is_null()) {
+ RD::get_singleton()->free(texture.rd_texture);
+ ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
+ }
+ }
+
+ //used for 2D, overridable
+ texture.width_2d = texture.width;
+ texture.height_2d = texture.height;
+ texture.is_render_target = false;
+ texture.rd_view = rd_view;
+ texture.is_proxy = false;
+
+ texture_owner.initialize_rid(p_texture, texture);
+}
+
+void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
+ Texture *tex = texture_owner.get_or_null(p_base);
+ ERR_FAIL_COND(!tex);
+ Texture proxy_tex = *tex;
+
+ proxy_tex.rd_view.format_override = tex->rd_format;
+ proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture);
+ if (proxy_tex.rd_texture_srgb.is_valid()) {
+ proxy_tex.rd_view.format_override = tex->rd_format_srgb;
+ proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture);
+ }
+ proxy_tex.proxy_to = p_base;
+ proxy_tex.is_render_target = false;
+ proxy_tex.is_proxy = true;
+ proxy_tex.proxies.clear();
+
+ texture_owner.initialize_rid(p_texture, proxy_tex);
+
+ tex->proxies.push_back(p_texture);
+}
+
+void TextureStorage::_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.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(tex->is_render_target);
+ ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height);
+ ERR_FAIL_COND(p_image->get_format() != tex->format);
+
+ if (tex->type == Texture::TYPE_LAYERED) {
+ ERR_FAIL_INDEX(p_layer, tex->layers);
+ }
+
+#ifdef TOOLS_ENABLED
+ tex->image_cache_2d.unref();
+#endif
+ TextureToRDFormat f;
+ Ref<Image> validated = _validate_texture_format(p_image, f);
+
+ RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data());
+}
+
+void TextureStorage::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 TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(tex->type != Texture::TYPE_3D);
+
+ Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data);
+ if (verr != Image::VALIDATE_3D_OK) {
+ ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
+ }
+
+ Vector<uint8_t> all_data;
+ {
+ Vector<Ref<Image>> images;
+ uint32_t all_data_size = 0;
+ images.resize(p_data.size());
+ for (int i = 0; i < p_data.size(); i++) {
+ Ref<Image> image = p_data[i];
+ if (image->get_format() != tex->validated_format) {
+ image = image->duplicate();
+ image->convert(tex->validated_format);
+ }
+ all_data_size += images[i]->get_data().size();
+ images.push_back(image);
+ }
+
+ all_data.resize(all_data_size); //consolidate all data here
+ uint32_t offset = 0;
+
+ for (int i = 0; i < p_data.size(); i++) {
+ uint32_t s = images[i]->get_data().size();
+ memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s);
+ offset += s;
+ }
+ }
+
+ RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data);
+}
+
+void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(!tex->is_proxy);
+ Texture *proxy_to = texture_owner.get_or_null(p_proxy_to);
+ ERR_FAIL_COND(!proxy_to);
+ ERR_FAIL_COND(proxy_to->is_proxy);
+
+ if (tex->proxy_to.is_valid()) {
+ //unlink proxy
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
+ RD::get_singleton()->free(tex->rd_texture);
+ tex->rd_texture = RID();
+ }
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
+ RD::get_singleton()->free(tex->rd_texture_srgb);
+ tex->rd_texture_srgb = RID();
+ }
+ Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to);
+ ERR_FAIL_COND(!prev_tex);
+ prev_tex->proxies.erase(p_texture);
+ }
+
+ *tex = *proxy_to;
+
+ tex->proxy_to = p_proxy_to;
+ tex->is_render_target = false;
+ tex->is_proxy = true;
+ tex->proxies.clear();
+ proxy_to->proxies.push_back(p_texture);
+
+ tex->rd_view.format_override = tex->rd_format;
+ tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
+ if (tex->rd_texture_srgb.is_valid()) {
+ tex->rd_view.format_override = tex->rd_format_srgb;
+ tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
+ }
+}
+
+//these two APIs can be used together or in combination with the others.
+void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
+ //this could be better optimized to reuse an existing image , done this way
+ //for now to get it working
+ Ref<Image> image;
+ image.instantiate();
+ image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->fill(Color(1, 0, 1, 1));
+
+ texture_2d_initialize(p_texture, image);
+}
+
+void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, 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;
+ image.instantiate();
+ image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->fill(Color(1, 0, 1, 1));
+
+ Vector<Ref<Image>> images;
+ if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
+ images.push_back(image);
+ } else {
+ //cube
+ for (int i = 0; i < 6; i++) {
+ images.push_back(image);
+ }
+ }
+
+ texture_2d_layered_initialize(p_texture, images, p_layered_type);
+}
+
+void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
+ //this could be better optimized to reuse an existing image , done this way
+ //for now to get it working
+ Ref<Image> image;
+ image.instantiate();
+ image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->fill(Color(1, 0, 1, 1));
+
+ Vector<Ref<Image>> images;
+ //cube
+ for (int i = 0; i < 4; i++) {
+ images.push_back(image);
+ }
+
+ texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
+}
+
+Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!tex, Ref<Image>());
+
+#ifdef TOOLS_ENABLED
+ if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
+ return tex->image_cache_2d;
+ }
+#endif
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+ ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
+ Ref<Image> image;
+ image.instantiate();
+ image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
+ if (tex->format != tex->validated_format) {
+ image->convert(tex->format);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
+ tex->image_cache_2d = image;
+ }
+#endif
+
+ return image;
+}
+
+Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) const {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!tex, Ref<Image>());
+
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer);
+ ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
+ Ref<Image> image;
+ image.instantiate();
+ image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
+ if (tex->format != tex->validated_format) {
+ image->convert(tex->format);
+ }
+
+ return image;
+}
+
+Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>());
+ ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>());
+
+ Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+
+ ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>());
+
+ Vector<Ref<Image>> ret;
+
+ for (int i = 0; i < tex->buffer_slices_3d.size(); i++) {
+ const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i];
+ ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>());
+ ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>());
+ Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size);
+
+ Ref<Image> img;
+ img.instantiate();
+ img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
+ ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
+ if (tex->format != tex->validated_format) {
+ img->convert(tex->format);
+ }
+
+ ret.push_back(img);
+ }
+
+ return ret;
+}
+
+void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy
+ Texture *by_tex = texture_owner.get_or_null(p_by_texture);
+ ERR_FAIL_COND(!by_tex);
+ ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy
+
+ if (tex == by_tex) {
+ return;
+ }
+
+ if (tex->rd_texture_srgb.is_valid()) {
+ RD::get_singleton()->free(tex->rd_texture_srgb);
+ }
+ RD::get_singleton()->free(tex->rd_texture);
+
+ if (tex->canvas_texture) {
+ memdelete(tex->canvas_texture);
+ tex->canvas_texture = nullptr;
+ }
+
+ Vector<RID> proxies_to_update = tex->proxies;
+ Vector<RID> proxies_to_redirect = by_tex->proxies;
+
+ *tex = *by_tex;
+
+ tex->proxies = proxies_to_update; //restore proxies, so they can be updated
+
+ if (tex->canvas_texture) {
+ tex->canvas_texture->diffuse = p_texture; //update
+ }
+
+ for (int i = 0; i < proxies_to_update.size(); i++) {
+ texture_proxy_update(proxies_to_update[i], p_texture);
+ }
+ for (int i = 0; i < proxies_to_redirect.size(); i++) {
+ texture_proxy_update(proxies_to_redirect[i], p_texture);
+ }
+ //delete last, so proxies can be updated
+ texture_owner.free(p_by_texture);
+
+ decal_atlas_mark_dirty_on_texture(p_texture);
+}
+
+void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
+
+ tex->width_2d = p_width;
+ tex->height_2d = p_height;
+}
+
+void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+
+ tex->path = p_path;
+}
+
+String TextureStorage::texture_get_path(RID p_texture) const {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!tex, String());
+
+ return tex->path;
+}
+
+void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+
+ tex->detect_3d_callback_ud = p_userdata;
+ tex->detect_3d_callback = p_callback;
+}
+
+void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+
+ tex->detect_normal_callback_ud = p_userdata;
+ tex->detect_normal_callback = p_callback;
+}
+
+void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+
+ tex->detect_roughness_callback_ud = p_userdata;
+ tex->detect_roughness_callback = p_callback;
+}
+
+void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
+}
+
+void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+}
+
+Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) {
+ return texture_2d_get_size(p_proxy);
+}
+
+Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) {
+ Ref<Image> image = p_image->duplicate();
+
+ switch (p_image->get_format()) {
+ case Image::FORMAT_L8: {
+ r_format.format = RD::DATA_FORMAT_R8_UNORM;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break; //luminance
+ case Image::FORMAT_LA8: {
+ r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G;
+ } break; //luminance-alpha
+ case Image::FORMAT_R8: {
+ r_format.format = RD::DATA_FORMAT_R8_UNORM;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_RG8: {
+ r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_RGB8: {
+ //this format is not mandatory for specification, check if supported first
+ if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break;
+ case Image::FORMAT_RGBA8: {
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ } break;
+ case Image::FORMAT_RGBA4444: {
+ r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ } break;
+ case Image::FORMAT_RGB565: {
+ r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ } break;
+ case Image::FORMAT_RF: {
+ r_format.format = RD::DATA_FORMAT_R32_SFLOAT;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break; //float
+ case Image::FORMAT_RGF: {
+ r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_RGBF: {
+ //this format is not mandatory for specification, check if supported first
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ image->convert(Image::FORMAT_RGBAF);
+ }
+
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_RGBAF: {
+ r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+ } break;
+ case Image::FORMAT_RH: {
+ r_format.format = RD::DATA_FORMAT_R16_SFLOAT;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break; //half float
+ case Image::FORMAT_RGH: {
+ r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break;
+ case Image::FORMAT_RGBH: {
+ //this format is not mandatory for specification, check if supported first
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ image->convert(Image::FORMAT_RGBAH);
+ }
+
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_RGBAH: {
+ r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+ } break;
+ case Image::FORMAT_RGBE9995: {
+ r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+#ifndef _MSC_VER
+#warning TODO need to make a function in Image to swap bits for this
+#endif
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY;
+ } break;
+ case Image::FORMAT_DXT1: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break; //s3tc bc1
+ case Image::FORMAT_DXT3: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+ } break; //bc2
+ case Image::FORMAT_DXT5: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ } break; //bc3
+ case Image::FORMAT_RGTC_R: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8_UNORM;
+ image->decompress();
+ image->convert(Image::FORMAT_R8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break;
+ case Image::FORMAT_RGTC_RG: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+ image->decompress();
+ image->convert(Image::FORMAT_RG8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break;
+ case Image::FORMAT_BPTC_RGBA: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+ } break; //btpc bc7
+ case Image::FORMAT_BPTC_RGBF: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBAH);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break; //float bc6h
+ case Image::FORMAT_BPTC_RGBFU: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBAH);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break; //unsigned float bc6hu
+ case Image::FORMAT_ETC2_R11: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8_UNORM;
+ image->decompress();
+ image->convert(Image::FORMAT_R8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break; //etc2
+ case Image::FORMAT_ETC2_R11S: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8_SNORM;
+ image->decompress();
+ image->convert(Image::FORMAT_R8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break; //signed: {} break; NOT srgb.
+ case Image::FORMAT_ETC2_RG11: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+ image->decompress();
+ image->convert(Image::FORMAT_RG8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_ETC2_RG11S: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8_SNORM;
+ image->decompress();
+ image->convert(Image::FORMAT_RG8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_ETC:
+ case Image::FORMAT_ETC2_RGB8: {
+ //ETC2 is backwards compatible with ETC1, and all modern platforms support it
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+ } break;
+ case Image::FORMAT_ETC2_RGBA8: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ } break;
+ case Image::FORMAT_ETC2_RGB8A1: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ } break;
+ case Image::FORMAT_ETC2_RA_AS_RG: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+ case Image::FORMAT_DXT5_RA_AS_RG: {
+ if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+ r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
+ r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK;
+ } else {
+ //not supported, reconvert
+ r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ image->decompress();
+ image->convert(Image::FORMAT_RGBA8);
+ }
+ r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A;
+ r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+ r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ } break;
+
+ default: {
+ }
+ }
+
+ return image;
+}
+
+/* DECAL API */
+
+RID TextureStorage::decal_atlas_get_texture() const {
+ return decal_atlas.texture;
+}
+
+RID TextureStorage::decal_atlas_get_texture_srgb() const {
+ return decal_atlas.texture_srgb;
+}
+
+RID TextureStorage::decal_allocate() {
+ return decal_owner.allocate_rid();
+}
+
+void TextureStorage::decal_initialize(RID p_decal) {
+ decal_owner.initialize_rid(p_decal, Decal());
+}
+
+void TextureStorage::decal_free(RID p_rid) {
+ Decal *decal = decal_owner.get_or_null(p_rid);
+ for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
+ if (decal->textures[i].is_valid() && owns_texture(decal->textures[i])) {
+ texture_remove_from_decal_atlas(decal->textures[i]);
+ }
+ }
+ decal->dependency.deleted_notify(p_rid);
+ decal_owner.free(p_rid);
+}
+
+void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->extents = p_extents;
+ decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
+
+ if (decal->textures[p_type] == p_texture) {
+ return;
+ }
+
+ ERR_FAIL_COND(p_texture.is_valid() && !owns_texture(p_texture));
+
+ if (decal->textures[p_type].is_valid() && owns_texture(decal->textures[p_type])) {
+ texture_remove_from_decal_atlas(decal->textures[p_type]);
+ }
+
+ decal->textures[p_type] = p_texture;
+
+ if (decal->textures[p_type].is_valid()) {
+ texture_add_to_decal_atlas(decal->textures[p_type]);
+ }
+
+ decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
+}
+
+void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->emission_energy = p_energy;
+}
+
+void TextureStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->albedo_mix = p_mix;
+}
+
+void TextureStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->modulate = p_modulate;
+}
+
+void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->cull_mask = p_layers;
+ decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->distance_fade = p_enabled;
+ decal->distance_fade_begin = p_begin;
+ decal->distance_fade_length = p_length;
+}
+
+void TextureStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->upper_fade = p_above;
+ decal->lower_fade = p_below;
+}
+
+void TextureStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->normal_fade = p_fade;
+}
+
+void TextureStorage::decal_atlas_mark_dirty_on_texture(RID p_texture) {
+ if (decal_atlas.textures.has(p_texture)) {
+ //belongs to decal atlas..
+
+ decal_atlas.dirty = true; //mark it dirty since it was most likely modified
+ }
+}
+
+void TextureStorage::decal_atlas_remove_texture(RID p_texture) {
+ if (decal_atlas.textures.has(p_texture)) {
+ decal_atlas.textures.erase(p_texture);
+ //there is not much a point of making it dirty, just let it be.
+ }
+}
+
+AABB TextureStorage::decal_get_aabb(RID p_decal) const {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND_V(!decal, AABB());
+
+ return AABB(-decal->extents, decal->extents * 2.0);
+}
+
+void TextureStorage::update_decal_atlas() {
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
+
+ if (!decal_atlas.dirty) {
+ return; //nothing to do
+ }
+
+ decal_atlas.dirty = false;
+
+ if (decal_atlas.texture.is_valid()) {
+ RD::get_singleton()->free(decal_atlas.texture);
+ decal_atlas.texture = RID();
+ decal_atlas.texture_srgb = RID();
+ decal_atlas.texture_mipmaps.clear();
+ }
+
+ int border = 1 << decal_atlas.mipmaps;
+
+ if (decal_atlas.textures.size()) {
+ //generate atlas
+ Vector<DecalAtlas::SortItem> itemsv;
+ itemsv.resize(decal_atlas.textures.size());
+ int base_size = 8;
+
+ int idx = 0;
+
+ for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) {
+ DecalAtlas::SortItem &si = itemsv.write[idx];
+
+ Texture *src_tex = get_texture(E.key);
+
+ si.size.width = (src_tex->width / border) + 1;
+ si.size.height = (src_tex->height / border) + 1;
+ si.pixel_size = Size2i(src_tex->width, src_tex->height);
+
+ if (base_size < si.size.width) {
+ base_size = nearest_power_of_2_templated(si.size.width);
+ }
+
+ si.texture = E.key;
+ idx++;
+ }
+
+ //sort items by size
+ itemsv.sort();
+
+ //attempt to create atlas
+ int item_count = itemsv.size();
+ DecalAtlas::SortItem *items = itemsv.ptrw();
+
+ int atlas_height = 0;
+
+ while (true) {
+ Vector<int> v_offsetsv;
+ v_offsetsv.resize(base_size);
+
+ int *v_offsets = v_offsetsv.ptrw();
+ memset(v_offsets, 0, sizeof(int) * base_size);
+
+ int max_height = 0;
+
+ for (int i = 0; i < item_count; i++) {
+ //best fit
+ DecalAtlas::SortItem &si = items[i];
+ int best_idx = -1;
+ int best_height = 0x7FFFFFFF;
+ for (int j = 0; j <= base_size - si.size.width; j++) {
+ int height = 0;
+ for (int k = 0; k < si.size.width; k++) {
+ int h = v_offsets[k + j];
+ if (h > height) {
+ height = h;
+ if (height > best_height) {
+ break; //already bad
+ }
+ }
+ }
+
+ if (height < best_height) {
+ best_height = height;
+ best_idx = j;
+ }
+ }
+
+ //update
+ for (int k = 0; k < si.size.width; k++) {
+ v_offsets[k + best_idx] = best_height + si.size.height;
+ }
+
+ si.pos.x = best_idx;
+ si.pos.y = best_height;
+
+ if (si.pos.y + si.size.height > max_height) {
+ max_height = si.pos.y + si.size.height;
+ }
+ }
+
+ if (max_height <= base_size * 2) {
+ atlas_height = max_height;
+ break; //good ratio, break;
+ }
+
+ base_size *= 2;
+ }
+
+ decal_atlas.size.width = base_size * border;
+ decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
+
+ for (int i = 0; i < item_count; i++) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
+ t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
+ t->uv_rect.size = items[i].pixel_size;
+
+ t->uv_rect.position /= Size2(decal_atlas.size);
+ t->uv_rect.size /= Size2(decal_atlas.size);
+ }
+ } else {
+ //use border as size, so it at least has enough mipmaps
+ decal_atlas.size.width = border;
+ decal_atlas.size.height = border;
+ }
+
+ //blit textures
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ 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.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);
+
+ decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1);
+
+ {
+ //create the framebuffer
+
+ Size2i s = decal_atlas.size;
+
+ for (int i = 0; i < decal_atlas.mipmaps; i++) {
+ DecalAtlas::MipMap mm;
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ mm.size = s;
+ decal_atlas.texture_mipmaps.push_back(mm);
+
+ s.width = MAX(1, s.width >> 1);
+ s.height = MAX(1, s.height >> 1);
+ }
+ {
+ //create the SRGB variant
+ RD::TextureView rd_view;
+ rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
+ }
+ }
+
+ RID prev_texture;
+ for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
+ const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
+
+ Color clear_color(0, 0, 0, 0);
+
+ if (decal_atlas.textures.size()) {
+ if (i == 0) {
+ Vector<Color> cc;
+ cc.push_back(clear_color);
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
+
+ for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key);
+ Texture *src_tex = get_texture(E.key);
+ copy_effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
+ }
+
+ RD::get_singleton()->draw_list_end();
+
+ prev_texture = mm.texture;
+ } else {
+ copy_effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
+ prev_texture = mm.texture;
+ }
+ } else {
+ RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1);
+ }
+ }
+}
+
+void TextureStorage::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;
+ t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
+ decal_atlas.textures[p_texture] = t;
+ decal_atlas.dirty = true;
+ } else {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ t->users++;
+ if (p_panorama_to_dp) {
+ t->panorama_to_dp_users++;
+ }
+ }
+}
+
+void TextureStorage::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--;
+ if (p_panorama_to_dp) {
+ ERR_FAIL_COND(t->panorama_to_dp_users == 0);
+ t->panorama_to_dp_users--;
+ }
+ if (t->users == 0) {
+ decal_atlas.textures.erase(p_texture);
+ //do not mark it dirty, there is no need to since it remains working
+ }
+}
+
+/* RENDER TARGET API */
+
+void TextureStorage::_clear_render_target(RenderTarget *rt) {
+ //free in reverse dependency order
+ if (rt->framebuffer.is_valid()) {
+ RD::get_singleton()->free(rt->framebuffer);
+ rt->framebuffer_uniform_set = RID(); //chain deleted
+ }
+
+ if (rt->color.is_valid()) {
+ RD::get_singleton()->free(rt->color);
+ }
+
+ if (rt->backbuffer.is_valid()) {
+ RD::get_singleton()->free(rt->backbuffer);
+ rt->backbuffer = RID();
+ rt->backbuffer_mipmaps.clear();
+ rt->backbuffer_uniform_set = RID(); //chain deleted
+ }
+
+ _render_target_clear_sdf(rt);
+
+ rt->framebuffer = RID();
+ rt->color = RID();
+}
+
+void TextureStorage::_update_render_target(RenderTarget *rt) {
+ if (rt->texture.is_null()) {
+ //create a placeholder until updated
+ rt->texture = texture_allocate();
+ texture_2d_placeholder_initialize(rt->texture);
+ Texture *tex = get_texture(rt->texture);
+ tex->is_render_target = true;
+ }
+
+ _clear_render_target(rt);
+
+ if (rt->size.width == 0 || rt->size.height == 0) {
+ return;
+ }
+ //until we implement support for HDR monitors (and render target is attached to screen), this is enough.
+ rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
+
+ RD::TextureFormat rd_format;
+ RD::TextureView rd_view;
+ { //attempt register
+ rd_format.format = rt->color_format;
+ rd_format.width = rt->size.width;
+ rd_format.height = rt->size.height;
+ rd_format.depth = 1;
+ rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
+ rd_format.mipmaps = 1;
+ if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ 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);
+ rd_format.shareable_formats.push_back(rt->color_format_srgb);
+ }
+
+ rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
+ ERR_FAIL_COND(rt->color.is_null());
+
+ Vector<RID> fb_textures;
+ fb_textures.push_back(rt->color);
+ rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
+ if (rt->framebuffer.is_null()) {
+ _clear_render_target(rt);
+ ERR_FAIL_COND(rt->framebuffer.is_null());
+ }
+
+ { //update texture
+
+ Texture *tex = get_texture(rt->texture);
+
+ //free existing textures
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
+ RD::get_singleton()->free(tex->rd_texture);
+ }
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
+ RD::get_singleton()->free(tex->rd_texture_srgb);
+ }
+
+ tex->rd_texture = RID();
+ tex->rd_texture_srgb = RID();
+
+ //create shared textures to the color buffer,
+ //so transparent can be supported
+ RD::TextureView view;
+ view.format_override = rt->color_format;
+ if (!rt->is_transparent) {
+ view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ }
+ tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
+ if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
+ view.format_override = rt->color_format_srgb;
+ tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
+ }
+ tex->rd_view = view;
+ tex->width = rt->size.width;
+ tex->height = rt->size.height;
+ tex->width_2d = rt->size.width;
+ tex->height_2d = rt->size.height;
+ tex->rd_format = rt->color_format;
+ tex->rd_format_srgb = rt->color_format_srgb;
+ tex->format = rt->image_format;
+
+ Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
+ for (int i = 0; i < proxies.size(); i++) {
+ texture_proxy_update(proxies[i], rt->texture);
+ }
+ }
+}
+
+void TextureStorage::_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);
+ RD::TextureFormat tf;
+ tf.format = rt->color_format;
+ tf.width = rt->size.width;
+ tf.height = rt->size.height;
+ 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;
+
+ rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rt->backbuffer, "Render Target Back Buffer");
+ rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
+ RD::get_singleton()->set_resource_name(rt->backbuffer_mipmap0, "Back Buffer slice mipmap 0");
+
+ {
+ Vector<RID> fb_tex;
+ fb_tex.push_back(rt->backbuffer_mipmap0);
+ rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+
+ if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
+ //the new one will require the backbuffer.
+ RD::get_singleton()->free(rt->framebuffer_uniform_set);
+ rt->framebuffer_uniform_set = RID();
+ }
+ //create mipmaps
+ for (uint32_t i = 1; i < mipmaps_required; i++) {
+ RID mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
+ RD::get_singleton()->set_resource_name(mipmap, "Back Buffer slice mip: " + itos(i));
+
+ rt->backbuffer_mipmaps.push_back(mipmap);
+ }
+}
+
+RID TextureStorage::render_target_create() {
+ RenderTarget render_target;
+
+ render_target.was_used = false;
+ render_target.clear_requested = false;
+
+ _update_render_target(&render_target);
+ return render_target_owner.make_rid(render_target);
+}
+
+void TextureStorage::render_target_free(RID p_rid) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_rid);
+
+ _clear_render_target(rt);
+
+ if (rt->texture.is_valid()) {
+ Texture *tex = get_texture(rt->texture);
+ tex->is_render_target = false;
+ texture_free(rt->texture);
+ }
+
+ render_target_owner.free(p_rid);
+}
+
+void TextureStorage::render_target_set_position(RID p_render_target, int p_x, int p_y) {
+ //unused for this render target
+}
+
+void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
+ rt->size.x = p_width;
+ rt->size.y = p_height;
+ rt->view_count = p_view_count;
+ _update_render_target(rt);
+ }
+}
+
+RID TextureStorage::render_target_get_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->texture;
+}
+
+void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+}
+
+void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->is_transparent = p_is_transparent;
+ _update_render_target(rt);
+}
+
+void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_value) {
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+ return rt->was_used;
+}
+
+void TextureStorage::render_target_set_as_unused(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->was_used = false;
+}
+
+Size2 TextureStorage::render_target_get_size(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Size2());
+
+ return rt->size;
+}
+
+RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->framebuffer;
+}
+
+RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->color;
+}
+
+RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ return rt->backbuffer;
+}
+
+RID TextureStorage::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ return rt->backbuffer_fb;
+}
+
+void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = true;
+ rt->clear_color = p_clear_color;
+}
+
+bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+ return rt->clear_requested;
+}
+
+Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Color());
+ return rt->clear_color;
+}
+
+void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_do_clear_request(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->clear_requested) {
+ return;
+ }
+ Vector<Color> clear_colors;
+ clear_colors.push_back(rt->clear_color);
+ RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
+ RD::get_singleton()->draw_list_end();
+ rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
+ return;
+ }
+
+ rt->sdf_oversize = p_size;
+ rt->sdf_scale = p_scale;
+
+ _render_target_clear_sdf(rt);
+}
+
+Rect2i TextureStorage::_render_target_get_sdf_rect(const RenderTarget *rt) const {
+ Size2i margin;
+ int scale;
+ switch (rt->sdf_oversize) {
+ case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
+ scale = 100;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
+ scale = 120;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
+ scale = 150;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
+ scale = 200;
+ } break;
+ default: {
+ }
+ }
+
+ margin = (rt->size * scale / 100) - rt->size;
+
+ Rect2i r(Vector2i(), rt->size);
+ r.position -= margin;
+ r.size += margin * 2;
+
+ return r;
+}
+
+Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Rect2i());
+
+ return _render_target_get_sdf_rect(rt);
+}
+
+void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->sdf_enabled = p_enabled;
+}
+
+bool TextureStorage::render_target_is_sdf_enabled(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->sdf_enabled;
+}
+
+RID TextureStorage::render_target_get_sdf_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ if (rt->sdf_buffer_read.is_null()) {
+ // no texture, create a dummy one for the 2D uniform set
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ memset(pv.ptrw(), 0, 16 * 4);
+ Vector<Vector<uint8_t>> vpv;
+
+ rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ return rt->sdf_buffer_read;
+}
+
+void TextureStorage::_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);
+ rt->sdf_buffer_read = RID();
+ }
+
+ Size2i size = _render_target_get_sdf_rect(rt).size;
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8_UNORM;
+ 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.texture_type = RD::TEXTURE_TYPE_2D;
+
+ rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ Vector<RID> write_fb;
+ write_fb.push_back(rt->sdf_buffer_write);
+ rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
+ }
+
+ int scale;
+ switch (rt->sdf_scale) {
+ case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
+ scale = 100;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+ scale = 50;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+ scale = 25;
+ } break;
+ default: {
+ scale = 100;
+ } break;
+ }
+
+ rt->process_size = size * scale / 100;
+ rt->process_size.x = MAX(rt->process_size.x, 1);
+ rt->process_size.y = MAX(rt->process_size.y, 1);
+
+ tformat.format = RD::DATA_FORMAT_R16G16_SINT;
+ tformat.width = rt->process_size.width;
+ tformat.height = rt->process_size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ tformat.format = RD::DATA_FORMAT_R16_SNORM;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(rt->sdf_buffer_write);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.append_id(rt->sdf_buffer_read);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.append_id(rt->sdf_buffer_process[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 4;
+ u.append_id(rt->sdf_buffer_process[1]);
+ uniforms.push_back(u);
+ }
+
+ rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+ RID aux2 = uniforms.write[2].get_id(0);
+ RID aux3 = uniforms.write[3].get_id(0);
+ uniforms.write[2].set_id(0, aux3);
+ uniforms.write[3].set_id(0, aux2);
+ rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+ }
+}
+
+void TextureStorage::_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();
+ }
+ if (rt->sdf_buffer_write_fb.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_write);
+ RD::get_singleton()->free(rt->sdf_buffer_process[0]);
+ RD::get_singleton()->free(rt->sdf_buffer_process[1]);
+ rt->sdf_buffer_write = RID();
+ rt->sdf_buffer_write_fb = RID();
+ rt->sdf_buffer_process[0] = RID();
+ rt->sdf_buffer_process[1] = RID();
+ rt->sdf_buffer_process_uniform_sets[0] = RID();
+ rt->sdf_buffer_process_uniform_sets[1] = RID();
+ }
+}
+
+RID TextureStorage::render_target_get_sdf_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->sdf_buffer_write_fb.is_null()) {
+ _render_target_allocate_sdf(rt);
+ }
+
+ return rt->sdf_buffer_write_fb;
+}
+void TextureStorage::render_target_sdf_process(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
+
+ RenderTargetSDF::PushConstant push_constant;
+
+ Rect2i r = _render_target_get_sdf_rect(rt);
+
+ push_constant.size[0] = r.size.width;
+ push_constant.size[1] = r.size.height;
+ push_constant.stride = 0;
+ push_constant.shift = 0;
+ push_constant.base_size[0] = r.size.width;
+ push_constant.base_size[1] = r.size.height;
+
+ bool shrink = false;
+
+ switch (rt->sdf_scale) {
+ case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+ push_constant.size[0] >>= 1;
+ push_constant.size[1] >>= 1;
+ push_constant.shift = 1;
+ shrink = true;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+ push_constant.size[0] >>= 2;
+ push_constant.size[1] >>= 2;
+ push_constant.shift = 2;
+ shrink = true;
+ } break;
+ default: {
+ };
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ /* Load */
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+
+ /* Process */
+
+ int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ bool swap = false;
+
+ //jumpflood
+ while (stride > 0) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+ push_constant.stride = stride;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+ stride /= 2;
+ swap = !swap;
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ /* Store */
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
+
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).intersection(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ // TODO figure out stereo support here
+
+ //single texture copy for backbuffer
+ //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
+ copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+
+ if (!p_gen_mipmaps) {
+ return;
+ }
+ RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps");
+ //then mipmap blur
+ RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
+
+ for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ region.size.y = MAX(1, region.size.y >> 1);
+
+ RID mipmap = rt->backbuffer_mipmaps[i];
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+ prev_texture = mipmap;
+ }
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).intersection(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //single texture copy for backbuffer
+ copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+}
+
+void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).intersection(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+ RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
+ //then mipmap blur
+ RID prev_texture = rt->backbuffer_mipmap0;
+
+ for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ region.size.y = MAX(1, region.size.y >> 1);
+
+ RID mipmap = rt->backbuffer_mipmaps[i];
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+ prev_texture = mipmap;
+ }
+ RD::get_singleton()->draw_command_end_label();
+}
+
+RID TextureStorage::render_target_get_framebuffer_uniform_set(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ return rt->framebuffer_uniform_set;
+}
+RID TextureStorage::render_target_get_backbuffer_uniform_set(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ return rt->backbuffer_uniform_set;
+}
+
+void TextureStorage::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->framebuffer_uniform_set = p_uniform_set;
+}
+
+void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->backbuffer_uniform_set = p_uniform_set;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
new file mode 100644
index 0000000000..901f764085
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -0,0 +1,567 @@
+/*************************************************************************/
+/* texture_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEXTURE_STORAGE_RD_H
+#define TEXTURE_STORAGE_RD_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/texture_storage.h"
+
+namespace RendererRD {
+
+enum DefaultRDTexture {
+ DEFAULT_RD_TEXTURE_WHITE,
+ DEFAULT_RD_TEXTURE_BLACK,
+ DEFAULT_RD_TEXTURE_NORMAL,
+ DEFAULT_RD_TEXTURE_ANISO,
+ DEFAULT_RD_TEXTURE_DEPTH,
+ DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
+ DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
+ DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
+ DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
+ DEFAULT_RD_TEXTURE_3D_WHITE,
+ DEFAULT_RD_TEXTURE_3D_BLACK,
+ DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
+ DEFAULT_RD_TEXTURE_2D_UINT,
+ DEFAULT_RD_TEXTURE_MAX
+};
+
+class CanvasTexture {
+public:
+ RID diffuse;
+ RID normal_map;
+ RID specular;
+ Color specular_color = Color(1, 1, 1, 1);
+ float shininess = 1.0;
+
+ RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+ RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+ RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
+ Size2i size_cache = Size2i(1, 1);
+ bool use_normal_cache = false;
+ bool use_specular_cache = false;
+ bool cleared_cache = true;
+
+ void clear_sets();
+ ~CanvasTexture();
+};
+
+class Texture {
+public:
+ enum Type {
+ TYPE_2D,
+ TYPE_LAYERED,
+ TYPE_3D
+ };
+
+ Type type;
+ RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
+
+ RenderingDevice::TextureType rd_type;
+ RID rd_texture;
+ RID rd_texture_srgb;
+ RenderingDevice::DataFormat rd_format;
+ RenderingDevice::DataFormat rd_format_srgb;
+
+ RD::TextureView rd_view;
+
+ Image::Format format;
+ Image::Format validated_format;
+
+ int width;
+ int height;
+ int depth;
+ int layers;
+ int mipmaps;
+
+ int height_2d;
+ int width_2d;
+
+ struct BufferSlice3D {
+ Size2i size;
+ uint32_t offset = 0;
+ uint32_t buffer_size = 0;
+ };
+ Vector<BufferSlice3D> buffer_slices_3d;
+ uint32_t buffer_size_3d = 0;
+
+ bool is_render_target;
+ bool is_proxy;
+
+ Ref<Image> image_cache_2d;
+ String path;
+
+ RID proxy_to;
+ Vector<RID> proxies;
+
+ HashSet<RID> lightmap_users;
+
+ RS::TextureDetectCallback detect_3d_callback = nullptr;
+ void *detect_3d_callback_ud = nullptr;
+
+ RS::TextureDetectCallback detect_normal_callback = nullptr;
+ void *detect_normal_callback_ud = nullptr;
+
+ RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
+ void *detect_roughness_callback_ud = nullptr;
+
+ CanvasTexture *canvas_texture = nullptr;
+
+ void cleanup();
+};
+
+struct DecalAtlas {
+ struct Texture {
+ int panorama_to_dp_users;
+ int users;
+ Rect2 uv_rect;
+ };
+
+ struct SortItem {
+ RID texture;
+ Size2i pixel_size;
+ Size2i size;
+ Point2i pos;
+
+ bool operator<(const SortItem &p_item) const {
+ //sort larger to smaller
+ if (size.height == p_item.size.height) {
+ return size.width > p_item.size.width;
+ } else {
+ return size.height > p_item.size.height;
+ }
+ }
+ };
+
+ HashMap<RID, Texture> textures;
+ bool dirty = true;
+ int mipmaps = 5;
+
+ RID texture;
+ RID texture_srgb;
+ struct MipMap {
+ RID fb;
+ RID texture;
+ Size2i size;
+ };
+ Vector<MipMap> texture_mipmaps;
+
+ Size2i size;
+};
+
+struct Decal {
+ Vector3 extents = Vector3(1, 1, 1);
+ RID textures[RS::DECAL_TEXTURE_MAX];
+ float emission_energy = 1.0;
+ float albedo_mix = 1.0;
+ Color modulate = Color(1, 1, 1, 1);
+ uint32_t cull_mask = (1 << 20) - 1;
+ float upper_fade = 0.3;
+ float lower_fade = 0.3;
+ bool distance_fade = false;
+ float distance_fade_begin = 10;
+ float distance_fade_length = 1;
+ float normal_fade = 0.0;
+
+ RendererStorage::Dependency dependency;
+};
+
+struct RenderTarget {
+ Size2i size;
+ uint32_t view_count;
+ RID framebuffer;
+ RID color;
+
+ //used for retrieving from CPU
+ RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ Image::Format image_format = Image::FORMAT_L8;
+
+ bool is_transparent = false;
+
+ bool sdf_enabled = false;
+
+ RID backbuffer; //used for effects
+ RID backbuffer_fb;
+ RID backbuffer_mipmap0;
+
+ Vector<RID> backbuffer_mipmaps;
+
+ RID framebuffer_uniform_set;
+ RID backbuffer_uniform_set;
+
+ RID sdf_buffer_write;
+ RID sdf_buffer_write_fb;
+ RID sdf_buffer_process[2];
+ RID sdf_buffer_read;
+ RID sdf_buffer_process_uniform_sets[2];
+ RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
+ RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
+ Size2i process_size;
+
+ //texture generated for this owner (nor RD).
+ RID texture;
+ bool was_used;
+
+ //clear request
+ bool clear_requested;
+ Color clear_color;
+};
+
+struct RenderTargetSDF {
+ enum {
+ SHADER_LOAD,
+ SHADER_LOAD_SHRINK,
+ SHADER_PROCESS,
+ SHADER_PROCESS_OPTIMIZED,
+ SHADER_STORE,
+ SHADER_STORE_SHRINK,
+ SHADER_MAX
+ };
+
+ struct PushConstant {
+ int32_t size[2];
+ int32_t stride;
+ int32_t shift;
+ int32_t base_size[2];
+ int32_t pad[2];
+ };
+
+ CanvasSdfShaderRD shader;
+ RID shader_version;
+ RID pipelines[SHADER_MAX];
+};
+
+class TextureStorage : public RendererTextureStorage {
+private:
+ static TextureStorage *singleton;
+
+ /* Canvas Texture API */
+
+ RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
+
+ /* Texture API */
+
+ //textures can be created from threads, so this RID_Owner is thread safe
+ mutable RID_Owner<Texture, true> texture_owner;
+
+ struct TextureToRDFormat {
+ RD::DataFormat format;
+ RD::DataFormat format_srgb;
+ RD::TextureSwizzle swizzle_r;
+ RD::TextureSwizzle swizzle_g;
+ RD::TextureSwizzle swizzle_b;
+ RD::TextureSwizzle swizzle_a;
+ TextureToRDFormat() {
+ format = RD::DATA_FORMAT_MAX;
+ format_srgb = RD::DATA_FORMAT_MAX;
+ swizzle_r = RD::TEXTURE_SWIZZLE_R;
+ swizzle_g = RD::TEXTURE_SWIZZLE_G;
+ swizzle_b = RD::TEXTURE_SWIZZLE_B;
+ swizzle_a = RD::TEXTURE_SWIZZLE_A;
+ }
+ };
+
+ Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
+ void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false);
+
+ /* DECAL API */
+
+ DecalAtlas decal_atlas;
+
+ mutable RID_Owner<Decal, true> decal_owner;
+
+ /* RENDER TARGET API */
+
+ mutable RID_Owner<RenderTarget> render_target_owner;
+
+ void _clear_render_target(RenderTarget *rt);
+ void _update_render_target(RenderTarget *rt);
+ void _create_render_target_backbuffer(RenderTarget *rt);
+ void _render_target_allocate_sdf(RenderTarget *rt);
+ void _render_target_clear_sdf(RenderTarget *rt);
+ Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
+
+ RenderTargetSDF rt_sdf;
+
+public:
+ static TextureStorage *get_singleton();
+
+ RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
+
+ _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
+ return default_rd_textures[p_texture];
+ }
+
+ TextureStorage();
+ virtual ~TextureStorage();
+
+ /* Canvas Texture API */
+
+ CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
+ bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+
+ virtual RID canvas_texture_allocate() override;
+ virtual void canvas_texture_initialize(RID p_rid) override;
+ virtual void canvas_texture_free(RID p_rid) override;
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
+
+ virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
+ virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+
+ bool 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);
+
+ /* Texture API */
+
+ Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
+ bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
+
+ virtual bool can_create_resources_async() const override;
+
+ virtual RID texture_allocate() override;
+ virtual void texture_free(RID p_rid) override;
+
+ virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
+ virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
+ virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
+ virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
+
+ virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
+ virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
+ virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
+
+ //these two APIs can be used together or in combination with the others.
+ virtual void texture_2d_placeholder_initialize(RID p_texture) override;
+ virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
+ virtual void texture_3d_placeholder_initialize(RID p_texture) override;
+
+ virtual Ref<Image> texture_2d_get(RID p_texture) const override;
+ virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override;
+ virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override;
+
+ virtual void texture_replace(RID p_texture, RID p_by_texture) override;
+ virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
+
+ virtual void texture_set_path(RID p_texture, const String &p_path) override;
+ virtual String texture_get_path(RID p_texture) const override;
+
+ virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+ virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+ virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override;
+
+ virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
+
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override;
+
+ virtual Size2 texture_size_with_proxy(RID p_proxy) override;
+
+ //internal usage
+
+ _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
+ if (p_texture.is_null()) {
+ return RID();
+ }
+ RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+
+ if (!tex) {
+ return RID();
+ }
+ return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+ }
+
+ _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) {
+ if (p_texture.is_null()) {
+ return Size2i();
+ }
+ RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+
+ if (!tex) {
+ return Size2i();
+ }
+ return Size2i(tex->width_2d, tex->height_2d);
+ }
+
+ /* DECAL API */
+
+ void update_decal_atlas();
+
+ Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
+ bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
+
+ RID decal_atlas_get_texture() const;
+ RID decal_atlas_get_texture_srgb() const;
+ _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ if (!t) {
+ return Rect2();
+ }
+
+ return t->uv_rect;
+ }
+
+ virtual RID decal_allocate() override;
+ virtual void decal_initialize(RID p_decal) override;
+ virtual void decal_free(RID p_rid) override;
+
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
+
+ void decal_atlas_mark_dirty_on_texture(RID p_texture);
+ void decal_atlas_remove_texture(RID p_texture);
+
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
+
+ _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->extents;
+ }
+
+ _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->textures[p_texture];
+ }
+
+ _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->modulate;
+ }
+
+ _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->emission_energy;
+ }
+
+ _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->albedo_mix;
+ }
+
+ _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->cull_mask;
+ }
+
+ _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->upper_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->lower_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->normal_fade;
+ }
+
+ _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->distance_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->distance_fade_begin;
+ }
+
+ _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->distance_fade_length;
+ }
+
+ virtual AABB decal_get_aabb(RID p_decal) const override;
+
+ /* RENDER TARGET API */
+
+ RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
+ bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+
+ virtual RID render_target_create() override;
+ virtual void render_target_free(RID p_rid) override;
+
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
+ virtual RID render_target_get_texture(RID p_render_target) override;
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+ virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
+ virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
+ virtual bool render_target_was_used(RID p_render_target) override;
+ virtual void render_target_set_as_unused(RID p_render_target) override;
+
+ void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
+ void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
+ void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
+ RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
+
+ virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
+ virtual bool render_target_is_clear_requested(RID p_render_target) override;
+ virtual Color render_target_get_clear_request_color(RID p_render_target) override;
+ virtual void render_target_disable_clear_request(RID p_render_target) override;
+ virtual void render_target_do_clear_request(RID p_render_target) override;
+
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
+ RID render_target_get_sdf_texture(RID p_render_target);
+ RID render_target_get_sdf_framebuffer(RID p_render_target);
+ void render_target_sdf_process(RID p_render_target);
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
+ virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
+ bool render_target_is_sdf_enabled(RID p_render_target) const;
+
+ Size2 render_target_get_size(RID p_render_target);
+ RID render_target_get_rd_framebuffer(RID p_render_target);
+ RID render_target_get_rd_texture(RID p_render_target);
+ RID render_target_get_rd_backbuffer(RID p_render_target);
+ RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
+
+ RID render_target_get_framebuffer_uniform_set(RID p_render_target);
+ RID render_target_get_backbuffer_uniform_set(RID p_render_target);
+
+ void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
+ void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
+};
+
+} // namespace RendererRD
+
+#endif // !_TEXTURE_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
new file mode 100644
index 0000000000..84529ca400
--- /dev/null
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* uniform_set_cache_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "uniform_set_cache_rd.h"
+
+UniformSetCacheRD *UniformSetCacheRD::singleton = nullptr;
+
+void UniformSetCacheRD::_invalidate(Cache *p_cache) {
+ if (p_cache->prev) {
+ p_cache->prev->next = p_cache->next;
+ } else {
+ // At beginning of table
+ uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE;
+ hash_table[table_idx] = p_cache->next;
+ }
+
+ if (p_cache->next) {
+ p_cache->next->prev = p_cache->prev;
+ }
+
+ cache_allocator.free(p_cache);
+ cache_instances_used--;
+}
+void UniformSetCacheRD::_uniform_set_invalidation_callback(void *p_userdata) {
+ singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata));
+}
+
+UniformSetCacheRD::UniformSetCacheRD() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+}
+
+UniformSetCacheRD::~UniformSetCacheRD() {
+ if (cache_instances_used > 0) {
+ ERR_PRINT("At exit: " + itos(cache_instances_used) + " uniform set cache instance(s) still in use.");
+ }
+}
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
new file mode 100644
index 0000000000..e49cf4dafa
--- /dev/null
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
@@ -0,0 +1,221 @@
+/*************************************************************************/
+/* uniform_set_cache_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef UNIFORM_SET_CACHE_H
+#define UNIFORM_SET_CACHE_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "servers/rendering/rendering_device.h"
+
+class UniformSetCacheRD : public Object {
+ GDCLASS(UniformSetCacheRD, Object)
+
+ struct Cache {
+ Cache *prev = nullptr;
+ Cache *next = nullptr;
+ uint32_t hash = 0;
+ RID shader;
+ uint32_t set = 0;
+ RID cache;
+ LocalVector<RD::Uniform> uniforms;
+ };
+
+ PagedAllocator<Cache> cache_allocator;
+
+ enum {
+ HASH_TABLE_SIZE = 16381 // Prime
+ };
+
+ Cache *hash_table[HASH_TABLE_SIZE] = {};
+
+ static _FORCE_INLINE_ uint32_t _hash_uniform(const RD::Uniform &u, uint32_t h) {
+ h = hash_djb2_one_32(u.uniform_type, h);
+ h = hash_djb2_one_32(u.binding, h);
+ uint32_t rsize = u.get_id_count();
+ for (uint32_t j = 0; j < rsize; j++) {
+ h = hash_djb2_one_64(u.get_id(j).get_id(), h);
+ }
+ return h;
+ }
+
+ static _FORCE_INLINE_ bool _compare_uniform(const RD::Uniform &a, const RD::Uniform &b) {
+ if (a.binding != b.binding) {
+ return false;
+ }
+ if (a.uniform_type != b.uniform_type) {
+ return false;
+ }
+ uint32_t rsize = a.get_id_count();
+ if (rsize != b.get_id_count()) {
+ return false;
+ }
+ for (uint32_t j = 0; j < rsize; j++) {
+ if (a.get_id(j) != b.get_id(j)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ _FORCE_INLINE_ uint32_t _hash_args(uint32_t h, const RD::Uniform &arg) {
+ return _hash_uniform(arg, h);
+ }
+
+ template <typename... Args>
+ uint32_t _hash_args(uint32_t h, const RD::Uniform &arg, Args... args) {
+ h = _hash_uniform(arg, h);
+ return _hash_args(h, args...);
+ }
+
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RD::Uniform> &uniforms, const RD::Uniform &arg) {
+ return _compare_uniform(uniforms[idx], arg);
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RD::Uniform> &uniforms, const RD::Uniform &arg, Args... args) {
+ if (!_compare_uniform(uniforms[idx], arg)) {
+ return false;
+ }
+ return _compare_args(idx + 1, uniforms, args...);
+ }
+
+ _FORCE_INLINE_ void _create_args(Vector<RD::Uniform> &uniforms, const RD::Uniform &arg) {
+ uniforms.push_back(arg);
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ void _create_args(Vector<RD::Uniform> &uniforms, const RD::Uniform &arg, Args... args) {
+ uniforms.push_back(arg);
+ _create_args(uniforms, args...);
+ }
+
+ static UniformSetCacheRD *singleton;
+
+ uint32_t cache_instances_used = 0;
+
+ void _invalidate(Cache *p_cache);
+ static void _uniform_set_invalidation_callback(void *p_userdata);
+
+ RID _allocate_from_uniforms(RID p_shader, uint32_t p_set, uint32_t p_hash, uint32_t p_table_idx, const Vector<RD::Uniform> &p_uniforms) {
+ RID rid = RD::get_singleton()->uniform_set_create(p_uniforms, p_shader, p_set);
+ ERR_FAIL_COND_V(rid.is_null(), rid);
+
+ Cache *c = cache_allocator.alloc();
+ c->hash = p_hash;
+ c->set = p_set;
+ c->shader = p_shader;
+ c->cache = rid;
+ c->uniforms.resize(p_uniforms.size());
+ for (uint32_t i = 0; i < c->uniforms.size(); i++) {
+ c->uniforms[i] = p_uniforms[i];
+ }
+ c->prev = nullptr;
+ c->next = hash_table[p_table_idx];
+ if (hash_table[p_table_idx]) {
+ hash_table[p_table_idx]->prev = c;
+ }
+ hash_table[p_table_idx] = c;
+
+ RD::get_singleton()->uniform_set_set_invalidation_callback(rid, _uniform_set_invalidation_callback, c);
+
+ cache_instances_used++;
+
+ return rid;
+ }
+
+public:
+ template <typename... Args>
+ RID get_cache(RID p_shader, uint32_t p_set, Args... args) {
+ uint32_t h = hash_djb2_one_64(p_shader.get_id());
+ h = hash_djb2_one_32(p_set, h);
+ h = _hash_args(h, args...);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && _compare_args(0, c->uniforms, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RD::Uniform> uniforms;
+ _create_args(uniforms, args...);
+
+ return _allocate_from_uniforms(p_shader, p_set, h, table_idx, uniforms);
+ }
+
+ template <typename... Args>
+ RID get_cache_vec(RID p_shader, uint32_t p_set, const Vector<RD::Uniform> &p_uniforms) {
+ uint32_t h = hash_djb2_one_64(p_shader.get_id());
+ h = hash_djb2_one_32(p_set, h);
+ for (int i = 0; i < p_uniforms.size(); i++) {
+ h = _hash_uniform(p_uniforms[i], h);
+ }
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader) {
+ bool all_ok = true;
+ for (int i = 0; i < p_uniforms.size(); i++) {
+ if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) {
+ all_ok = false;
+ break;
+ }
+ }
+
+ if (all_ok) {
+ return c->cache;
+ }
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+ return _allocate_from_uniforms(p_shader, p_set, h, table_idx, p_uniforms);
+ }
+
+ static UniformSetCacheRD *get_singleton() { return singleton; }
+
+ UniformSetCacheRD();
+ ~UniformSetCacheRD();
+};
+
+#endif // UNIFORMSETCACHE_H
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 43d5b07869..b773ed61f4 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -194,7 +194,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@@ -211,7 +211,7 @@ public:
int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
};
- virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 5bdc7ce600..6f427272b5 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -228,7 +228,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
voxel_gi->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);
+ RSG::particles_storage->particles_add_collision(A->base, collision->instance);
}
}
@@ -344,7 +344,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
voxel_gi->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);
+ RSG::particles_storage->particles_remove_collision(A->base, collision->instance);
}
}
@@ -464,10 +464,10 @@ void RendererSceneCull::instance_initialize(RID p_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());
+ bool needs_instance = RSG::mesh_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);
+ p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);
} else {
RSG::storage->free(p_instance->mesh_instance);
@@ -488,7 +488,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
}
if (p_instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
+ RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
}
}
@@ -521,7 +521,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (scenario && instance->visible && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (scenario && instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
scenario->dynamic_lights.erase(light->instance);
}
@@ -562,8 +562,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
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);
+ while (lightmap_data->users.begin()) {
+ instance_geometry_set_lightmap((*lightmap_data->users.begin())->self, RID(), Rect2(), 0);
}
scene_render->free(lightmap_data->instance);
} break;
@@ -609,17 +609,20 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
if (p_base.is_valid()) {
instance->base_type = RSG::storage->get_base_type(p_base);
+ // fix up a specific malfunctioning case before the switch, so it can be handled
if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) {
instance->base_type = RS::INSTANCE_OCCLUDER;
}
- ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE);
-
switch (instance->base_type) {
+ case RS::INSTANCE_NONE: {
+ ERR_PRINT_ONCE("unimplemented base type encountered in renderer scene cull");
+ return;
+ }
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = memnew(InstanceLightData);
- if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
+ if (scenario && RSG::light_storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
light->D = scenario->directional_lights.push_back(instance);
}
@@ -650,8 +653,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
}
- for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
+ for (Instance *E : instance->visibility_dependencies) {
+ Instance *dep_instance = E;
ERR_CONTINUE(dep_instance->array_index == -1);
ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1);
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = instance->array_index;
@@ -659,8 +662,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} 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);
+ collision->instance = RSG::particles_storage->particles_collision_instance_create(p_base);
+ RSG::particles_storage->particles_collision_instance_set_active(collision->instance, instance->visible);
instance->base_data = collision;
} break;
case RS::INSTANCE_FOG_VOLUME: {
@@ -801,7 +804,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
+ if (RSG::light_storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
light->D = scenario->directional_lights.push_back(instance);
}
} break;
@@ -860,7 +863,7 @@ void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D
#ifdef DEBUG_ENABLED
for (int i = 0; i < 4; i++) {
- const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin;
+ const Vector3 &v = i < 3 ? p_transform.basis.rows[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));
@@ -890,7 +893,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
+ RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
}
}
@@ -900,7 +903,7 @@ void RendererSceneCull::instance_set_surface_override_material(RID p_instance, i
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)));
+ instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base)));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
@@ -930,7 +933,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
if (instance->base_type == RS::INSTANCE_LIGHT) {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (instance->scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (instance->scenario && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
if (p_visible) {
instance->scenario->dynamic_lights.push_back(light->instance);
} else {
@@ -941,7 +944,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
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);
+ RSG::particles_storage->particles_collision_instance_set_active(collision->instance, p_visible);
}
if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {
@@ -997,7 +1000,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID 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);
+ RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
}
_instance_queue_update(instance, true, true);
@@ -1289,15 +1292,15 @@ void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_par
bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
bool cycle_detected = false;
- Set<Instance *> traversed_nodes;
+ HashSet<Instance *> traversed_nodes;
{
Instance *instance = p_instance;
while (instance) {
if (!instance->visibility_dependencies.is_empty()) {
uint32_t depth = 0;
- for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) {
- depth = MAX(depth, E->get()->visibility_dependencies_depth);
+ for (const Instance *E : instance->visibility_dependencies) {
+ depth = MAX(depth, E->visibility_dependencies_depth);
}
instance->visibility_dependencies_depth = depth + 1;
} else {
@@ -1426,7 +1429,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
+ HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter);
if (!E) {
Instance::InstanceShaderParameter isp;
@@ -1435,10 +1438,10 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
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) {
+ E->value.value = p_value;
+ if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) {
//update directly
- RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
+ RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value);
}
}
}
@@ -1490,8 +1493,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
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) {
+ RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);
+ if (RSG::light_storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
p_instance->scenario->dynamic_lights.erase(light->instance);
}
@@ -1503,7 +1506,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
}
}
- uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base);
+ uint32_t max_sdfgi_cascade = RSG::light_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
}
@@ -1529,15 +1532,15 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->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);
+ RSG::particles_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)) {
+ if (RSG::particles_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);
+ RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {
InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);
scene_render->fog_volume_instance_set_transform(volume->instance, p_instance->transform);
@@ -1556,8 +1559,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
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();
+ for (Instance *E : lightmap_data->geometries) {
+ Instance *geom = E;
_instance_queue_update(geom, true, false);
}
}
@@ -1571,8 +1574,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
//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);
+ for (const Instance *E : geom->lights) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
light->shadow_dirty = true;
}
}
@@ -1629,8 +1632,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;
idata.visibility_index = p_instance->visibility_index;
- for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
+ for (Instance *E : p_instance->visibility_dependencies) {
+ Instance *dep_instance = E;
if (dep_instance->array_index != -1) {
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
}
@@ -1646,8 +1649,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);
idata.instance_data_rid = light_data->instance.get_id();
- light_data->uses_projector = RSG::storage->light_has_projector(p_instance->base);
- light_data->uses_softshadow = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
+ light_data->uses_projector = RSG::light_storage->light_has_projector(p_instance->base);
+ light_data->uses_softshadow = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
@@ -1740,7 +1743,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
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) {
+ if (RSG::light_storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
}
@@ -1797,8 +1800,8 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;
}
- for (Set<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
+ for (Instance *E : swapped_instance->visibility_dependencies) {
+ Instance *dep_instance = E;
if (dep_instance != p_instance && dep_instance->array_index != -1) {
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
}
@@ -1821,8 +1824,8 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
}
- for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
+ for (Instance *E : p_instance->visibility_dependencies) {
+ Instance *dep_instance = E;
if (dep_instance->array_index != -1) {
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
@@ -1847,7 +1850,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
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);
+ new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
}
} break;
@@ -1856,7 +1859,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
+ new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base);
}
} break;
@@ -1864,12 +1867,12 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->particles_get_aabb(p_instance->base);
+ new_aabb = RSG::particles_storage->particles_get_aabb(p_instance->base);
}
} break;
case RenderingServer::INSTANCE_PARTICLES_COLLISION: {
- new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
+ new_aabb = RSG::particles_storage->particles_collision_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_FOG_VOLUME: {
@@ -1879,15 +1882,15 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_LIGHT: {
- new_aabb = RSG::storage->light_get_aabb(p_instance->base);
+ new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_REFLECTION_PROBE: {
- new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
+ new_aabb = RSG::light_storage->reflection_probe_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_DECAL: {
- new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
+ new_aabb = RSG::texture_storage->decal_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_VOXEL_GI: {
@@ -1895,7 +1898,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
} break;
case RenderingServer::INSTANCE_LIGHTMAP: {
- new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base);
+ new_aabb = RSG::light_storage->lightmap_get_aabb(p_instance->base);
} break;
default: {
@@ -1920,10 +1923,10 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
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();
+ for (Instance *E : geom->lightmap_captures) {
+ Instance *lightmap = E;
- bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
+ bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base);
if (inside && !interior) {
continue; //we are inside, ignore exteriors
@@ -1934,13 +1937,13 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
Vector3 lm_pos = to_bounds.xform(center);
- AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base);
+ AABB bounds = RSG::light_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);
+ RSG::light_storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
//rotate it
Basis rot = lightmap->transform.basis.orthonormalized();
@@ -1997,19 +2000,19 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
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);
+ real_t shadow_max = RSG::light_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);
- real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+ real_t pancake_size = RSG::light_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)) {
+ switch (RSG::light_storage->light_directional_get_shadow_mode(p_instance->base)) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
splits = 1;
break;
@@ -2025,21 +2028,21 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
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[i + 1] = min_distance + RSG::light_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);
+ bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base);
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));
+ RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
// setup a camera matrix for that range!
CameraMatrix camera_matrix;
@@ -2065,9 +2068,9 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
Transform3D 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();
+ Vector3 x_vec = transform.basis.get_column(Vector3::AXIS_X).normalized();
+ Vector3 y_vec = transform.basis.get_column(Vector3::AXIS_Y).normalized();
+ Vector3 z_vec = transform.basis.get_column(Vector3::AXIS_Z).normalized();
//z_vec points against the camera, like in default opengl
real_t x_min = 0.f, x_max = 0.f;
@@ -2139,7 +2142,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
z_min_cam = z_vec.dot(center) - radius;
{
- float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
+ float soft_shadow_angle = RSG::light_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;
@@ -2215,11 +2218,11 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
bool animated_material_found = false;
- switch (RSG::storage->light_get_type(p_instance->base)) {
+ switch (RSG::light_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);
+ RS::LightOmniShadowMode shadow_mode = RSG::light_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()) {
if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {
@@ -2227,9 +2230,9 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
for (int i = 0; i < 2; i++) {
//using this one ensures that raster deferred will have it
- RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
+ RENDER_TIMESTAMP("Cull OmniLight3D Shadow Paraboloid, Half " + itos(i));
- real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
real_t z = i == 0 ? -1 : 1;
Vector<Plane> planes;
@@ -2271,14 +2274,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
shadow_data.light = light->instance;
@@ -2290,12 +2293,12 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return true;
}
- real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
CameraMatrix cm;
cm.set_perspective(90, 1, radius * 0.005f, radius);
for (int i = 0; i < 6; i++) {
- RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i));
+ RENDER_TIMESTAMP("Cull OmniLight3D Shadow Cube, Side " + itos(i));
//using this one ensures that raster deferred will have it
static const Vector3 view_normals[6] = {
@@ -2348,14 +2351,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
animated_material_found = true;
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
shadow_data.light = light->instance;
@@ -2368,14 +2371,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
} break;
case RS::LIGHT_SPOT: {
- RENDER_TIMESTAMP("Culling Spot Light");
+ RENDER_TIMESTAMP("Cull SpotLight3D Shadow");
if (max_shadows_used + 1 > MAX_UPDATE_SHADOWS) {
return true;
}
- 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);
+ real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
CameraMatrix cm;
cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius);
@@ -2412,13 +2415,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
shadow_data.light = light->instance;
@@ -2430,12 +2433,17 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
+void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
+ Vector2 jitter;
+ if (p_use_taa) {
+ jitter = taa_jitter_array[RSG::rasterizer->get_frame_number() % TAA_JITTER_COUNT] / p_viewport_size;
+ }
+
RendererSceneRender::CameraData camera_data;
// Setup Camera(s)
@@ -2444,7 +2452,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
Transform3D transform = camera->transform;
CameraMatrix projection;
bool vaspect = camera->vaspect;
- bool is_ortogonal = false;
+ bool is_orthogonal = false;
switch (camera->type) {
case Camera::ORTHOGONAL: {
@@ -2454,7 +2462,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
camera->znear,
camera->zfar,
camera->vaspect);
- is_ortogonal = true;
+ is_orthogonal = true;
} break;
case Camera::PERSPECTIVE: {
projection.set_perspective(
@@ -2476,7 +2484,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
} break;
}
- camera_data.set_camera(transform, projection, is_ortogonal, vaspect);
+ camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter);
} else {
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
@@ -2498,7 +2506,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
}
if (view_count == 1) {
- camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect);
+ camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter);
} else if (view_count == 2) {
camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect);
} else {
@@ -2508,9 +2516,9 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
RID environment = _render_get_environment(p_camera, p_scenario);
- RENDER_TIMESTAMP("Update occlusion buffer")
+ RENDER_TIMESTAMP("Update Occlusion Buffer")
// For now just cull on the first camera
- RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool);
+ RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool);
_render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);
#endif
@@ -2623,7 +2631,7 @@ void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_d
void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &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();
+ float lightmap_probe_update_speed = RSG::light_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;
@@ -2654,7 +2662,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
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)) {
+ if (cull_data.shadow_atlas.is_valid() && RSG::light_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
}
@@ -2714,14 +2722,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
mesh_visible = true;
} else if (base_type == RS::INSTANCE_PARTICLES) {
//particles visible? process them
- if (RSG::storage->particles_is_inactive(idata.base_rid)) {
+ if (RSG::particles_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);
+ RSG::particles_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(), cull_data.cam_transform.basis.get_axis(1).normalized());
+ RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_column(2).normalized(), cull_data.cam_transform.basis.get_column(1).normalized());
//particles visible? request redraw
RenderingServerDefault::redraw_request();
}
@@ -2741,8 +2749,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
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);
+ for (const Instance *E : geom->lights) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
instance_pair_buffer[idx++] = light->instance;
if (idx == MAX_INSTANCE_PAIRS) {
break;
@@ -2764,8 +2772,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
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);
+ for (const Instance *E : geom->reflection_probes) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->base_data);
instance_pair_buffer[idx++] = reflection_probe->instance;
if (idx == MAX_INSTANCE_PAIRS) {
@@ -2781,8 +2789,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) {
- InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data);
+ for (const Instance *E : geom->decals) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->base_data);
instance_pair_buffer[idx++] = decal->instance;
if (idx == MAX_INSTANCE_PAIRS) {
@@ -2796,8 +2804,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) {
- InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->get()->base_data);
+ for (const Instance *E : geom->voxel_gi_instances) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->base_data);
instance_pair_buffer[idx++] = voxel_gi->probe_instance;
if (idx == MAX_INSTANCE_PAIRS) {
@@ -2890,7 +2898,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not)
}
- RENDER_TIMESTAMP("Visibility Dependencies");
+ RENDER_TIMESTAMP("Update Visibility Dependencies");
if (scenario->instance_visibility.get_bin_count() > 0) {
if (!scenario->viewport_visibility_masks.has(p_viewport)) {
@@ -2918,9 +2926,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
}
- RENDER_TIMESTAMP("Culling");
+ RENDER_TIMESTAMP("Cull 3D Scene");
- //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_ortogonal);
+ //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_orthogonal);
/* STEP 2 - CULL */
@@ -2948,7 +2956,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
//check shadow..
if (light) {
- if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->base) && !(RSG::storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->base))) {
+ if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(E->base) && !(RSG::light_storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) {
lights_with_shadow.push_back(E);
}
//add to list
@@ -2959,7 +2967,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
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_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect);
+ _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect);
}
}
@@ -3037,9 +3045,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
if (scene_cull_result.mesh_instances.size()) {
for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {
- RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
+ RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
}
}
@@ -3070,7 +3078,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {
Instance *ins = scene_cull_result.lights[i];
- if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
+ if (!p_shadow_atlas.is_valid() || !RSG::light_storage->light_has_shadow(ins->base)) {
continue;
}
@@ -3082,22 +3090,22 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Transform3D cam_xf = p_camera_data->main_transform;
float zn = p_camera_data->main_projection.get_z_near();
- Plane p(-cam_xf.basis.get_axis(2), cam_xf.origin + cam_xf.basis.get_axis(2) * -zn); //camera near plane
+ Plane p(-cam_xf.basis.get_column(2), cam_xf.origin + cam_xf.basis.get_column(2) * -zn); //camera near plane
// near plane half width and height
Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
- switch (RSG::storage->light_get_type(ins->base)) {
+ switch (RSG::light_storage->light_get_type(ins->base)) {
case RS::LIGHT_OMNI: {
- float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+ float radius = RSG::light_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
+ ins->transform.origin + cam_xf.basis.get_column(0) * radius
};
- if (!p_camera_data->is_ortogonal) {
+ if (!p_camera_data->is_orthogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
@@ -3112,20 +3120,20 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
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 radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+ float angle = RSG::light_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 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;
Vector3 points[2] = {
base,
- base + cam_xf.basis.get_axis(0) * w
+ base + cam_xf.basis.get_column(0) * w
};
- if (!p_camera_data->is_ortogonal) {
+ if (!p_camera_data->is_orthogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
@@ -3155,9 +3163,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw!
- RENDER_TIMESTAMP(">Rendering Light " + itos(i));
- light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold);
- RENDER_TIMESTAMP("<Rendering Light " + itos(i));
+ RENDER_TIMESTAMP("> Render Light3D " + itos(i));
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold);
+ RENDER_TIMESTAMP("< Render Light3D " + itos(i));
} else {
light->shadow_dirty = redraw;
}
@@ -3213,12 +3221,18 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
/* PROCESS GEOMETRY AND DRAW SCENE */
RID occluders_tex;
+ const RendererSceneRender::CameraData *prev_camera_data = p_camera_data;
if (p_viewport.is_valid()) {
occluders_tex = RSG::viewport->viewport_get_occluder_debug_texture(p_viewport);
+ prev_camera_data = RSG::viewport->viewport_get_prev_camera_data(p_viewport);
}
- RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
+ RENDER_TIMESTAMP("Render 3D Scene");
+ scene_render->render_scene(p_render_buffers, p_camera_data, prev_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
+
+ if (p_viewport.is_valid()) {
+ RSG::viewport->viewport_set_prev_camera_data(p_viewport, p_camera_data);
+ }
for (uint32_t i = 0; i < max_shadows_used; i++) {
render_shadow_data[i].instances.clear();
@@ -3229,7 +3243,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
render_sdfgi_data[i].instances.clear();
}
- // virtual void render_scene(RID p_render_buffers, const Transform3D &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_voxel_gi_instances, 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_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
+ // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, 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_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -3263,12 +3277,12 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
} else {
environment = scenario->fallback_environment;
}
- RENDER_TIMESTAMP("Render Empty Scene ");
+ RENDER_TIMESTAMP("Render Empty 3D Scene");
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, nullptr, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3303,11 +3317,11 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
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 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base);
+ Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base);
+ float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base);
float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
- float mesh_lod_threshold = RSG::storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
+ float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_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
@@ -3325,7 +3339,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RID shadow_atlas;
- bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base);
+ bool use_shadows = RSG::light_storage->reflection_probe_renders_shadows(p_instance->base);
if (use_shadows) {
shadow_atlas = scenario->reflection_probe_shadow_atlas;
}
@@ -3337,15 +3351,15 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
environment = scenario->fallback_environment;
}
- RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
+ RENDER_TIMESTAMP("Render ReflectionProbe, Step " + itos(p_step));
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(xform, cm, false, false);
- _render_scene(&camera_data, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
+ _render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
- RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step));
+ RENDER_TIMESTAMP("Post-Process ReflectionProbe, Step " + itos(p_step));
return scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance);
}
@@ -3363,7 +3377,7 @@ void RendererSceneCull::render_probes() {
SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
RID base = ref_probe->self()->owner->base;
- switch (RSG::storage->reflection_probe_get_update_mode(base)) {
+ switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {
case RS::REFLECTION_PROBE_UPDATE_ONCE: {
if (busy) { //already rendering something
break;
@@ -3398,7 +3412,7 @@ void RendererSceneCull::render_probes() {
SelfList<InstanceVoxelGIData> *voxel_gi = voxel_gi_update_list.first();
if (voxel_gi) {
- RENDER_TIMESTAMP("Render GI Probes");
+ RENDER_TIMESTAMP("Render VoxelGI");
}
while (voxel_gi) {
@@ -3417,8 +3431,8 @@ void RendererSceneCull::render_probes() {
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();
+ for (Instance *E : probe->lights) {
+ Instance *instance = E;
InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
if (!instance->visible) {
continue;
@@ -3432,16 +3446,16 @@ void RendererSceneCull::render_probes() {
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->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||
+ cache->type != RSG::light_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->color != RSG::light_storage->light_get_color(instance->base) ||
+ cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+ cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+ cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+ cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+ cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+ cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
cache_dirty = true;
}
}
@@ -3463,17 +3477,17 @@ void RendererSceneCull::render_probes() {
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->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||
+ cache->type != RSG::light_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->color != RSG::light_storage->light_get_color(instance->base) ||
+ cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+ cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+ cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+ cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+ cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+ cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
+ cache->sky_mode != RSG::light_storage->light_directional_get_sky_mode(instance->base)) {
cache_dirty = true;
}
}
@@ -3499,8 +3513,8 @@ void RendererSceneCull::render_probes() {
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();
+ for (Instance *E : probe->lights) {
+ Instance *instance = E;
InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
if (!instance->visible) {
continue;
@@ -3509,16 +3523,16 @@ void RendererSceneCull::render_probes() {
InstanceVoxelGIData::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->has_shadow = RSG::light_storage->light_has_shadow(instance->base);
+ cache->type = RSG::light_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->color = RSG::light_storage->light_get_color(instance->base);
+ cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+ cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+ cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+ cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -3531,17 +3545,17 @@ void RendererSceneCull::render_probes() {
InstanceVoxelGIData::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->has_shadow = RSG::light_storage->light_has_shadow(instance->base);
+ cache->type = RSG::light_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->color = RSG::light_storage->light_get_color(instance->base);
+ cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+ cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+ cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+ cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ cache->sky_mode = RSG::light_storage->light_directional_get_sky_mode(instance->base);
idx++;
}
@@ -3554,8 +3568,8 @@ void RendererSceneCull::render_probes() {
RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
- for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
- Instance *ins = E->get();
+ for (Instance *E : probe->dynamic_geometries) {
+ Instance *ins = E;
if (!ins->visible) {
continue;
}
@@ -3563,8 +3577,8 @@ void RendererSceneCull::render_probes() {
if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) {
uint32_t idx = 0;
- for (Set<Instance *>::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) {
- InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->get()->base_data);
+ for (const Instance *F : geom->voxel_gi_instances) {
+ InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->base_data);
instance_pair_buffer[idx++] = voxel_gi2->probe_instance;
if (idx == MAX_INSTANCE_PAIRS) {
@@ -3589,10 +3603,10 @@ void RendererSceneCull::render_probes() {
}
void RendererSceneCull::render_particle_colliders() {
- while (heightfield_particle_colliders_update_list.front()) {
- Instance *hfpc = heightfield_particle_colliders_update_list.front()->get();
+ while (heightfield_particle_colliders_update_list.begin()) {
+ Instance *hfpc = *heightfield_particle_colliders_update_list.begin();
- if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
+ if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::particles_storage->particles_collision_is_heightfield(hfpc->base)) {
//update heightfield
instance_cull_result.clear();
scene_cull_result.geometry_instances.clear();
@@ -3622,14 +3636,14 @@ void RendererSceneCull::render_particle_colliders() {
scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, scene_cull_result.geometry_instances);
}
- heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
+ heightfield_particle_colliders_update_list.remove(heightfield_particle_colliders_update_list.begin());
}
}
-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 (const RendererStorage::InstanceShaderParam &E : plist) {
+void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
+ List<RendererMaterialStorage::InstanceShaderParam> plist;
+ RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist);
+ for (const RendererMaterialStorage::InstanceShaderParam &E : plist) {
StringName name = E.info.name;
if (isparams.has(name)) {
if (isparams[name].info.type != E.info.type) {
@@ -3667,17 +3681,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->material_override.is_valid()) {
- RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
}
if (p_instance->material_overlay.is_valid()) {
- RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(p_instance->material_overlay, &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);
+ int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base);
p_instance->materials.resize(new_mat_count);
_instance_update_mesh_instance(p_instance);
@@ -3686,9 +3700,9 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
// update the process material dependency
- RID particle_material = RSG::storage->particles_get_process_material(p_instance->base);
+ RID particle_material = RSG::particles_storage->particles_get_process_material(p_instance->base);
if (particle_material.is_valid()) {
- RSG::storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
+ RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
}
}
@@ -3697,17 +3711,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
bool can_cast_shadows = true;
bool is_animated = false;
- Map<StringName, Instance::InstanceShaderParameter> isparams;
+ HashMap<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)) {
+ if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) {
can_cast_shadows = false;
}
- is_animated = RSG::storage->material_is_animated(p_instance->material_override);
+ is_animated = RSG::material_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) {
@@ -3717,22 +3731,22 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
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);
+ RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
- if (RSG::storage->material_casts_shadows(mat)) {
+ if (RSG::material_storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
- if (RSG::storage->material_is_animated(mat)) {
+ if (RSG::material_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);
+ RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
@@ -3742,28 +3756,28 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
- RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
+ RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base);
if (mesh.is_valid()) {
bool cast_shadows = false;
- int sc = RSG::storage->mesh_get_surface_count(mesh);
+ int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);
for (int i = 0; i < sc; i++) {
- RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
+ RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
- if (RSG::storage->material_casts_shadows(mat)) {
+ if (RSG::material_storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
- if (RSG::storage->material_is_animated(mat)) {
+ if (RSG::material_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);
+ RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
@@ -3776,32 +3790,32 @@ void RendererSceneCull::_update_dirty_instance(Instance *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);
+ int dp = RSG::particles_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);
+ RID mesh = RSG::particles_storage->particles_get_draw_pass_mesh(p_instance->base, i);
if (!mesh.is_valid()) {
continue;
}
- int sc = RSG::storage->mesh_get_surface_count(mesh);
+ int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);
for (int j = 0; j < sc; j++) {
- RID mat = RSG::storage->mesh_surface_get_material(mesh, j);
+ RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
- if (RSG::storage->material_casts_shadows(mat)) {
+ if (RSG::material_storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
- if (RSG::storage->material_is_animated(mat)) {
+ if (RSG::material_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);
+ RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
}
@@ -3813,15 +3827,15 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->material_overlay.is_valid()) {
- can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay);
- is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
+ can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay);
+ is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
}
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);
+ for (const Instance *E : geom->lights) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
light->shadow_dirty = true;
}
@@ -3834,16 +3848,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
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);
+ p_instance->instance_allocated_shader_parameters_offset = RSG::material_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 (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
if (E.value.value.get_type() != Variant::NIL) {
- RSG::storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
+ RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
}
}
} else {
- RSG::storage->global_variables_instance_free(p_instance->self);
+ RSG::material_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);
}
@@ -3851,7 +3865,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->skeleton.is_valid()) {
- RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
+ RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
}
p_instance->dependency_tracker.update_end();
@@ -3939,7 +3953,7 @@ bool RendererSceneCull::free(RID p_rid) {
if (instance->instance_allocated_shader_parameters) {
//free the used shader parameters
- RSG::storage->global_variables_instance_free(instance->self);
+ RSG::material_storage->global_variables_instance_free(instance->self);
}
update_dirty_instances(); //in case something changed this
@@ -3990,6 +4004,17 @@ void RendererSceneCull::set_scene_render(RendererSceneRender *p_scene_render) {
geometry_instance_pair_mask = scene_render->geometry_instance_get_pair_mask();
}
+float get_halton_value(int index, int base) {
+ float f = 1;
+ float r = 0;
+ while (index > 0) {
+ f = f / static_cast<float>(base);
+ r = r + f * (index % base);
+ index = index / base;
+ }
+ return r * 2.0f - 1.0f;
+};
+
RendererSceneCull::RendererSceneCull() {
render_pass = 1;
singleton = this;
@@ -4014,6 +4039,12 @@ RendererSceneCull::RendererSceneCull() {
thread_cull_threshold = GLOBAL_GET("rendering/limits/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
+ taa_jitter_array.resize(TAA_JITTER_COUNT);
+ for (int i = 0; i < TAA_JITTER_COUNT; i++) {
+ taa_jitter_array[i].x = get_halton_value(i, 2);
+ taa_jitter_array[i].y = get_halton_value(i, 3);
+ }
+
dummy_occlusion_culling = memnew(RendererSceneOcclusionCull);
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 90d290bef9..d1d3484871 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -47,7 +47,7 @@
class RendererSceneCull : public RendererScene {
public:
- RendererSceneRender *scene_render;
+ RendererSceneRender *scene_render = nullptr;
enum {
SDFGI_MAX_CASCADES = 8,
@@ -115,7 +115,7 @@ public:
/* VISIBILITY NOTIFIER API */
- RendererSceneOcclusionCull *dummy_occlusion_culling;
+ RendererSceneOcclusionCull *dummy_occlusion_culling = nullptr;
/* SCENARIO API */
@@ -273,7 +273,7 @@ public:
union {
uint64_t instance_data_rid;
RendererSceneRender::GeometryInstance *instance_geometry;
- InstanceVisibilityNotifierData *visibility_notifier;
+ InstanceVisibilityNotifierData *visibility_notifier = nullptr;
};
Instance *instance = nullptr;
int32_t parent_array_index = -1;
@@ -324,7 +324,7 @@ public:
RID reflection_probe_shadow_atlas;
RID reflection_atlas;
uint64_t used_viewport_visibility_bits;
- Map<RID, uint64_t> viewport_visibility_masks;
+ HashMap<RID, uint64_t> viewport_visibility_masks;
SelfList<Instance>::List instances;
@@ -365,8 +365,8 @@ public:
/* INSTANCING API */
struct InstancePair {
- Instance *a;
- Instance *b;
+ Instance *a = nullptr;
+ Instance *b = nullptr;
SelfList<InstancePair> list_a;
SelfList<InstancePair> list_b;
InstancePair() :
@@ -409,7 +409,7 @@ public:
bool dynamic_gi : 2; //same above for dynamic objects
bool redraw_if_visible : 4;
- Instance *lightmap;
+ Instance *lightmap = nullptr;
Rect2 lightmap_uv_scale;
int lightmap_slice_index;
uint32_t lightmap_cull_index;
@@ -426,7 +426,7 @@ public:
PropertyInfo info;
};
- Map<StringName, InstanceShaderParameter> instance_shader_parameters;
+ HashMap<StringName, InstanceShaderParameter> instance_shader_parameters;
bool instance_allocated_shader_parameters = false;
int32_t instance_allocated_shader_parameters_offset = -1;
@@ -443,7 +443,7 @@ public:
float visibility_range_end_margin = 0.0f;
RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED;
Instance *visibility_parent = nullptr;
- Set<Instance *> visibility_dependencies;
+ HashSet<Instance *> visibility_dependencies;
uint32_t visibility_dependencies_depth = 0;
float transparency = 0.0f;
Scenario *scenario = nullptr;
@@ -455,7 +455,7 @@ public:
SelfList<Instance> update_item;
- AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
+ AABB *custom_aabb = nullptr; // <Zylann> would using aabb directly with a bool be better?
float extra_margin;
ObjectID object_id;
@@ -465,7 +465,7 @@ public:
uint64_t version; // changes to this, and changes to base increase version
- InstanceBaseData *base_data;
+ InstanceBaseData *base_data = nullptr;
SelfList<InstancePair>::List pairs;
uint64_t pair_check;
@@ -579,16 +579,16 @@ public:
struct InstanceGeometryData : public InstanceBaseData {
RendererSceneRender::GeometryInstance *geometry_instance = nullptr;
- Set<Instance *> lights;
+ HashSet<Instance *> lights;
bool can_cast_shadows;
bool material_is_animated;
uint32_t projector_count = 0;
uint32_t softshadow_count = 0;
- Set<Instance *> decals;
- Set<Instance *> reflection_probes;
- Set<Instance *> voxel_gi_instances;
- Set<Instance *> lightmap_captures;
+ HashSet<Instance *> decals;
+ HashSet<Instance *> reflection_probes;
+ HashSet<Instance *> voxel_gi_instances;
+ HashSet<Instance *> lightmap_captures;
InstanceGeometryData() {
can_cast_shadows = true;
@@ -597,9 +597,9 @@ public:
};
struct InstanceReflectionProbeData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
- Set<Instance *> geometries;
+ HashSet<Instance *> geometries;
RID instance;
SelfList<InstanceReflectionProbeData> update_list;
@@ -613,10 +613,10 @@ public:
};
struct InstanceDecalData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
RID instance;
- Set<Instance *> geometries;
+ HashSet<Instance *> geometries;
InstanceDecalData() {
}
@@ -654,9 +654,9 @@ public:
bool uses_projector = false;
bool uses_softshadow = false;
- Set<Instance *> geometries;
+ HashSet<Instance *> geometries;
- Instance *baked_light;
+ Instance *baked_light = nullptr;
RS::LightBakeMode bake_mode;
uint32_t max_sdfgi_cascade = 2;
@@ -671,12 +671,12 @@ public:
};
struct InstanceVoxelGIData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
- Set<Instance *> geometries;
- Set<Instance *> dynamic_geometries;
+ HashSet<Instance *> geometries;
+ HashSet<Instance *> dynamic_geometries;
- Set<Instance *> lights;
+ HashSet<Instance *> lights;
struct LightCache {
RS::LightType type;
@@ -689,7 +689,7 @@ public:
float spot_angle;
float spot_attenuation;
bool has_shadow;
- bool sky_only;
+ RS::LightDirectionalSkyMode sky_mode;
};
Vector<LightCache> light_cache;
@@ -713,8 +713,8 @@ public:
struct InstanceLightmapData : public InstanceBaseData {
RID instance;
- Set<Instance *> geometries;
- Set<Instance *> users;
+ HashSet<Instance *> geometries;
+ HashSet<Instance *> users;
InstanceLightmapData() {
}
@@ -779,7 +779,7 @@ public:
}
};
- Set<Instance *> heightfield_particle_colliders_update_list;
+ HashSet<Instance *> heightfield_particle_colliders_update_list;
PagedArrayPool<Instance *> instance_cull_page_pool;
PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool;
@@ -921,7 +921,10 @@ public:
RID_Owner<Instance, true> instance_owner;
- uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecessary on clustered
+ uint32_t geometry_instance_pair_mask = 0; // used in traditional forward, unnecessary on clustered
+
+ const int TAA_JITTER_COUNT = 16;
+ LocalVector<Vector2> taa_jitter_array;
virtual RID instance_allocate();
virtual void instance_initialize(RID p_rid);
@@ -964,7 +967,7 @@ public:
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);
+ void _update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<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;
@@ -1023,7 +1026,7 @@ public:
struct VisibilityCullData {
uint64_t viewport_mask;
- Scenario *scenario;
+ Scenario *scenario = nullptr;
Vector3 camera_position;
uint32_t cull_offset;
uint32_t cull_count;
@@ -1035,12 +1038,12 @@ public:
_FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
struct CullData {
- Cull *cull;
- Scenario *scenario;
+ Cull *cull = nullptr;
+ Scenario *scenario = nullptr;
RID shadow_atlas;
Transform3D cam_transform;
uint32_t visible_layers;
- Instance *render_reflection_probe;
+ Instance *render_reflection_probe = nullptr;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
const CameraMatrix *camera_matrix;
uint64_t visibility_viewport_mask;
@@ -1054,7 +1057,7 @@ public:
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
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, RID p_viewport, Size2 p_viewport_size, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
+ void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
void update_dirty_instances();
void render_particle_colliders();
@@ -1155,7 +1158,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
- PASS12(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
+ PASS13(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, bool, uint32_t)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 48412dab68..7198379ade 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -161,31 +161,31 @@ public:
static RendererSceneOcclusionCull *get_singleton() { return singleton; }
- void _print_warining() {
- WARN_PRINT_ONCE("Occlusion culling is disabled at build time.");
+ void _print_warning() {
+ WARN_PRINT_ONCE("Occlusion culling is disabled at build-time.");
}
virtual bool is_occluder(RID p_rid) { return false; }
virtual RID occluder_allocate() { return RID(); }
virtual void occluder_initialize(RID p_occluder) {}
- virtual void free_occluder(RID p_occluder) { _print_warining(); }
- virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) { _print_warining(); }
+ virtual void free_occluder(RID p_occluder) { _print_warning(); }
+ virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) { _print_warning(); }
virtual void add_scenario(RID p_scenario) {}
virtual void remove_scenario(RID p_scenario) {}
- virtual void scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform3D &p_xform, bool p_enabled) { _print_warining(); }
- virtual void scenario_remove_instance(RID p_scenario, RID p_instance) { _print_warining(); }
+ virtual void scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform3D &p_xform, bool p_enabled) { _print_warning(); }
+ virtual void scenario_remove_instance(RID p_scenario, RID p_instance) { _print_warning(); }
- virtual void add_buffer(RID p_buffer) { _print_warining(); }
- virtual void remove_buffer(RID p_buffer) { _print_warining(); }
+ virtual void add_buffer(RID p_buffer) { _print_warning(); }
+ virtual void remove_buffer(RID p_buffer) { _print_warning(); }
virtual HZBuffer *buffer_get_ptr(RID p_buffer) {
return nullptr;
}
- virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warining(); }
- virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warining(); }
+ virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warning(); }
+ virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warning(); }
virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {}
virtual RID buffer_get_debug_texture(RID p_buffer) {
- _print_warining();
+ _print_warning();
return RID();
}
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index c802f72fdf..600908cf16 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -30,9 +30,9 @@
#include "renderer_scene_render.h"
-void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect) {
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
view_count = 1;
- is_ortogonal = p_is_ortogonal;
+ is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
main_transform = p_transform;
@@ -40,13 +40,14 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
view_offset[0] = Transform3D();
view_projection[0] = p_projection;
+ taa_jitter = p_taa_jitter;
}
-void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect) {
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) {
ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
view_count = p_view_count;
- is_ortogonal = p_is_ortogonal;
+ is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
Vector<Plane> planes[2];
@@ -65,7 +66,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
Vector3 y = n0.cross(n1).normalized();
Vector3 x = y.cross(z).normalized();
y = z.cross(x).normalized();
- main_transform.basis.set(x, y, z);
+ main_transform.basis.set_columns(x, y, z);
// 3. create a horizon plane with one of the eyes and the up vector as normal.
Plane horizon(y, p_transforms[0].origin);
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 5f9c4bb816..280277c6d8 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -223,7 +223,7 @@ public:
struct RenderSDFGIUpdateData {
bool update_static = false;
uint32_t static_cascade_count;
- uint32_t *static_cascade_indices;
+ uint32_t *static_cascade_indices = nullptr;
PagedArray<RID> *static_positional_lights;
const Vector<RID> *directional_lights;
@@ -234,7 +234,7 @@ public:
struct CameraData {
// flags
uint32_t view_count;
- bool is_ortogonal;
+ bool is_orthogonal;
bool vaspect;
// Main/center projection
@@ -243,14 +243,15 @@ public:
Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS];
CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Vector2 taa_jitter;
- void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect);
- void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect);
+ void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect);
};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
- virtual void render_material(const Transform3D &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_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
@@ -258,7 +259,7 @@ public:
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_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index a2df7ad38e..bb4acab582 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -54,7 +54,6 @@ public:
struct DependencyTracker;
-protected:
struct Dependency {
void changed_notify(DependencyChangedNotification p_notification);
void deleted_notify(const RID &p_rid);
@@ -63,10 +62,9 @@ protected:
private:
friend struct DependencyTracker;
- Map<DependencyTracker *, uint32_t> instances;
+ HashMap<DependencyTracker *, uint32_t> instances;
};
-public:
struct DependencyTracker {
void *userdata = nullptr;
typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
@@ -85,15 +83,16 @@ public:
}
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);
+ List<Pair<Dependency *, DependencyTracker *>> to_clean_up;
+
+ for (Dependency *E : dependencies) {
+ Dependency *dep = E;
+ HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this);
ERR_CONTINUE(!F);
- if (F->get() != instance_version) {
- Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *> p;
+ if (F->value != instance_version) {
+ Pair<Dependency *, DependencyTracker *> p;
p.first = dep;
- p.second = F;
+ p.second = F->key;
to_clean_up.push_back(p);
}
}
@@ -106,8 +105,8 @@ public:
}
void clear() { // clear all dependencies
- for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) {
- Dependency *dep = E->get();
+ for (Dependency *E : dependencies) {
+ Dependency *dep = E;
dep->instances.erase(this);
}
dependencies.clear();
@@ -118,284 +117,10 @@ public:
private:
friend struct Dependency;
uint32_t instance_version = 0;
- Set<Dependency *> dependencies;
+ HashSet<Dependency *> dependencies;
};
- virtual bool can_create_resources_async() const = 0;
- /* TEXTURE API */
-
- virtual RID texture_allocate() = 0;
-
- virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
- virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
- virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
- virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
-
- 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 void texture_2d_placeholder_initialize(RID p_texture) = 0;
- virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
- virtual void texture_3d_placeholder_initialize(RID p_texture) = 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_allocate() = 0;
- virtual void canvas_texture_initialize(RID p_rid) = 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_allocate() = 0;
- virtual void shader_initialize(RID p_rid) = 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, int p_index) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) 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_allocate() = 0;
- virtual void material_initialize(RID p_rid) = 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_allocate() = 0;
- virtual void mesh_initialize(RID p_rid) = 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_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
- virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
- virtual void mesh_surface_update_skin_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_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 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_allocate() = 0;
- virtual void multimesh_initialize(RID p_rid) = 0;
-
- virtual void multimesh_allocate_data(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 Transform3D &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 Transform3D 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;
-
- /* SKELETON API */
-
- virtual RID skeleton_allocate() = 0;
- virtual void skeleton_initialize(RID p_rid) = 0;
-
- virtual void skeleton_allocate_data(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 Transform3D &p_transform) = 0;
- virtual Transform3D 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 directional_light_allocate() = 0;
- virtual void directional_light_initialize(RID p_rid) = 0;
-
- virtual RID omni_light_allocate() = 0;
- virtual void omni_light_initialize(RID p_rid) = 0;
-
- virtual RID spot_light_allocate() = 0;
- virtual void spot_light_initialize(RID p_rid) = 0;
-
- 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 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 bool light_has_projector(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_allocate() = 0;
- virtual void reflection_probe_initialize(RID p_rid) = 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_mesh_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_mesh_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_allocate() = 0;
- virtual void decal_initialize(RID p_rid) = 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;
/* VOXEL GI API */
@@ -439,103 +164,6 @@ public:
virtual uint32_t voxel_gi_get_version(RID p_probe) = 0;
- /* LIGHTMAP */
-
- virtual RID lightmap_allocate() = 0;
- virtual void lightmap_initialize(RID p_rid) = 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_allocate() = 0;
- virtual void particles_initialize(RID p_rid) = 0;
- virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 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, double 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, double p_time) = 0;
- virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
- virtual void particles_set_randomness_ratio(RID p_particles, real_t 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, double 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 RID particles_get_process_material(RID p_particles) const = 0;
- virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
- virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
- virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
- virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
-
- virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
-
- virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
- virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
-
- virtual void particles_restart(RID p_particles) = 0;
- virtual void particles_emit(RID p_particles, const Transform3D &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 Transform3D &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, const Vector3 &p_up_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 particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
-
- virtual void update_particles() = 0;
-
- /* PARTICLES COLLISION */
-
- virtual RID particles_collision_allocate() = 0;
- virtual void particles_collision_initialize(RID p_rid) = 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, real_t 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, real_t p_strength) = 0;
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t 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;
-
/* FOG VOLUMES */
virtual RID fog_volume_allocate() = 0;
@@ -557,56 +185,6 @@ public:
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 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 Transform3D &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, uint32_t p_view_count) = 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 void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
-
virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
virtual bool free(RID p_rid) = 0;
@@ -622,6 +200,7 @@ public:
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
+ virtual String get_video_adapter_api_version() const = 0;
static RendererStorage *base_singleton;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 69c017a1c8..2e0c4e0f79 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -34,6 +34,7 @@
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
#include "rendering_server_globals.h"
+#include "storage/texture_storage.h"
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;
@@ -42,7 +43,7 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
if (p_viewport->canvas_map.has(p_canvas->parent)) {
Transform2D c_xform = p_viewport->canvas_map[p_canvas->parent].transform;
if (p_viewport->snap_2d_transforms_to_pixel) {
- c_xform.elements[2] = c_xform.elements[2].floor();
+ c_xform.columns[2] = c_xform.columns[2].floor();
}
xf = xf * c_xform;
scale = p_canvas->parent_scale;
@@ -51,7 +52,7 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
Transform2D c_xform = p_canvas_data->transform;
if (p_viewport->snap_2d_transforms_to_pixel) {
- c_xform.elements[2] = c_xform.elements[2].floor();
+ c_xform.columns[2] = c_xform.columns[2].floor();
}
xf = xf * c_xform;
@@ -77,23 +78,21 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RSG::scene->free(p_viewport->render_buffers);
p_viewport->render_buffers = RID();
} else {
- float scaling_3d_scale = p_viewport->scaling_3d_scale;
-
+ const float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
bool scaling_enabled = true;
if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
- // FSR is not design for downsampling.
- // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR
- WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling.");
+ // FSR is not designed for downsampling.
+ // Fall back to bilinear scaling.
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) {
// FSR is not actually available.
- // Throw a warning and fallback to disable scaling
- WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling.");
- scaling_enabled = false;
+ // Fall back to bilinear scaling.
+ WARN_PRINT_ONCE("FSR 1.0 3D resolution scaling is not available. Falling back to bilinear 3D resolution scaling.");
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
if (scaling_3d_scale == 1.0) {
@@ -139,13 +138,13 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
p_viewport->internal_size = Size2(render_width, render_height);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
void RendererViewport::_draw_3d(Viewport *p_viewport) {
- RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
+ RENDER_TIMESTAMP("> Render 3D Scene");
Ref<XRInterface> xr_interface;
if (p_viewport->use_xr && XRServer::get_singleton() != nullptr) {
@@ -168,9 +167,9 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
}
float screen_mesh_lod_threshold = p_viewport->mesh_lod_threshold / float(p_viewport->size.width);
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, screen_mesh_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, p_viewport->use_taa, screen_mesh_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
- RENDER_TIMESTAMP("<End Rendering 3D Scene");
+ RENDER_TIMESTAMP("< Render 3D Scene");
}
void RendererViewport::_draw_viewport(Viewport *p_viewport) {
@@ -196,8 +195,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
}
}
- Color bgcolor = RSG::storage->get_default_clear_color();
-
if (!p_viewport->disable_2d && !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)) {
@@ -208,15 +205,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera) && !p_viewport->disable_3d;
- if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
- if (p_viewport->transparent_bg) {
- bgcolor = Color(0, 0, 0, 0);
- }
- if (p_viewport->clear_mode == RS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
- p_viewport->clear_mode = RS::VIEWPORT_CLEAR_NEVER;
- }
- }
-
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_buffers_create();
@@ -224,16 +212,21 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_configure_3d_render_buffers(p_viewport);
}
- RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
+ Color bgcolor = p_viewport->transparent_bg ? Color(0, 0, 0, 0) : RSG::storage->get_default_clear_color();
+
+ if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
+ RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
+ if (p_viewport->clear_mode == RS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
+ p_viewport->clear_mode = RS::VIEWPORT_CLEAR_NEVER;
+ }
+ }
if (!scenario_draw_canvas_bg && can_draw_3d) {
_draw_3d(p_viewport);
}
if (!p_viewport->disable_2d) {
- int i = 0;
-
- Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
+ RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
RendererCanvasRender::Light *lights = nullptr;
@@ -243,57 +236,56 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RendererCanvasRender::Light *directional_lights_with_shadow = nullptr;
if (p_viewport->sdf_active) {
- //process SDF
+ // Process SDF.
- Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target);
+ Rect2 sdf_rect = RSG::texture_storage->render_target_get_sdf_rect(p_viewport->render_target);
RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
- //make list of occluders
+ // Make list of occluders.
for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
- for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
- if (!F->get()->enabled) {
+ for (RendererCanvasRender::LightOccluderInstance *F : canvas->occluders) {
+ if (!F->enabled) {
continue;
}
- F->get()->xform_cache = xf * F->get()->xform;
+ F->xform_cache = xf * F->xform;
- if (sdf_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) {
- F->get()->next = occluders;
- occluders = F->get();
+ if (sdf_rect.intersects_transformed(F->xform_cache, F->aabb_cache)) {
+ F->next = occluders;
+ occluders = F;
}
}
}
RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
- RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
+ RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
- p_viewport->sdf_active = false; // if used, gets set active again
+ p_viewport->sdf_active = false; // If used, gets set active again.
} else {
- RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
+ RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
}
Rect2 shadow_rect;
- int light_count = 0;
int shadow_count = 0;
int directional_light_count = 0;
- RENDER_TIMESTAMP("Cull Canvas Lights");
+ RENDER_TIMESTAMP("Cull 2D Lights");
for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
- //find lights in canvas
+ // Find lights in canvas.
- for (Set<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
- RendererCanvasRender::Light *cl = F->get();
+ for (RendererCanvasRender::Light *F : canvas->lights) {
+ RendererCanvasRender::Light *cl = F;
if (cl->enabled && cl->texture.is_valid()) {
//not super efficient..
- Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture);
+ Size2 tsize = RSG::texture_storage->texture_size_with_proxy(cl->texture);
tsize *= cl->scale;
Vector2 offset = tsize / 2.0;
@@ -303,12 +295,10 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) {
cl->filter_next_ptr = lights;
lights = cl;
- // cl->texture_cache = nullptr;
Transform2D scale;
scale.scale(cl->rect_cache.size);
- scale.elements[2] = cl->rect_cache.position;
+ scale.columns[2] = cl->rect_cache.position;
cl->light_shader_xform = cl->xform * scale;
- //cl->light_shader_pos = cl->xform_cache[2];
if (cl->use_shadow) {
cl->shadows_next_ptr = lights_with_shadow;
if (lights_with_shadow == nullptr) {
@@ -319,21 +309,17 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
lights_with_shadow = cl;
cl->radius_cache = cl->rect_cache.size.length();
}
-
- light_count++;
}
-
- //guess this is not needed, but keeping because it may be
}
}
- for (Set<RendererCanvasRender::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) {
- RendererCanvasRender::Light *cl = F->get();
+ for (RendererCanvasRender::Light *F : canvas->directional_lights) {
+ RendererCanvasRender::Light *cl = F;
if (cl->enabled) {
cl->filter_next_ptr = directional_lights;
directional_lights = cl;
cl->xform_cache = xf * cl->xform;
- cl->xform_cache.elements[2] = Vector2(); //translation is pointless
+ cl->xform_cache.columns[2] = Vector2(); //translation is pointless
if (cl->use_shadow) {
cl->shadows_next_ptr = directional_lights_with_shadow;
directional_lights_with_shadow = cl;
@@ -355,22 +341,22 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
- RENDER_TIMESTAMP(">Render 2D Shadows");
- RENDER_TIMESTAMP("Cull Occluders");
+ RENDER_TIMESTAMP("> Render PointLight2D Shadows");
+ RENDER_TIMESTAMP("Cull LightOccluder2Ds");
//make list of occluders
for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
- for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
- if (!F->get()->enabled) {
+ for (RendererCanvasRender::LightOccluderInstance *F : canvas->occluders) {
+ if (!F->enabled) {
continue;
}
- F->get()->xform_cache = xf * F->get()->xform;
- if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) {
- F->get()->next = occluders;
- occluders = F->get();
+ F->xform_cache = xf * F->xform;
+ if (shadow_rect.intersects_transformed(F->xform_cache, F->aabb_cache)) {
+ F->next = occluders;
+ occluders = F;
}
}
}
@@ -378,20 +364,20 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RendererCanvasRender::Light *light = lights_with_shadow;
while (light) {
- RENDER_TIMESTAMP("Render Shadow");
+ RENDER_TIMESTAMP("Render PointLight2D Shadow");
RSG::canvas_render->light_update_shadow(light->light_internal, shadow_count++, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders);
light = light->shadows_next_ptr;
}
- RENDER_TIMESTAMP("<End rendering 2D Shadows");
+ RENDER_TIMESTAMP("< Render PointLight2D Shadows");
}
if (directional_lights_with_shadow) {
//update shadows if any
RendererCanvasRender::Light *light = directional_lights_with_shadow;
while (light) {
- Vector2 light_dir = -light->xform_cache.elements[1].normalized(); // Y is light direction
+ Vector2 light_dir = -light->xform_cache.columns[1].normalized(); // Y is light direction
float cull_distance = light->directional_distance;
Vector2 light_dir_sign;
@@ -436,28 +422,26 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
- RENDER_TIMESTAMP(">Render Directional 2D Shadows");
+ RENDER_TIMESTAMP("> Render DirectionalLight2D Shadows");
- //make list of occluders
- int occ_cullded = 0;
+ // Make list of occluders.
for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
- for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
- if (!F->get()->enabled) {
+ for (RendererCanvasRender::LightOccluderInstance *F : canvas->occluders) {
+ if (!F->enabled) {
continue;
}
- F->get()->xform_cache = xf * F->get()->xform;
- Transform2D localizer = F->get()->xform_cache.affine_inverse();
+ F->xform_cache = xf * F->xform;
+ Transform2D localizer = F->xform_cache.affine_inverse();
for (int j = 0; j < point_count; j++) {
xf_points[j] = localizer.xform(points[j]);
}
- if (F->get()->aabb_cache.intersects_filled_polygon(xf_points, point_count)) {
- F->get()->next = occluders;
- occluders = F->get();
- occ_cullded++;
+ if (F->aabb_cache.intersects_filled_polygon(xf_points, point_count)) {
+ F->next = occluders;
+ occluders = F;
}
}
}
@@ -467,10 +451,10 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
light = light->shadows_next_ptr;
}
- RENDER_TIMESTAMP("<Render Directional 2D Shadows");
+ RENDER_TIMESTAMP("< Render DirectionalLight2D Shadows");
}
- if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
+ if (scenario_draw_canvas_bg && canvas_map.begin() && canvas_map.begin()->key.get_layer() > scenario_canvas_max_layer) {
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
@@ -509,7 +493,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (RSG::canvas->was_sdf_used()) {
p_viewport->sdf_active = true;
}
- i++;
if (scenario_draw_canvas_bg && E.key.get_layer() >= scenario_canvas_max_layer) {
if (!can_draw_3d) {
@@ -531,9 +514,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
}
}
- if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) {
+ if (RSG::texture_storage->render_target_is_clear_requested(p_viewport->render_target)) {
//was never cleared in the end, force clear it
- RSG::storage->render_target_do_clear_request(p_viewport->render_target);
+ RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target);
}
if (p_viewport->measure_render_time) {
@@ -564,9 +547,9 @@ void RendererViewport::draw_viewports() {
//sort viewports
active_viewports.sort_custom<ViewportSort>();
- Map<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
+ HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
- RENDER_TIMESTAMP(">Render Viewports");
+ RENDER_TIMESTAMP("> Render Viewports");
//determine what is visible
draw_viewports_pass++;
@@ -597,7 +580,7 @@ void RendererViewport::draw_viewports() {
vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
vp->size = xr_size;
uint32_t view_count = xr_interface->get_view_count();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ RSG::texture_storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
// Inform xr interface we're about to render its viewport, if this returns false we don't render
visible = xr_interface->pre_draw_viewport(vp->render_target);
@@ -612,7 +595,7 @@ void RendererViewport::draw_viewports() {
visible = true;
}
- if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::storage->render_target_was_used(vp->render_target)) {
+ if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::texture_storage->render_target_was_used(vp->render_target)) {
visible = true;
}
@@ -641,13 +624,13 @@ void RendererViewport::draw_viewports() {
continue; //should not draw
}
- RENDER_TIMESTAMP(">Rendering Viewport " + itos(i));
+ RENDER_TIMESTAMP("> Render Viewport " + itos(i));
- RSG::storage->render_target_set_as_unused(vp->render_target);
+ RSG::texture_storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
// check for an external texture destination (disabled for now, not yet supported)
- // RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
- RSG::storage->render_target_set_external_texture(vp->render_target, 0);
+ // RSG::texture_storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+ RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
// render...
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -669,7 +652,7 @@ void RendererViewport::draw_viewports() {
}
}
} else {
- RSG::storage->render_target_set_external_texture(vp->render_target, 0);
+ RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -699,7 +682,7 @@ void RendererViewport::draw_viewports() {
vp->update_mode = RS::VIEWPORT_UPDATE_DISABLED;
}
- RENDER_TIMESTAMP("<Rendering Viewport " + itos(i));
+ RENDER_TIMESTAMP("< Render Viewport " + itos(i));
objects_drawn += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME];
vertices_drawn += vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] + vp->render_info.info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME];
@@ -711,7 +694,7 @@ void RendererViewport::draw_viewports() {
total_vertices_drawn = vertices_drawn;
total_draw_calls_used = draw_calls_used;
- RENDER_TIMESTAMP("<Render Viewports");
+ RENDER_TIMESTAMP("< Render Viewports");
//this needs to be called to make screen swapping more efficient
RSG::rasterizer->prepare_for_blitting_render_targets();
@@ -728,7 +711,7 @@ void RendererViewport::viewport_initialize(RID p_rid) {
viewport_owner.initialize_rid(p_rid);
Viewport *viewport = viewport_owner.get_or_null(p_rid);
viewport->self = p_rid;
- viewport->render_target = RSG::storage->render_target_create();
+ viewport->render_target = RSG::texture_storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
@@ -810,7 +793,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
viewport->size = Size2(p_width, p_height);
uint32_t view_count = viewport->get_view_count();
- RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
_configure_3d_render_buffers(viewport);
viewport->occlusion_buffer_dirty = true;
@@ -851,8 +834,8 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
- RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
viewport->viewport_to_screen_rect = p_rect;
@@ -860,8 +843,8 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
} else {
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
viewport->viewport_to_screen_rect = Rect2();
@@ -879,17 +862,17 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
- RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
- RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
+ RSG::texture_storage->render_target_set_direct_to_screen(viewport->render_target, 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
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
- RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
- RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
@@ -904,7 +887,7 @@ RID RendererViewport::viewport_get_texture(RID p_viewport) const {
const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND_V(!viewport, RID());
- return RSG::storage->render_target_get_texture(viewport->render_target);
+ return RSG::texture_storage->render_target_get_texture(viewport->render_target);
}
RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const {
@@ -917,6 +900,22 @@ RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const
return RID();
}
+void RendererViewport::viewport_set_prev_camera_data(RID p_viewport, const RendererSceneRender::CameraData *p_camera_data) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+ uint64_t frame = RSG::rasterizer->get_frame_number();
+ if (viewport->prev_camera_data_frame != frame) {
+ viewport->prev_camera_data = *p_camera_data;
+ viewport->prev_camera_data_frame = frame;
+ }
+}
+
+const RendererSceneRender::CameraData *RendererViewport::viewport_get_prev_camera_data(RID p_viewport) {
+ const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND_V(!viewport, nullptr);
+ return &viewport->prev_camera_data;
+}
+
void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -997,7 +996,7 @@ void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
+ RSG::texture_storage->render_target_set_transparent(viewport->render_target, p_enabled);
viewport->transparent_bg = p_enabled;
}
@@ -1056,6 +1055,17 @@ void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::Viewport
_configure_3d_render_buffers(viewport);
}
+void RendererViewport::viewport_set_use_taa(RID p_viewport, bool p_use_taa) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ if (viewport->use_taa == p_use_taa) {
+ return;
+ }
+ viewport->use_taa = p_use_taa;
+ _configure_3d_render_buffers(viewport);
+}
+
void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -1180,21 +1190,21 @@ void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::V
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
+ RSG::texture_storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
}
bool RendererViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.get_or_null(p_rid);
- RSG::storage->free(viewport->render_target);
+ RSG::texture_storage->render_target_free(viewport->render_target);
RSG::scene->free(viewport->shadow_atlas);
if (viewport->render_buffers.is_valid()) {
RSG::scene->free(viewport->render_buffers);
}
- while (viewport->canvas_map.front()) {
- viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key());
+ while (viewport->canvas_map.begin()) {
+ viewport_remove_canvas(p_rid, viewport->canvas_map.begin()->key);
}
viewport_set_scenario(p_rid, RID());
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 2245d9a216..18385d1613 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -35,6 +35,7 @@
#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/rendering_server.h"
#include "servers/xr/xr_interface.h"
@@ -66,8 +67,12 @@ public:
RS::ViewportMSAA msaa;
RS::ViewportScreenSpaceAA screen_space_aa;
+ bool use_taa;
bool use_debanding;
+ RendererSceneRender::CameraData prev_camera_data;
+ uint64_t prev_camera_data_frame = 0;
+
bool use_occlusion_culling;
bool occlusion_buffer_dirty;
@@ -129,7 +134,7 @@ public:
};
struct CanvasData {
- CanvasBase *canvas;
+ CanvasBase *canvas = nullptr;
Transform2D transform;
int layer;
int sublayer;
@@ -137,7 +142,7 @@ public:
Transform2D global_transform;
- Map<RID, CanvasData> canvas_map;
+ HashMap<RID, CanvasData> canvas_map;
RendererScene::RenderInfo render_info;
@@ -233,6 +238,9 @@ public:
RID viewport_get_texture(RID p_viewport) const;
RID viewport_get_occluder_debug_texture(RID p_viewport) const;
+ void viewport_set_prev_camera_data(RID p_viewport, const RendererSceneRender::CameraData *p_camera_data);
+ const RendererSceneRender::CameraData *viewport_get_prev_camera_data(RID p_viewport);
+
void viewport_set_disable_2d(RID p_viewport, bool p_disable);
void viewport_set_disable_environment(RID p_viewport, bool p_disable);
void viewport_set_disable_3d(RID p_viewport, bool p_disable);
@@ -252,6 +260,7 @@ public:
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
+ void viewport_set_use_taa(RID p_viewport, bool p_use_taa);
void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding);
void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling);
void viewport_set_occlusion_rays_per_thread(int p_rays_per_thread);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 49d89bcadc..0973e29974 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -528,6 +528,7 @@ public:
/*********************/
struct AttachmentFormat {
+ enum { UNUSED_ATTACHMENT = 0xFFFFFFFF };
DataFormat format;
TextureSamples samples;
uint32_t usage_flags;
@@ -726,16 +727,65 @@ public:
struct Uniform {
UniformType uniform_type;
- int binding; //binding index as specified in shader
+ int binding; // Binding index as specified in shader.
- //for single items, provide one ID, for
- //multiple items (declared as arrays in shader),
- //provide more
- //for sampler with texture, supply two IDs for each.
- //accepted IDs are: Sampler, Texture, Uniform Buffer and Texture Buffer
- Vector<RID> ids;
+ private:
+ // In most cases only one ID is provided per binding, so avoid allocating memory unnecessarily for performance.
+ RID id; // If only one is provided, this is used.
+ Vector<RID> ids; // If multiple ones are provided, this is used instead.
- Uniform() {
+ public:
+ _FORCE_INLINE_ uint32_t get_id_count() const {
+ return (id.is_valid() ? 1 : ids.size());
+ }
+
+ _FORCE_INLINE_ RID get_id(uint32_t p_idx) const {
+ if (id.is_valid()) {
+ ERR_FAIL_COND_V(p_idx != 0, RID());
+ return id;
+ } else {
+ return ids[p_idx];
+ }
+ }
+ _FORCE_INLINE_ void set_id(uint32_t p_idx, RID p_id) {
+ if (id.is_valid()) {
+ ERR_FAIL_COND(p_idx != 0);
+ id = p_id;
+ } else {
+ ids.write[p_idx] = p_id;
+ }
+ }
+
+ _FORCE_INLINE_ void append_id(RID p_id) {
+ if (ids.is_empty()) {
+ if (id == RID()) {
+ id = p_id;
+ } else {
+ ids.push_back(id);
+ ids.push_back(p_id);
+ id = RID();
+ }
+ } else {
+ ids.push_back(p_id);
+ }
+ }
+
+ _FORCE_INLINE_ void clear_ids() {
+ id = RID();
+ ids.clear();
+ }
+
+ _FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, RID p_id) {
+ uniform_type = p_type;
+ binding = p_binding;
+ id = p_id;
+ }
+ _FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, const Vector<RID> &p_ids) {
+ uniform_type = p_type;
+ binding = p_binding;
+ ids = p_ids;
+ }
+ _FORCE_INLINE_ Uniform() {
uniform_type = UNIFORM_TYPE_IMAGE;
binding = 0;
}
@@ -1173,7 +1223,7 @@ public:
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z,
};
- virtual int limit_get(Limit p_limit) = 0;
+ virtual uint64_t limit_get(Limit p_limit) = 0;
//methods below not exposed, used by RenderingDeviceRD
virtual void prepare_screen_for_drawing() = 0;
@@ -1204,6 +1254,7 @@ public:
virtual String get_device_vendor_name() const = 0;
virtual String get_device_name() const = 0;
virtual RenderingDevice::DeviceType get_device_type() const = 0;
+ virtual String get_device_api_version() const = 0;
virtual String get_device_pipeline_cache_uuid() const = 0;
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0) = 0;
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index e50ac42027..d03c4e0427 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -45,7 +45,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
};
String stage_code[RD::SHADER_STAGE_MAX];
int stages_found = 0;
- Map<StringName, String> version_texts;
+ HashMap<StringName, String> version_texts;
versions.clear();
base_error = "";
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index b07857364b..8bdd3deea1 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -329,7 +329,7 @@ protected:
class RDShaderFile : public Resource {
GDCLASS(RDShaderFile, Resource)
- Map<StringName, Ref<RDShaderSPIRV>> versions;
+ HashMap<StringName, Ref<RDShaderSPIRV>> versions;
String base_error;
public:
@@ -441,23 +441,23 @@ public:
RD_SETGET(RD::UniformType, uniform_type)
RD_SETGET(int32_t, binding)
- void add_id(const RID &p_id) { base.ids.push_back(p_id); }
- void clear_ids() { base.ids.clear(); }
+ void add_id(const RID &p_id) { base.append_id(p_id); }
+ void clear_ids() { base.clear_ids(); }
Array get_ids() const {
Array ids;
- for (int i = 0; i < base.ids.size(); i++) {
- ids.push_back(base.ids[i]);
+ for (uint32_t i = 0; i < base.get_id_count(); i++) {
+ ids.push_back(base.get_id(i));
}
return ids;
}
protected:
void _set_ids(const Array &p_ids) {
- base.ids.clear();
+ base.clear_ids();
for (int i = 0; i < p_ids.size(); i++) {
RID id = p_ids[i];
ERR_FAIL_COND(id.is_null());
- base.ids.push_back(id);
+ base.append_id(id);
}
}
static void _bind_methods() {
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index d93aad5d7b..718f20f80a 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -84,7 +84,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0;
- RSG::storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
+ RSG::particles_storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
RSG::scene->render_probes();
@@ -179,10 +179,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
print_line("GPU PROFILE (total " + rtos(total_time) + "ms): ");
float print_threshold = 0.01;
- for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) {
- double time = E.value() / double(print_frame_profile_frame_count);
+ for (const KeyValue<String, float> &E : print_gpu_profile_task_time) {
+ double time = E.value / double(print_frame_profile_frame_count);
if (time > print_threshold) {
- print_line("\t-" + E.key() + ": " + rtos(time) + "ms");
+ print_line("\t-" + E.key + ": " + rtos(time) + "ms");
}
}
print_gpu_profile_task_time.clear();
@@ -265,6 +265,10 @@ RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() con
return RSG::storage->get_video_adapter_type();
}
+String RenderingServerDefault::get_video_adapter_api_version() const {
+ return RSG::storage->get_video_adapter_api_version();
+}
+
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
RSG::storage->capturing_timestamps = p_enable;
}
@@ -309,7 +313,11 @@ RID RenderingServerDefault::get_test_cube() {
}
bool RenderingServerDefault::has_os_feature(const String &p_feature) const {
- return RSG::storage->has_os_feature(p_feature);
+ if (RSG::storage) {
+ return RSG::storage->has_os_feature(p_feature);
+ } else {
+ return false;
+ }
}
void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
@@ -317,11 +325,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
}
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.
- //return RSG::rasterizer->is_low_end();
- return false;
+ return RendererCompositor::is_low_end();
}
void RenderingServerDefault::_thread_exit() {
@@ -384,6 +388,8 @@ void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
command_queue(p_create_thread) {
+ RenderingServer::init();
+
create_thread = p_create_thread;
if (!p_create_thread) {
@@ -398,6 +404,11 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
RendererSceneCull *sr = memnew(RendererSceneCull);
RSG::scene = sr;
RSG::rasterizer = RendererCompositor::create();
+ RSG::light_storage = RSG::rasterizer->get_light_storage();
+ RSG::material_storage = RSG::rasterizer->get_material_storage();
+ RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
+ RSG::particles_storage = RSG::rasterizer->get_particles_storage();
+ RSG::texture_storage = RSG::rasterizer->get_texture_storage();
RSG::storage = RSG::rasterizer->get_storage();
RSG::canvas_render = RSG::rasterizer->get_canvas();
sr->set_scene_render(RSG::rasterizer->get_scene());
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 6d2c36537b..6008f2b00e 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -33,7 +33,7 @@
#include "core/math/octree.h"
#include "core/templates/command_queue_mt.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
#include "renderer_viewport.h"
@@ -69,7 +69,7 @@ class RenderingServerDefault : public RenderingServer {
//for printing
bool print_gpu_profile = false;
- OrderedHashMap<String, float> print_gpu_profile_task_time;
+ HashMap<String, float> print_gpu_profile_task_time;
uint64_t print_frame_profile_ticks_from = 0;
uint32_t print_frame_profile_frame_count = 0;
@@ -113,7 +113,9 @@ public:
_changes_changed();
#else
- _FORCE_INLINE_ static void redraw_request() { changes++; }
+ _FORCE_INLINE_ static void redraw_request() {
+ changes++;
+ }
#endif
#define WRITE_ACTION redraw_request();
@@ -126,54 +128,53 @@ public:
#include "servers/server_wrap_mt_common.h"
-//from now on, calls forwarded to this singleton
-#define ServerName RendererStorage
-#define server_name RSG::storage
-
/* TEXTURE API */
-#define FUNCRIDTEX0(m_type) \
- virtual RID m_type##_create() override { \
- RID ret = RSG::storage->texture_allocate(); \
- if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
- RSG::storage->m_type##_initialize(ret); \
- } else { \
- command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret); \
- } \
- return ret; \
+#define ServerName RendererTextureStorage
+#define server_name RSG::texture_storage
+
+#define FUNCRIDTEX0(m_type) \
+ virtual RID m_type##_create() override { \
+ RID ret = RSG::texture_storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \
+ RSG::texture_storage->m_type##_initialize(ret); \
+ } else { \
+ command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret); \
+ } \
+ return ret; \
}
-#define FUNCRIDTEX1(m_type, m_type1) \
- virtual RID m_type##_create(m_type1 p1) override { \
- RID ret = RSG::storage->texture_allocate(); \
- if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
- RSG::storage->m_type##_initialize(ret, p1); \
- } else { \
- command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1); \
- } \
- return ret; \
+#define FUNCRIDTEX1(m_type, m_type1) \
+ virtual RID m_type##_create(m_type1 p1) override { \
+ RID ret = RSG::texture_storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \
+ RSG::texture_storage->m_type##_initialize(ret, p1); \
+ } else { \
+ command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1); \
+ } \
+ return ret; \
}
-#define FUNCRIDTEX2(m_type, m_type1, m_type2) \
- virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \
- RID ret = RSG::storage->texture_allocate(); \
- if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
- RSG::storage->m_type##_initialize(ret, p1, p2); \
- } else { \
- command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2); \
- } \
- return ret; \
+#define FUNCRIDTEX2(m_type, m_type1, m_type2) \
+ virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \
+ RID ret = RSG::texture_storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \
+ RSG::texture_storage->m_type##_initialize(ret, p1, p2); \
+ } else { \
+ command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2); \
+ } \
+ return ret; \
}
-#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
- virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \
- RID ret = RSG::storage->texture_allocate(); \
- if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
- RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \
- } else { \
- command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \
- } \
- return ret; \
+#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
+ virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \
+ RID ret = RSG::texture_storage->texture_allocate(); \
+ if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \
+ RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \
+ } else { \
+ command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \
+ } \
+ return ret; \
}
//these go pass-through, as they can be called from any thread
@@ -216,6 +217,12 @@ public:
/* SHADER API */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererMaterialStorage
+#define server_name RSG::material_storage
+
FUNCRIDSPLIT(shader)
FUNC2(shader_set_code, RID, const String &)
@@ -243,23 +250,32 @@ public:
/* MESH API */
+//from now on, calls forwarded to this singleton
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererMeshStorage
+#define server_name RSG::mesh_storage
+
virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
- RID mesh = RSG::storage->mesh_allocate();
+ RID mesh = RSG::mesh_storage->mesh_allocate();
- if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) {
+ // TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!!
+
+ if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) {
if (Thread::get_caller_id() == server_thread) {
command_queue.flush_if_pending();
}
- RSG::storage->mesh_initialize(mesh);
- RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
+ RSG::mesh_storage->mesh_initialize(mesh);
+ RSG::mesh_storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
for (int i = 0; i < p_surfaces.size(); i++) {
- RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+ RSG::mesh_storage->mesh_add_surface(mesh, p_surfaces[i]);
}
} else {
- command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh);
- command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_initialize, mesh);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
for (int i = 0; i < p_surfaces.size(); i++) {
- command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_add_surface, mesh, p_surfaces[i]);
}
}
@@ -334,6 +350,11 @@ public:
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
/* Light API */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererLightStorage
+#define server_name RSG::light_storage
FUNCRIDSPLIT(directional_light)
FUNCRIDSPLIT(omni_light)
@@ -342,10 +363,10 @@ public:
FUNC2(light_set_color, RID, const Color &)
FUNC3(light_set_param, RID, LightParam, float)
FUNC2(light_set_shadow, RID, bool)
- FUNC2(light_set_shadow_color, RID, const Color &)
FUNC2(light_set_projector, RID, RID)
FUNC2(light_set_negative, RID, bool)
FUNC2(light_set_cull_mask, RID, uint32_t)
+ FUNC5(light_set_distance_fade, RID, bool, float, float, float)
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
FUNC2(light_set_bake_mode, RID, LightBakeMode)
FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
@@ -354,7 +375,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_sky_mode, RID, LightDirectionalSkyMode)
/* PROBE API */
@@ -375,8 +396,28 @@ public:
FUNC2(reflection_probe_set_resolution, RID, int)
FUNC2(reflection_probe_set_mesh_lod_threshold, RID, float)
+ /* LIGHTMAP */
+
+ FUNCRIDSPLIT(lightmap)
+
+ FUNC3(lightmap_set_textures, RID, RID, bool)
+ FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
+ FUNC2(lightmap_set_probe_interior, RID, bool)
+ FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+ FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+ FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
+ FUNC1(lightmap_set_probe_capture_update_speed, float)
+
/* DECAL API */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererTextureStorage
+#define server_name RSG::texture_storage
+
FUNCRIDSPLIT(decal)
FUNC2(decal_set_extents, RID, const Vector3 &)
@@ -391,6 +432,13 @@ public:
/* BAKED LIGHT API */
+//from now on, calls forwarded to this singleton
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
FUNCRIDSPLIT(voxel_gi)
FUNC8(voxel_gi_allocate_data, RID, const Transform3D &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
@@ -411,21 +459,13 @@ public:
FUNC2(voxel_gi_set_interior, RID, bool)
FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
- /* LIGHTMAP */
-
- FUNCRIDSPLIT(lightmap)
+ /* PARTICLES */
- FUNC3(lightmap_set_textures, RID, RID, bool)
- FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
- FUNC2(lightmap_set_probe_interior, RID, bool)
- FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
- FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
- FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
- FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
- FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
- FUNC1(lightmap_set_probe_capture_update_speed, float)
+#undef ServerName
+#undef server_name
- /* PARTICLES */
+#define ServerName RendererParticlesStorage
+#define server_name RSG::particles_storage
FUNCRIDSPLIT(particles)
@@ -482,6 +522,12 @@ public:
/* FOG VOLUME */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
FUNCRIDSPLIT(fog_volume)
FUNC2(fog_volume_set_shape, RID, FogVolumeShape)
@@ -570,6 +616,7 @@ public:
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
+ FUNC2(viewport_set_use_taa, RID, bool)
FUNC2(viewport_set_use_debanding, RID, bool)
FUNC2(viewport_set_use_occlusion_culling, RID, bool)
FUNC1(viewport_set_occlusion_rays_per_thread, int)
@@ -767,7 +814,7 @@ public:
FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
- FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
+ FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
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 &)
@@ -849,8 +896,8 @@ public:
#undef server_name
#undef ServerName
//from now on, calls forwarded to this singleton
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererMaterialStorage
+#define server_name RSG::material_storage
FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
FUNC1(global_variable_remove, const StringName &)
@@ -895,6 +942,7 @@ public:
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
+ virtual String get_video_adapter_api_version() const override;
virtual void set_frame_profiling_enabled(bool p_enable) override;
virtual Vector<FrameProfileArea> get_frame_profile() override;
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index b8b06b5eea..4d24dbf3b4 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -32,6 +32,11 @@
bool RenderingServerGlobals::threaded = false;
+RendererLightStorage *RenderingServerGlobals::light_storage = nullptr;
+RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
+RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
+RendererParticlesStorage *RenderingServerGlobals::particles_storage = nullptr;
+RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
RendererStorage *RenderingServerGlobals::storage = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
RendererCompositor *RenderingServerGlobals::rasterizer = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 4351830a5f..ce11fae9e8 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -34,6 +34,11 @@
#include "servers/rendering/renderer_canvas_cull.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
+#include "servers/rendering/storage/light_storage.h"
+#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/particles_storage.h"
+#include "servers/rendering/storage/texture_storage.h"
class RendererCanvasCull;
class RendererViewport;
@@ -43,6 +48,11 @@ class RenderingServerGlobals {
public:
static bool threaded;
+ static RendererLightStorage *light_storage;
+ static RendererMaterialStorage *material_storage;
+ static RendererMeshStorage *mesh_storage;
+ static RendererParticlesStorage *particles_storage;
+ static RendererTextureStorage *texture_storage;
static RendererStorage *storage;
static RendererCanvasRender *canvas_render;
static RendererCompositor *rasterizer;
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 812d636a0b..463b67033d 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -48,8 +48,8 @@ static String _mktab(int p_level) {
static String _typestr(SL::DataType p_type) {
String type = ShaderLanguage::get_datatype_name(p_type);
- if (ShaderLanguage::is_sampler_type(p_type)) {
- type = type.replace("sampler", "texture"); //we use textures instead of samplers
+ if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
+ type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
}
return type;
}
@@ -289,7 +289,7 @@ String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter,
return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]";
}
-void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
+void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, HashSet<StringName> &added) {
int fidx = -1;
for (int i = 0; i < p_node->functions.size(); i++) {
@@ -303,8 +303,8 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
Vector<StringName> uses_functions;
- for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) {
- uses_functions.push_back(E->get());
+ for (const StringName &E : p_node->functions[fidx].uses_function) {
+ uses_functions.push_back(E);
}
uses_functions.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
@@ -538,7 +538,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
continue; // Instances are indexed directly, don't need index uniforms.
}
if (SL::is_sampler_type(uniform.type)) {
- ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform ";
+ // Texture layouts are different for OpenGL GLSL and Vulkan GLSL
+ if (!RS::get_singleton()->is_low_end()) {
+ ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
+ }
+ ucode += "uniform ";
}
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -567,6 +571,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
texture.name = uniform_name;
texture.hint = uniform.hint;
texture.type = uniform.type;
+ texture.use_color = uniform.use_color;
texture.filter = uniform.filter;
texture.repeat = uniform.repeat;
texture.global = uniform.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -681,9 +686,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
vcode += ";\n";
-
- r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode;
- r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode;
+ // GLSL ES 3.0 does not allow layout qualifiers for varyings
+ if (!RS::get_singleton()->is_low_end()) {
+ r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") ";
+ r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") ";
+ }
+ r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode;
+ r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;
index += inc;
}
@@ -727,7 +736,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
}
- Map<StringName, String> function_code;
+ HashMap<StringName, String> function_code;
//code for functions
for (int i = 0; i < pnode->functions.size(); i++) {
@@ -740,7 +749,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
//place functions in actual code
- Set<StringName> added_funcs_per_stage[STAGE_MAX];
+ HashSet<StringName> added_funcs_per_stage[STAGE_MAX];
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
@@ -1125,8 +1134,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += ", ";
}
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (is_texture_func && i == 1) {
- //need to map from texture to sampler in order to sample
+ if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
+ //need to map from texture to sampler in order to sample when using Vulkan GLSL
StringName texture_uniform;
bool correct_texture_uniform = false;
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index 8f0ee664ac..06f42e9f0f 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -45,14 +45,14 @@ public:
};
struct IdentifierActions {
- Map<StringName, Stage> entry_point_stages;
+ HashMap<StringName, Stage> entry_point_stages;
- Map<StringName, Pair<int *, int>> render_mode_values;
- Map<StringName, bool *> render_mode_flags;
- Map<StringName, bool *> usage_flag_pointers;
- Map<StringName, bool *> write_flag_pointers;
+ HashMap<StringName, Pair<int *, int>> render_mode_values;
+ HashMap<StringName, bool *> render_mode_flags;
+ HashMap<StringName, bool *> usage_flag_pointers;
+ HashMap<StringName, bool *> write_flag_pointers;
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms;
};
struct GeneratedCode {
@@ -61,6 +61,7 @@ public:
StringName name;
ShaderLanguage::DataType type;
ShaderLanguage::ShaderNode::Uniform::Hint hint;
+ bool use_color = false;
ShaderLanguage::TextureFilter filter;
ShaderLanguage::TextureRepeat repeat;
bool global;
@@ -74,7 +75,7 @@ public:
String uniforms;
String stage_globals[STAGE_MAX];
- Map<String, String> code;
+ HashMap<String, String> code;
bool uses_global_textures;
bool uses_fragment_time;
@@ -82,10 +83,10 @@ public:
};
struct DefaultIdentifierActions {
- Map<StringName, String> renames;
- Map<StringName, String> render_mode_defines;
- Map<StringName, String> usage_defines;
- Map<StringName, String> custom_samplers;
+ HashMap<StringName, String> renames;
+ HashMap<StringName, String> render_mode_defines;
+ HashMap<StringName, String> usage_defines;
+ HashMap<StringName, String> custom_samplers;
ShaderLanguage::TextureFilter default_filter;
ShaderLanguage::TextureRepeat default_repeat;
String sampler_array_name;
@@ -103,20 +104,20 @@ private:
String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat);
- void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
+ void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, HashSet<StringName> &added);
String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_scope = true);
- const ShaderLanguage::ShaderNode *shader;
- const ShaderLanguage::FunctionNode *function;
+ const ShaderLanguage::ShaderNode *shader = nullptr;
+ const ShaderLanguage::FunctionNode *function = nullptr;
StringName current_func_name;
StringName time_name;
- Set<StringName> texture_functions;
+ HashSet<StringName> texture_functions;
- Set<StringName> used_name_defines;
- Set<StringName> used_flag_pointers;
- Set<StringName> used_rmode_defines;
- Set<StringName> internal_functions;
- Set<StringName> fragment_varyings;
+ HashSet<StringName> used_name_defines;
+ HashSet<StringName> used_flag_pointers;
+ HashSet<StringName> used_rmode_defines;
+ HashSet<StringName> internal_functions;
+ HashSet<StringName> fragment_varyings;
DefaultIdentifierActions actions;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 7683cf20b3..ad9b51ac0c 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -190,13 +190,11 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"OUT",
"INOUT",
"RENDER_MODE",
- "HINT_WHITE_TEXTURE",
- "HINT_BLACK_TEXTURE",
+ "SOURCE_COLOR",
+ "HINT_DEFAULT_WHITE_TEXTURE",
+ "HINT_DEFAULT_BLACK_TEXTURE",
"HINT_NORMAL_TEXTURE",
"HINT_ANISOTROPY_TEXTURE",
- "HINT_ALBEDO_TEXTURE",
- "HINT_BLACK_ALBEDO_TEXTURE",
- "HINT_COLOR",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
"FILTER_NEAREST",
@@ -237,92 +235,139 @@ ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type, const String
return tk;
}
+enum ContextFlag : uint32_t {
+ CF_UNSPECIFIED = 0U,
+ CF_BLOCK = 1U, // "void test() { <x> }"
+ CF_FUNC_DECL_PARAM_SPEC = 2U, // "void test(<x> int param) {}"
+ CF_FUNC_DECL_PARAM_TYPE = 4U, // "void test(<x> param) {}"
+ CF_IF_DECL = 8U, // "if(<x>) {}"
+ CF_BOOLEAN = 16U, // "bool t = <x>;"
+ CF_GLOBAL_SPACE = 32U, // "struct", "const", "void" etc.
+ CF_DATATYPE = 64U, // "<x> value;"
+ CF_UNIFORM_TYPE = 128U, // "uniform <x> myUniform;"
+ CF_VARYING_TYPE = 256U, // "varying <x> myVarying;"
+ CF_PRECISION_MODIFIER = 512U, // "<x> vec4 a = vec4(0.0, 1.0, 2.0, 3.0);"
+ CF_INTERPOLATION_QUALIFIER = 1024U, // "varying <x> vec3 myColor;"
+ CF_UNIFORM_KEYWORD = 2048U, // "uniform"
+ CF_CONST_KEYWORD = 4096U, // "const"
+ CF_UNIFORM_QUALIFIER = 8192U, // "<x> uniform float t;"
+};
+
+const uint32_t KCF_DATATYPE = CF_BLOCK | CF_GLOBAL_SPACE | CF_DATATYPE | CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE;
+const uint32_t KCF_SAMPLER_DATATYPE = CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE;
+
const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
- { TK_TRUE, "true" },
- { TK_FALSE, "false" },
- { TK_TYPE_VOID, "void" },
- { TK_TYPE_BOOL, "bool" },
- { TK_TYPE_BVEC2, "bvec2" },
- { TK_TYPE_BVEC3, "bvec3" },
- { TK_TYPE_BVEC4, "bvec4" },
- { TK_TYPE_INT, "int" },
- { TK_TYPE_IVEC2, "ivec2" },
- { TK_TYPE_IVEC3, "ivec3" },
- { TK_TYPE_IVEC4, "ivec4" },
- { TK_TYPE_UINT, "uint" },
- { TK_TYPE_UVEC2, "uvec2" },
- { TK_TYPE_UVEC3, "uvec3" },
- { TK_TYPE_UVEC4, "uvec4" },
- { TK_TYPE_FLOAT, "float" },
- { TK_TYPE_VEC2, "vec2" },
- { TK_TYPE_VEC3, "vec3" },
- { TK_TYPE_VEC4, "vec4" },
- { TK_TYPE_MAT2, "mat2" },
- { TK_TYPE_MAT3, "mat3" },
- { TK_TYPE_MAT4, "mat4" },
- { TK_TYPE_SAMPLER2D, "sampler2D" },
- { TK_TYPE_ISAMPLER2D, "isampler2D" },
- { TK_TYPE_USAMPLER2D, "usampler2D" },
- { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" },
- { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" },
- { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" },
- { TK_TYPE_SAMPLER3D, "sampler3D" },
- { TK_TYPE_ISAMPLER3D, "isampler3D" },
- { TK_TYPE_USAMPLER3D, "usampler3D" },
- { TK_TYPE_SAMPLERCUBE, "samplerCube" },
- { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray" },
- { TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_SMOOTH, "smooth" },
- { TK_CONST, "const" },
- { TK_STRUCT, "struct" },
- { TK_PRECISION_LOW, "lowp" },
- { TK_PRECISION_MID, "mediump" },
- { TK_PRECISION_HIGH, "highp" },
- { TK_CF_IF, "if" },
- { TK_CF_ELSE, "else" },
- { TK_CF_FOR, "for" },
- { TK_CF_WHILE, "while" },
- { TK_CF_DO, "do" },
- { TK_CF_SWITCH, "switch" },
- { TK_CF_CASE, "case" },
- { TK_CF_DEFAULT, "default" },
- { TK_CF_BREAK, "break" },
- { TK_CF_CONTINUE, "continue" },
- { TK_CF_RETURN, "return" },
- { TK_CF_DISCARD, "discard" },
- { TK_UNIFORM, "uniform" },
- { TK_INSTANCE, "instance" },
- { TK_GLOBAL, "global" },
- { TK_VARYING, "varying" },
- { TK_ARG_IN, "in" },
- { TK_ARG_OUT, "out" },
- { TK_ARG_INOUT, "inout" },
- { TK_RENDER_MODE, "render_mode" },
- { TK_HINT_WHITE_TEXTURE, "hint_white" },
- { TK_HINT_BLACK_TEXTURE, "hint_black" },
- { TK_HINT_NORMAL_TEXTURE, "hint_normal" },
- { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal" },
- { TK_HINT_ROUGHNESS_R, "hint_roughness_r" },
- { TK_HINT_ROUGHNESS_G, "hint_roughness_g" },
- { TK_HINT_ROUGHNESS_B, "hint_roughness_b" },
- { TK_HINT_ROUGHNESS_A, "hint_roughness_a" },
- { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" },
- { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy" },
- { TK_HINT_ALBEDO_TEXTURE, "hint_albedo" },
- { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
- { TK_HINT_COLOR, "hint_color" },
- { TK_HINT_RANGE, "hint_range" },
- { TK_HINT_INSTANCE_INDEX, "instance_index" },
- { TK_FILTER_NEAREST, "filter_nearest" },
- { TK_FILTER_LINEAR, "filter_linear" },
- { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
- { TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" },
- { TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC, "filter_nearest_mipmap_anisotropic" },
- { TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC, "filter_linear_mipmap_anisotropic" },
- { TK_REPEAT_ENABLE, "repeat_enable" },
- { TK_REPEAT_DISABLE, "repeat_disable" },
- { TK_SHADER_TYPE, "shader_type" },
- { TK_ERROR, nullptr }
+ { TK_TRUE, "true", CF_BLOCK | CF_IF_DECL | CF_BOOLEAN, {}, {} },
+ { TK_FALSE, "false", CF_BLOCK | CF_IF_DECL | CF_BOOLEAN, {}, {} },
+
+ // data types
+
+ { TK_TYPE_VOID, "void", CF_GLOBAL_SPACE, {}, {} },
+ { TK_TYPE_BOOL, "bool", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_BVEC2, "bvec2", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_BVEC3, "bvec3", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_BVEC4, "bvec4", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_INT, "int", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_IVEC2, "ivec2", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_IVEC3, "ivec3", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_IVEC4, "ivec4", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UINT, "uint", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UVEC2, "uvec2", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UVEC3, "uvec3", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UVEC4, "uvec4", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_FLOAT, "float", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_VEC2, "vec2", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_VEC3, "vec3", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_VEC4, "vec4", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_MAT2, "mat2", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_MAT3, "mat3", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_MAT4, "mat4", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_SAMPLER2D, "sampler2D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_ISAMPLER2D, "isampler2D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_USAMPLER2D, "usampler2D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLER3D, "sampler3D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_ISAMPLER3D, "isampler3D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_USAMPLER3D, "usampler3D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLERCUBE, "samplerCube", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray", KCF_SAMPLER_DATATYPE, {}, {} },
+
+ // interpolation qualifiers
+
+ { TK_INTERPOLATION_FLAT, "flat", CF_INTERPOLATION_QUALIFIER, {}, {} },
+ { TK_INTERPOLATION_SMOOTH, "smooth", CF_INTERPOLATION_QUALIFIER, {}, {} },
+
+ // precision modifiers
+
+ { TK_PRECISION_LOW, "lowp", CF_BLOCK | CF_PRECISION_MODIFIER, {}, {} },
+ { TK_PRECISION_MID, "mediump", CF_BLOCK | CF_PRECISION_MODIFIER, {}, {} },
+ { TK_PRECISION_HIGH, "highp", CF_BLOCK | CF_PRECISION_MODIFIER, {}, {} },
+
+ // global space keywords
+
+ { TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} },
+ { TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} },
+ { TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} },
+ { TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
+ { TK_SHADER_TYPE, "shader_type", CF_GLOBAL_SPACE, {}, {} },
+ { TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} },
+
+ // uniform qualifiers
+
+ { TK_INSTANCE, "instance", CF_GLOBAL_SPACE | CF_UNIFORM_QUALIFIER, {}, {} },
+ { TK_GLOBAL, "global", CF_GLOBAL_SPACE | CF_UNIFORM_QUALIFIER, {}, {} },
+
+ // block keywords
+
+ { TK_CF_IF, "if", CF_BLOCK, {}, {} },
+ { TK_CF_ELSE, "else", CF_BLOCK, {}, {} },
+ { TK_CF_FOR, "for", CF_BLOCK, {}, {} },
+ { TK_CF_WHILE, "while", CF_BLOCK, {}, {} },
+ { TK_CF_DO, "do", CF_BLOCK, {}, {} },
+ { TK_CF_SWITCH, "switch", CF_BLOCK, {}, {} },
+ { TK_CF_CASE, "case", CF_BLOCK, {}, {} },
+ { TK_CF_DEFAULT, "default", CF_BLOCK, {}, {} },
+ { TK_CF_BREAK, "break", CF_BLOCK, {}, {} },
+ { TK_CF_CONTINUE, "continue", CF_BLOCK, {}, {} },
+ { TK_CF_RETURN, "return", CF_BLOCK, {}, {} },
+ { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "fragment" } },
+
+ // function specifier keywords
+
+ { TK_ARG_IN, "in", CF_FUNC_DECL_PARAM_SPEC, {}, {} },
+ { TK_ARG_OUT, "out", CF_FUNC_DECL_PARAM_SPEC, {}, {} },
+ { TK_ARG_INOUT, "inout", CF_FUNC_DECL_PARAM_SPEC, {}, {} },
+
+ // hints
+
+ { TK_HINT_SOURCE_COLOR, "source_color", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_RANGE, "hint_range", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_INSTANCE_INDEX, "instance_index", CF_UNSPECIFIED, {}, {} },
+
+ // sampler hints
+
+ { TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEFAULT_WHITE_TEXTURE, "hint_default_white", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEFAULT_BLACK_TEXTURE, "hint_default_black", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_B, "hint_roughness_b", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC, "filter_nearest_mipmap_anisotropic", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC, "filter_linear_mipmap_anisotropic", CF_UNSPECIFIED, {}, {} },
+ { TK_REPEAT_ENABLE, "repeat_enable", CF_UNSPECIFIED, {}, {} },
+ { TK_REPEAT_DISABLE, "repeat_disable", CF_UNSPECIFIED, {}, {} },
+
+ { TK_ERROR, nullptr, CF_UNSPECIFIED, {}, {} }
};
ShaderLanguage::Token ShaderLanguage::_get_token() {
@@ -568,12 +613,16 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
String str;
int i = 0;
+ bool digit_after_exp = false;
while (true) {
const char32_t symbol = String::char_lowercase(GETCHAR(i));
bool error = false;
if (is_digit(symbol)) {
+ if (exponent_found) {
+ digit_after_exp = true;
+ }
if (end_suffix_found) {
error = true;
}
@@ -638,7 +687,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
}
} else if (period_found || exponent_found || float_suffix_found) { // Float
- if (exponent_found && (!is_digit(last_char) && last_char != 'f')) { // checks for eg: "2E", "2E-", "2E+"
+ if (exponent_found && (!digit_after_exp || (!is_digit(last_char) && last_char != 'f'))) { // Checks for eg: "2E", "2E-", "2E+" and 0ef, 0e+f, 0.0ef, 0.0e-f (exponent without digit after it).
return _make_token(TK_ERROR, "Invalid (float) numeric constant");
}
if (period_found) {
@@ -752,6 +801,19 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
#undef GETCHAR
}
+bool ShaderLanguage::_lookup_next(Token &r_tk) {
+ TkPos pre_pos = _get_tkpos();
+ int line = pre_pos.tk_line;
+ _get_token();
+ Token tk = _get_token();
+ _set_tkpos(pre_pos);
+ if (tk.line == line) {
+ r_tk = tk;
+ return true;
+ }
+ return false;
+}
+
String ShaderLanguage::token_debug(const String &p_code) {
clear();
@@ -852,6 +914,13 @@ bool ShaderLanguage::is_token_precision(TokenType p_type) {
p_type == TK_PRECISION_HIGH);
}
+bool ShaderLanguage::is_token_arg_qual(TokenType p_type) {
+ return (
+ p_type == TK_ARG_IN ||
+ p_type == TK_ARG_OUT ||
+ p_type == TK_ARG_INOUT);
+}
+
ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) {
if (p_type == TK_PRECISION_LOW) {
return PRECISION_LOWP;
@@ -949,6 +1018,93 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
return "";
}
+String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
+ String result;
+ switch (p_hint) {
+ case ShaderNode::Uniform::HINT_RANGE: {
+ result = "hint_range";
+ } break;
+ case ShaderNode::Uniform::HINT_SOURCE_COLOR: {
+ result = "hint_color";
+ } break;
+ case ShaderNode::Uniform::HINT_NORMAL: {
+ result = "hint_normal";
+ } break;
+ case ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+ result = "hint_roughness_normal";
+ } break;
+ case ShaderNode::Uniform::HINT_ROUGHNESS_R: {
+ result = "hint_roughness_r";
+ } break;
+ case ShaderNode::Uniform::HINT_ROUGHNESS_G: {
+ result = "hint_roughness_g";
+ } break;
+ case ShaderNode::Uniform::HINT_ROUGHNESS_B: {
+ result = "hint_roughness_b";
+ } break;
+ case ShaderNode::Uniform::HINT_ROUGHNESS_A: {
+ result = "hint_roughness_a";
+ } break;
+ case ShaderNode::Uniform::HINT_ROUGHNESS_GRAY: {
+ result = "hint_roughness_gray";
+ } break;
+ case ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
+ result = "hint_default_black";
+ } break;
+ case ShaderNode::Uniform::HINT_DEFAULT_WHITE: {
+ result = "hint_default_white";
+ } break;
+ case ShaderNode::Uniform::HINT_ANISOTROPY: {
+ result = "hint_anisotropy";
+ } break;
+ default:
+ break;
+ }
+ return result;
+}
+
+String ShaderLanguage::get_texture_filter_name(TextureFilter p_filter) {
+ String result;
+ switch (p_filter) {
+ case FILTER_NEAREST: {
+ result = "filter_nearest";
+ } break;
+ case FILTER_LINEAR: {
+ result = "filter_linear";
+ } break;
+ case FILTER_NEAREST_MIPMAP: {
+ result = "filter_nearest_mipmap";
+ } break;
+ case FILTER_LINEAR_MIPMAP: {
+ result = "filter_linear_mipmap";
+ } break;
+ case FILTER_NEAREST_MIPMAP_ANISOTROPIC: {
+ result = "filter_nearest_mipmap_anisotropic";
+ } break;
+ case FILTER_LINEAR_MIPMAP_ANISOTROPIC: {
+ result = "filter_linear_mipmap_anisotropic";
+ } break;
+ default: {
+ } break;
+ }
+ return result;
+}
+
+String ShaderLanguage::get_texture_repeat_name(TextureRepeat p_repeat) {
+ String result;
+ switch (p_repeat) {
+ case REPEAT_DISABLE: {
+ result = "repeat_disable";
+ } break;
+ case REPEAT_ENABLE: {
+ result = "repeat_enable";
+ } break;
+ default: {
+ } break;
+ }
+ return result;
+}
+
bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
return is_token_datatype(p_type) && p_type != TK_TYPE_VOID;
}
@@ -967,6 +1123,7 @@ void ShaderLanguage::clear() {
completion_base_array = false;
#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
used_constants.clear();
used_varyings.clear();
used_uniforms.clear();
@@ -1701,21 +1858,21 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1729,22 +1886,22 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
// Conversion vectors.
@@ -1756,57 +1913,57 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
// Conversion between matrixes.
@@ -2050,10 +2207,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// modf
- { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
// min
@@ -2073,13 +2230,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// max
@@ -2099,13 +2256,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// clamp
@@ -2125,13 +2282,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
{ "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
- { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
// mix
@@ -2182,31 +2339,31 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// floatBitsToInt
- { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// floatBitsToUint
- { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// intBitsToFloat
- { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// uintBitsToFloat
- { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// Built-ins - geometric functions.
// length
@@ -2295,9 +2452,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// greaterThan
@@ -2309,9 +2466,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// lessThanEqual
@@ -2323,9 +2480,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// greaterThanEqual
@@ -2337,9 +2494,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// equal
@@ -2351,9 +2508,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2369,9 +2526,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2398,38 +2555,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// Built-ins: texture functions.
// textureSize
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
// texture
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
@@ -2437,119 +2594,119 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// textureProj
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
// textureLod
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// texelFetch
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// textureProjLod
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// textureGrad
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
// textureGather
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
// dFdx
- { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// dFdy
- { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// fwidth
- { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// Sub-functions.
// array
- { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true },
+ { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, false },
// Modern functions.
// fma
@@ -2561,17 +2718,17 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// Packing/Unpacking functions.
- { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
- { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
// bitfieldExtract
@@ -2813,7 +2970,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool error = false;
if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) {
- const VariableNode *vn = (VariableNode *)p_func->arguments[arg];
+ const VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg]);
bool is_const = false;
ConstantNode::Value value;
@@ -2825,7 +2982,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
} else {
if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) {
- ConstantNode *cn = (ConstantNode *)p_func->arguments[arg];
+ const ConstantNode *cn = static_cast<ConstantNode *>(p_func->arguments[arg]);
if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) {
int value = cn->values[0].sint;
@@ -3351,17 +3508,7 @@ bool ShaderLanguage::is_float_type(DataType p_type) {
}
}
bool ShaderLanguage::is_sampler_type(DataType p_type) {
- return p_type == TYPE_SAMPLER2D ||
- p_type == TYPE_ISAMPLER2D ||
- p_type == TYPE_USAMPLER2D ||
- p_type == TYPE_SAMPLER2DARRAY ||
- p_type == TYPE_ISAMPLER2DARRAY ||
- p_type == TYPE_USAMPLER2DARRAY ||
- p_type == TYPE_SAMPLER3D ||
- p_type == TYPE_ISAMPLER3D ||
- p_type == TYPE_USAMPLER3D ||
- p_type == TYPE_SAMPLERCUBE ||
- p_type == TYPE_SAMPLERCUBEARRAY;
+ return p_type > TYPE_MAT4 && p_type < TYPE_STRUCT;
}
Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
@@ -3467,7 +3614,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ value = Variant(Quaternion(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
}
break;
case ShaderLanguage::TYPE_UINT:
@@ -3517,7 +3664,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ value = Variant(Quaternion(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
}
break;
case ShaderLanguage::TYPE_FLOAT:
@@ -3548,20 +3695,32 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 3;
- PackedVector3Array array = PackedVector3Array();
- for (int i = 0; i < array_size; i += 3) {
- array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
+ PackedColorArray array = PackedColorArray();
+ for (int i = 0; i < array_size; i += 3) {
+ array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
+ }
+ value = Variant(array);
+ } else {
+ PackedVector3Array array = PackedVector3Array();
+ for (int i = 0; i < array_size; i += 3) {
+ array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
+ }
+ value = Variant(array);
}
- value = Variant(array);
} else {
- value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real));
+ } else {
+ value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ }
}
break;
case ShaderLanguage::TYPE_VEC4:
if (array_size > 0) {
array_size *= 4;
- if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
PackedColorArray array = PackedColorArray();
for (int i = 0; i < array_size; i += 4) {
array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real));
@@ -3578,10 +3737,10 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
value = Variant(array);
}
} else {
- if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
} else {
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ value = Variant(Quaternion(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
}
}
break;
@@ -3760,23 +3919,33 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
break;
case ShaderLanguage::TYPE_VEC3:
if (p_uniform.array_size > 0) {
- pi.type = Variant::PACKED_VECTOR3_ARRAY;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
+ pi.hint = PROPERTY_HINT_COLOR_NO_ALPHA;
+ pi.type = Variant::PACKED_COLOR_ARRAY;
+ } else {
+ pi.type = Variant::PACKED_VECTOR3_ARRAY;
+ }
} else {
- pi.type = Variant::VECTOR3;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
+ pi.hint = PROPERTY_HINT_COLOR_NO_ALPHA;
+ pi.type = Variant::COLOR;
+ } else {
+ pi.type = Variant::VECTOR3;
+ }
}
break;
case ShaderLanguage::TYPE_VEC4: {
if (p_uniform.array_size > 0) {
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
pi.type = Variant::PACKED_COLOR_ARRAY;
} else {
pi.type = Variant::PACKED_FLOAT32_ARRAY;
}
} else {
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
pi.type = Variant::COLOR;
} else {
- pi.type = Variant::PLANE;
+ pi.type = Variant::QUATERNION;
}
}
} break;
@@ -3927,7 +4096,7 @@ uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) {
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
- Set<String> kws;
+ HashSet<String> kws;
int idx = 0;
@@ -3944,8 +4113,8 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
idx++;
}
- for (Set<String>::Element *E = kws.front(); E; E = E->next()) {
- r_keywords->push_back(E->get());
+ for (const String &E : kws) {
+ r_keywords->push_back(E);
}
}
@@ -3964,7 +4133,7 @@ bool ShaderLanguage::is_control_flow_keyword(String p_keyword) {
}
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
- Set<String> kws;
+ HashSet<String> kws;
int idx = 0;
@@ -3974,8 +4143,8 @@ void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
idx++;
}
- for (Set<String>::Element *E = kws.front(); E; E = E->next()) {
- r_keywords->push_back(E->get());
+ for (const String &E : kws) {
+ r_keywords->push_back(E);
}
}
@@ -4132,7 +4301,7 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
case Node::TYPE_OPERATOR: {
- OperatorNode *op_node = (OperatorNode *)p_node;
+ const OperatorNode *op_node = static_cast<const OperatorNode *>(p_node);
for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) {
if (!_check_node_constness(op_node->arguments[i])) {
return false;
@@ -4142,13 +4311,13 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
case Node::TYPE_CONSTANT:
break;
case Node::TYPE_VARIABLE: {
- VariableNode *varn = (VariableNode *)p_node;
+ const VariableNode *varn = static_cast<const VariableNode *>(p_node);
if (!varn->is_const) {
return false;
}
} break;
case Node::TYPE_ARRAY: {
- ArrayNode *arrn = (ArrayNode *)p_node;
+ const ArrayNode *arrn = static_cast<const ArrayNode *>(p_node);
if (!arrn->is_const) {
return false;
}
@@ -4248,9 +4417,9 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
arg->tex_argument_check = true;
arg->tex_argument_filter = p_filter;
arg->tex_argument_repeat = p_repeat;
- for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) {
- for (Set<int>::Element *F = E.value.front(); F; F = F->next()) {
- if (!_propagate_function_call_sampler_uniform_settings(E.key, F->get(), p_filter, p_repeat)) {
+ for (KeyValue<StringName, HashSet<int>> &E : arg->tex_argument_connect) {
+ for (const int &F : E.value) {
+ if (!_propagate_function_call_sampler_uniform_settings(E.key, F, p_filter, p_repeat)) {
return false;
}
}
@@ -4282,9 +4451,9 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
arg->tex_builtin_check = true;
arg->tex_builtin = p_builtin;
- for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) {
- for (Set<int>::Element *F = E.value.front(); F; F = F->next()) {
- if (!_propagate_function_call_sampler_builtin_reference(E.key, F->get(), p_builtin)) {
+ for (KeyValue<StringName, HashSet<int>> &E : arg->tex_argument_connect) {
+ for (const int &F : E.value) {
+ if (!_propagate_function_call_sampler_builtin_reference(E.key, F, p_builtin)) {
return false;
}
}
@@ -4670,16 +4839,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = _parse_array_constructor(p_block, p_function_info);
} else {
DataType datatype;
- DataPrecision precision;
- bool precision_defined = false;
+ DataPrecision precision = PRECISION_DEFAULT;
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
- precision_defined = true;
tk = _get_token();
}
datatype = get_token_datatype(tk.type);
+ if (precision != PRECISION_DEFAULT && _validate_precision(datatype, precision) != OK) {
+ return nullptr;
+ }
+
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -4697,7 +4868,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
OperatorNode *func = alloc_node<OperatorNode>();
func->op = OP_CONSTRUCT;
- if (precision_defined) {
+ if (precision != PRECISION_DEFAULT) {
func->return_precision_cache = precision;
}
@@ -5002,7 +5173,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
for (int j = 0; j < base_function->arguments.size(); j++) {
if (base_function->arguments[j].name == varname) {
if (!base_function->arguments[j].tex_argument_connect.has(call_function->name)) {
- base_function->arguments.write[j].tex_argument_connect[call_function->name] = Set<int>();
+ base_function->arguments.write[j].tex_argument_connect[call_function->name] = HashSet<int>();
}
base_function->arguments.write[j].tex_argument_connect[call_function->name].insert(i);
found = true;
@@ -5134,13 +5305,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
- data_type = call_expression->get_datatype();
} else if (tk.type == TK_BRACKET_OPEN) { // indexing
index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
@@ -5153,7 +5327,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
+ ConstantNode *cnode = static_cast<ConstantNode *>(index_expression);
if (cnode) {
if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
@@ -5282,14 +5456,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_CURSOR) {
//do nothing
} else if (tk.type == TK_PERIOD) {
+#ifdef DEBUG_ENABLED
+ uint32_t prev_keyword_completion_context = keyword_completion_context;
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif
+
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
if (!expr->is_indexed() && expr->get_array_size() > 0) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
@@ -5318,9 +5501,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
StringName member_struct_name = "";
int array_size = 0;
- Set<char> position_symbols;
- Set<char> color_symbols;
- Set<char> texture_symbols;
+ RBSet<char> position_symbols;
+ RBSet<char> color_symbols;
+ RBSet<char> texture_symbols;
bool mix_error = false;
@@ -5587,14 +5770,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->assign_expression = assign_expression;
} else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
- Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
- if (!call_expression) {
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
+ mn->call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
+ if (!mn->call_expression) {
return nullptr;
}
- mn->datatype = call_expression->get_datatype();
- mn->call_expression = call_expression;
} else if (tk.type == TK_BRACKET_OPEN) {
Node *index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
@@ -5607,7 +5792,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
+ ConstantNode *cnode = static_cast<ConstantNode *>(index_expression);
if (cnode) {
if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
@@ -5631,6 +5816,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
expr = mn;
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = prev_keyword_completion_context;
+#endif
+
//todo
//member (period) has priority over any operator
//creates a subindexing expression in place
@@ -6362,8 +6551,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_
Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one, bool p_can_break, bool p_can_continue) {
while (true) {
TkPos pos = _get_tkpos();
-
Token tk = _get_token();
+#ifdef DEBUG_ENABLED
+ Token next;
+#endif // DEBUG_ENABLED
if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) {
if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) {
@@ -6396,6 +6587,16 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
#endif // DEBUG_ENABLED
}
+#ifdef DEBUG_ENABLED
+ uint32_t precision_flag = CF_PRECISION_MODIFIER;
+
+ keyword_completion_context = CF_DATATYPE;
+ if (!is_token_precision(tk.type)) {
+ if (!is_struct) {
+ keyword_completion_context |= precision_flag;
+ }
+ }
+#endif // DEBUG_ENABLED
bool is_const = false;
@@ -6417,10 +6618,26 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!is_struct) {
is_struct = shader->structs.has(tk.text); // check again.
}
- if (is_struct && precision != PRECISION_DEFAULT) {
- _set_error(RTR("The precision modifier cannot be used on structs."));
- return ERR_PARSE_ERROR;
+
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & precision_flag) {
+ keyword_completion_context ^= precision_flag;
+ }
+#endif // DEBUG_ENABLED
+ }
+
+#ifdef DEBUG_ENABLED
+ if (is_const && _lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
}
+ if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= CF_DATATYPE;
+ }
+ }
+#endif // DEBUG_ENABLED
+
+ if (precision != PRECISION_DEFAULT) {
if (!is_token_nonvoid_datatype(tk.type)) {
_set_error(RTR("Expected variable type after precision modifier."));
return ERR_PARSE_ERROR;
@@ -6436,10 +6653,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
DataType type = is_struct ? TYPE_STRUCT : get_token_datatype(tk.type);
- if (_validate_datatype(type) != OK) {
+ if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) {
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
+
int array_size = 0;
bool fixed_array_size = false;
bool first = true;
@@ -6509,7 +6730,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
StringName func_name = parent_function->name;
if (!used_local_vars.has(func_name)) {
- used_local_vars.insert(func_name, Map<StringName, Usage>());
+ used_local_vars.insert(func_name, HashMap<StringName, Usage>());
}
used_local_vars[func_name].insert(name, Usage(tk_line));
@@ -6528,11 +6749,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (RenderingServer::get_singleton()->is_low_end() && is_const) {
- _set_error(RTR("Local const arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
-
Error error = _parse_array_size(p_block, p_function_info, false, &decl.size_expression, &var.array_size, &unknown_size);
if (error != OK) {
return error;
@@ -6543,16 +6759,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
}
-
+#ifdef DEBUG_ENABLED
+ if (var.type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BOOLEAN;
+ }
+#endif // DEBUG_ENABLED
if (var.array_size > 0 || unknown_size) {
bool full_def = false;
if (tk.type == TK_OP_ASSIGN) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Array initialization is only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
-
TkPos prev_pos = _get_tkpos();
tk = _get_token();
@@ -6591,10 +6806,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (is_token_precision(tk.type)) {
precision2 = get_token_precision(tk.type);
tk = _get_token();
- if (shader->structs.has(tk.text)) {
- _set_error(RTR("The precision modifier cannot be used on structs."));
- return ERR_PARSE_ERROR;
- }
if (!is_token_nonvoid_datatype(tk.type)) {
_set_error(RTR("Expected data type after precision modifier."));
return ERR_PARSE_ERROR;
@@ -6615,6 +6826,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
type2 = get_token_datatype(tk.type);
}
+ if (precision2 != PRECISION_DEFAULT && _validate_precision(type2, precision2) != OK) {
+ return ERR_PARSE_ERROR;
+ }
+
int array_size2 = 0;
tk = _get_token();
@@ -6690,7 +6905,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
_set_error(RTR("Expected a constant expression."));
return ERR_PARSE_ERROR;
}
@@ -6746,8 +6961,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!n) {
return ERR_PARSE_ERROR;
}
- if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- OperatorNode *op = ((OperatorNode *)n);
+ if (is_const && n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
+ OperatorNode *op = static_cast<OperatorNode *>(n);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
_set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1));
@@ -6790,8 +7005,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
} while (tk.type == TK_COMMA); //another variable
-
- p_block->statements.push_back((Node *)vdnode);
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
+ p_block->statements.push_back(static_cast<Node *>(vdnode));
} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
//a sub block, just because..
BlockNode *block = alloc_node<BlockNode>();
@@ -6810,10 +7027,16 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_IF;
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_IF_DECL;
+#endif // DEBUG_ENABLED
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n) {
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
if (n->get_datatype() != TYPE_BOOL) {
_set_error(RTR("Expected a boolean expression."));
@@ -6851,11 +7074,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_tkpos(pos); //rollback
}
} else if (tk.type == TK_CF_SWITCH) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(vformat(RTR("The '%s' operator is only supported on high-end platforms."), "switch"));
- return ERR_PARSE_ERROR;
- }
-
// switch() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
@@ -6911,9 +7129,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_tkpos(pos);
continue;
} else {
- Set<int> constants;
+ HashSet<int> constants;
for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates.
- ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i];
+ ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]);
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
@@ -7151,10 +7369,17 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
init_block->parent_block = p_block;
init_block->single_statement = true;
cf->blocks.push_back(init_block);
+
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_DATATYPE;
+#endif // DEBUG_ENABLED
Error err = _parse_block(init_block, p_function_info, true, false, false);
if (err != OK) {
return err;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
BlockNode *condition_block = alloc_node<BlockNode>();
condition_block->block_type = BlockNode::BLOCK_TYPE_FOR_CONDITION;
@@ -7183,6 +7408,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
cf->blocks.push_back(block);
p_block->statements.push_back(cf);
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
err = _parse_block(block, p_function_info, true, true, true);
if (err != OK) {
return err;
@@ -7227,6 +7455,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else {
_set_tkpos(pos); //rollback, wants expression
+#ifdef DEBUG_ENABLED
+ if (b->parent_function->return_type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BOOLEAN;
+ }
+#endif // DEBUG_ENABLED
+
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
if (!expr) {
return ERR_PARSE_ERROR;
@@ -7243,6 +7477,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ if (b->parent_function->return_type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BLOCK;
+ }
+#endif // DEBUG_ENABLED
+
flow->expressions.push_back(expr);
}
@@ -7392,15 +7632,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return OK;
}
-String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types) const {
+String ShaderLanguage::_get_shader_type_list(const HashSet<String> &p_shader_types) const {
// Return a list of shader types as an human-readable string
String valid_types;
- for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
+ for (const String &E : p_shader_types) {
if (!valid_types.is_empty()) {
valid_types += ", ";
}
- valid_types += "'" + E->get() + "'";
+ valid_types += "'" + E + "'";
}
return valid_types;
@@ -7418,47 +7658,39 @@ String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const {
return "";
}
-Error ShaderLanguage::_validate_datatype(DataType p_type) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- bool invalid_type = false;
-
- switch (p_type) {
- case TYPE_UINT:
- case TYPE_UVEC2:
- case TYPE_UVEC3:
- case TYPE_UVEC4:
- case TYPE_ISAMPLER2D:
- case TYPE_USAMPLER2D:
- case TYPE_ISAMPLER3D:
- case TYPE_USAMPLER3D:
- case TYPE_USAMPLER2DARRAY:
- case TYPE_ISAMPLER2DARRAY:
- invalid_type = true;
- break;
- default:
- break;
- }
-
- if (invalid_type) {
- _set_error(vformat(RTR("The \"%s\" type is only supported on high-end platforms."), get_datatype_name(p_type)));
- return ERR_UNAVAILABLE;
- }
+Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_precision) {
+ switch (p_type) {
+ case TYPE_STRUCT: {
+ _set_error(RTR("The precision modifier cannot be used on structs."));
+ return FAILED;
+ } break;
+ case TYPE_BOOL:
+ case TYPE_BVEC2:
+ case TYPE_BVEC3:
+ case TYPE_BVEC4: {
+ _set_error(RTR("The precision modifier cannot be used on boolean types."));
+ return FAILED;
+ } break;
+ default:
+ break;
}
return OK;
}
-Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
Token tk = _get_token();
TkPos prev_pos;
+ Token next;
if (tk.type != TK_SHADER_TYPE) {
_set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
- StringName shader_type_identifier;
_get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
-
if (shader_type_identifier == StringName()) {
_set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
@@ -7476,6 +7708,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
tk = _get_token();
int texture_uniforms = 0;
@@ -7483,8 +7718,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int uniforms = 0;
int instance_index = 0;
#ifdef DEBUG_ENABLED
- int uniform_buffer_size = 0;
- int max_uniform_buffer_size = 0;
+ uint64_t uniform_buffer_size = 0;
+ uint64_t max_uniform_buffer_size = 0;
int uniform_buffer_exceeded_line = -1;
bool check_device_limit_warnings = false;
@@ -7502,7 +7737,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
stages = &p_functions;
const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
- Map<String, String> defined_modes;
+ HashMap<String, String> defined_modes;
while (tk.type != TK_EOF) {
switch (tk.type) {
@@ -7569,7 +7804,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
case TK_STRUCT: {
ShaderNode::Struct st;
DataType type;
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
@@ -7591,16 +7828,20 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
st.shader_struct = st_node;
int member_count = 0;
- Set<String> member_names;
+ HashSet<String> member_names;
+
while (true) { // variables list
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_DATATYPE | CF_PRECISION_MODIFIER;
+#endif // DEBUG_ENABLED
+
tk = _get_token();
if (tk.type == TK_CURLY_BRACKET_CLOSE) {
break;
}
StringName struct_name = "";
bool struct_dt = false;
- bool use_precision = false;
- DataPrecision precision = DataPrecision::PRECISION_DEFAULT;
+ DataPrecision precision = PRECISION_DEFAULT;
if (tk.type == TK_STRUCT) {
_set_error(RTR("Nested structs are not allowed."));
@@ -7609,8 +7850,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
- use_precision = true;
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+#endif // DEBUG_ENABLED
}
if (shader->structs.has(tk.text)) {
@@ -7621,10 +7864,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
#endif // DEBUG_ENABLED
struct_dt = true;
- if (use_precision) {
- _set_error(RTR("The precision modifier cannot be used on structs."));
- return ERR_PARSE_ERROR;
- }
}
if (!is_token_datatype(tk.type) && !struct_dt) {
@@ -7633,10 +7872,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type);
+ if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) {
+ return ERR_PARSE_ERROR;
+ }
+
if (type == TYPE_VOID || is_sampler_type(type)) {
_set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type)));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
bool first = true;
bool fixed_array_size = false;
@@ -7708,12 +7954,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error(RTR("Empty structs are not allowed."));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
_set_expected_error(";");
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
+
shader->structs[st.name] = st;
shader->vstructs.push_back(st); // struct's order is important!
#ifdef DEBUG_ENABLED
@@ -7723,6 +7976,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
#endif // DEBUG_ENABLED
} break;
case TK_GLOBAL: {
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
+ }
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type != TK_UNIFORM) {
_set_expected_after_error("uniform", "global");
@@ -7732,6 +7993,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
};
[[fallthrough]];
case TK_INSTANCE: {
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
+ }
+#endif // DEBUG_ENABLED
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
tk = _get_token();
if (tk.type != TK_UNIFORM) {
@@ -7744,16 +8013,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
[[fallthrough]];
case TK_UNIFORM:
case TK_VARYING: {
- bool uniform = tk.type == TK_UNIFORM;
-
- if (!uniform) {
+ bool is_uniform = tk.type == TK_UNIFORM;
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
+ if (!is_uniform) {
if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") {
_set_error(vformat(RTR("Varyings cannot be used in '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
}
-
- bool precision_defined = false;
DataPrecision precision = PRECISION_DEFAULT;
DataInterpolation interpolation = INTERPOLATION_SMOOTH;
DataType type;
@@ -7761,27 +8030,85 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int array_size = 0;
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ bool temp_error = false;
+ uint32_t datatype_flag;
+
+ if (!is_uniform) {
+ datatype_flag = CF_VARYING_TYPE;
+ keyword_completion_context = CF_INTERPOLATION_QUALIFIER | CF_PRECISION_MODIFIER | datatype_flag;
+
+ if (_lookup_next(next)) {
+ if (is_token_interpolation(next.type)) {
+ keyword_completion_context ^= (CF_INTERPOLATION_QUALIFIER | datatype_flag);
+ } else if (is_token_precision(next.type)) {
+ keyword_completion_context ^= (CF_PRECISION_MODIFIER | datatype_flag);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= datatype_flag;
+ }
+ }
+ } else {
+ datatype_flag = CF_UNIFORM_TYPE;
+ keyword_completion_context = CF_PRECISION_MODIFIER | datatype_flag;
+
+ if (_lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context ^= (CF_PRECISION_MODIFIER | datatype_flag);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= datatype_flag;
+ }
+ }
+ }
+#endif // DEBUG_ENABLED
+
if (is_token_interpolation(tk.type)) {
- if (uniform) {
+ if (is_uniform) {
_set_error(RTR("Interpolation qualifiers are not supported for uniforms."));
+#ifdef DEBUG_ENABLED
+ temp_error = true;
+#else
return ERR_PARSE_ERROR;
+#endif // DEBUG_ENABLED
}
interpolation = get_token_interpolation(tk.type);
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_INTERPOLATION_QUALIFIER) {
+ keyword_completion_context ^= CF_INTERPOLATION_QUALIFIER;
+ }
+ if (_lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= datatype_flag;
+ }
+ }
+ if (temp_error) {
+ return ERR_PARSE_ERROR;
+ }
+#endif // DEBUG_ENABLED
}
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
- precision_defined = true;
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_INTERPOLATION_QUALIFIER) {
+ keyword_completion_context ^= CF_INTERPOLATION_QUALIFIER;
+ }
+ if (keyword_completion_context & CF_PRECISION_MODIFIER) {
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+ }
+ if (_lookup_next(next)) {
+ if (is_token_datatype(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ }
+ }
+#endif // DEBUG_ENABLED
}
if (shader->structs.has(tk.text)) {
- if (uniform) {
- if (precision_defined) {
- _set_error(RTR("The precision modifier cannot be used on structs."));
- return ERR_PARSE_ERROR;
- }
+ if (is_uniform) {
_set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct"));
return ERR_PARSE_ERROR;
} else {
@@ -7797,16 +8124,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
type = get_token_datatype(tk.type);
+ if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) {
+ return ERR_PARSE_ERROR;
+ }
+
if (type == TYPE_VOID) {
_set_error(vformat(RTR("The '%s' data type is not allowed here."), "void"));
return ERR_PARSE_ERROR;
}
- if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
+ if (!is_uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
_set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed."));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
@@ -7840,7 +8174,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (uniform) {
+ if (is_uniform) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor.
//validate global uniform
DataType gvtype = global_var_get_type_func(name);
@@ -7854,16 +8188,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
}
- ShaderNode::Uniform uniform2;
+ ShaderNode::Uniform uniform;
- uniform2.type = type;
- uniform2.scope = uniform_scope;
- uniform2.precision = precision;
- uniform2.array_size = array_size;
+ uniform.type = type;
+ uniform.scope = uniform_scope;
+ uniform.precision = precision;
+ uniform.array_size = array_size;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_array_size(nullptr, constants, true, nullptr, &uniform2.array_size, nullptr);
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &uniform.array_size, nullptr);
if (error != OK) {
return error;
}
@@ -7875,36 +8209,33 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error(vformat(RTR("The '%s' qualifier is not supported for sampler types."), "SCOPE_INSTANCE"));
return ERR_PARSE_ERROR;
}
- uniform2.texture_order = texture_uniforms++;
- uniform2.texture_binding = texture_binding;
- if (uniform2.array_size > 0) {
- texture_binding += uniform2.array_size;
+ uniform.texture_order = texture_uniforms++;
+ uniform.texture_binding = texture_binding;
+ if (uniform.array_size > 0) {
+ texture_binding += uniform.array_size;
} else {
++texture_binding;
}
- uniform2.order = -1;
- if (_validate_datatype(type) != OK) {
- return ERR_PARSE_ERROR;
- }
+ uniform.order = -1;
} else {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) {
_set_error(vformat(RTR("The '%s' qualifier is not supported for matrix types."), "SCOPE_INSTANCE"));
return ERR_PARSE_ERROR;
}
- uniform2.texture_order = -1;
+ uniform.texture_order = -1;
if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) {
- uniform2.order = uniforms++;
+ uniform.order = uniforms++;
#ifdef DEBUG_ENABLED
if (check_device_limit_warnings) {
- if (uniform2.array_size > 0) {
- int size = get_datatype_size(uniform2.type) * uniform2.array_size;
- int m = (16 * uniform2.array_size);
+ if (uniform.array_size > 0) {
+ int size = get_datatype_size(uniform.type) * uniform.array_size;
+ int m = (16 * uniform.array_size);
if ((size % m) != 0U) {
size += m - (size % m);
}
uniform_buffer_size += size;
} else {
- uniform_buffer_size += get_datatype_size(uniform2.type);
+ uniform_buffer_size += get_datatype_size(uniform.type);
}
if (uniform_buffer_exceeded_line == -1 && uniform_buffer_size > max_uniform_buffer_size) {
@@ -7915,7 +8246,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
}
- if (uniform2.array_size > 0) {
+ if (uniform.array_size > 0) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
_set_error(vformat(RTR("The '%s' qualifier is not supported for uniform arrays."), "SCOPE_GLOBAL"));
return ERR_PARSE_ERROR;
@@ -7931,7 +8262,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_COLON) {
completion_type = COMPLETION_HINT;
completion_base = type;
- completion_base_array = uniform2.array_size > 0;
+ completion_base_array = uniform.array_size > 0;
//hint
do {
@@ -7943,179 +8274,251 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (uniform2.array_size > 0) {
- if (tk.type != TK_HINT_COLOR) {
+ if (uniform.array_size > 0) {
+ if (tk.type != TK_HINT_SOURCE_COLOR) {
_set_error(RTR("This hint is not supported for uniform arrays."));
return ERR_PARSE_ERROR;
}
}
- if (tk.type == TK_HINT_WHITE_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_WHITE;
- } else if (tk.type == TK_HINT_BLACK_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_BLACK;
- } else if (tk.type == TK_HINT_NORMAL_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_NORMAL;
- } else if (tk.type == TK_HINT_ROUGHNESS_NORMAL_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL;
- } else if (tk.type == TK_HINT_ROUGHNESS_R) {
- uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_R;
- } else if (tk.type == TK_HINT_ROUGHNESS_G) {
- uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_G;
- } else if (tk.type == TK_HINT_ROUGHNESS_B) {
- uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_B;
- } else if (tk.type == TK_HINT_ROUGHNESS_A) {
- uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A;
- } else if (tk.type == TK_HINT_ROUGHNESS_GRAY) {
- uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY;
- } else if (tk.type == TK_HINT_ANISOTROPY_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_ANISOTROPY;
- } else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO;
- } else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
- } else if (tk.type == TK_HINT_COLOR) {
- if (type != TYPE_VEC4) {
- _set_error(vformat(RTR("Color hint is for '%s' only."), "vec4"));
- return ERR_PARSE_ERROR;
- }
- uniform2.hint = ShaderNode::Uniform::HINT_COLOR;
- } else if (tk.type == TK_HINT_RANGE) {
- uniform2.hint = ShaderNode::Uniform::HINT_RANGE;
- if (type != TYPE_FLOAT && type != TYPE_INT) {
- _set_error(vformat(RTR("Range hint is for '%s' and '%s' only."), "float", "int"));
- return ERR_PARSE_ERROR;
- }
-
- tk = _get_token();
- if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_expected_after_error("(", "hint_range");
- return ERR_PARSE_ERROR;
- }
+ ShaderNode::Uniform::Hint new_hint = ShaderNode::Uniform::HINT_NONE;
+ TextureFilter new_filter = FILTER_DEFAULT;
+ TextureRepeat new_repeat = REPEAT_DEFAULT;
- tk = _get_token();
+ switch (tk.type) {
+ case TK_HINT_SOURCE_COLOR: {
+ if (type != TYPE_VEC3 && type != TYPE_VEC4 && !is_sampler_type(type)) {
+ _set_error(vformat(RTR("Source color hint is for '%s', '%s' or sampler types only."), "vec3", "vec4"));
+ return ERR_PARSE_ERROR;
+ }
- float sign = 1.0;
+ if (is_sampler_type(type)) {
+ if (uniform.use_color) {
+ _set_error(vformat(RTR("Duplicated hint: '%s'."), "source_color"));
+ return ERR_PARSE_ERROR;
+ }
+ uniform.use_color = true;
+ } else {
+ new_hint = ShaderNode::Uniform::HINT_SOURCE_COLOR;
+ }
+ } break;
+ case TK_HINT_DEFAULT_BLACK_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEFAULT_BLACK;
+ } break;
+ case TK_HINT_DEFAULT_WHITE_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE;
+ } break;
+ case TK_HINT_NORMAL_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_NORMAL;
+ } break;
+ case TK_HINT_ROUGHNESS_NORMAL_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL;
+ } break;
+ case TK_HINT_ROUGHNESS_R: {
+ new_hint = ShaderNode::Uniform::HINT_ROUGHNESS_R;
+ } break;
+ case TK_HINT_ROUGHNESS_G: {
+ new_hint = ShaderNode::Uniform::HINT_ROUGHNESS_G;
+ } break;
+ case TK_HINT_ROUGHNESS_B: {
+ new_hint = ShaderNode::Uniform::HINT_ROUGHNESS_B;
+ } break;
+ case TK_HINT_ROUGHNESS_A: {
+ new_hint = ShaderNode::Uniform::HINT_ROUGHNESS_A;
+ } break;
+ case TK_HINT_ROUGHNESS_GRAY: {
+ new_hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY;
+ } break;
+ case TK_HINT_ANISOTROPY_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_ANISOTROPY;
+ } break;
+ case TK_HINT_RANGE: {
+ if (type != TYPE_FLOAT && type != TYPE_INT) {
+ _set_error(vformat(RTR("Range hint is for '%s' and '%s' only."), "float", "int"));
+ return ERR_PARSE_ERROR;
+ }
- if (tk.type == TK_OP_SUB) {
- sign = -1.0;
tk = _get_token();
- }
-
- if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
- _set_error(RTR("Expected an integer constant."));
- return ERR_PARSE_ERROR;
- }
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_expected_after_error("(", "hint_range");
+ return ERR_PARSE_ERROR;
+ }
- uniform2.hint_range[0] = tk.constant;
- uniform2.hint_range[0] *= sign;
+ tk = _get_token();
- tk = _get_token();
+ float sign = 1.0;
- if (tk.type != TK_COMMA) {
- _set_error(RTR("Expected ',' after integer constant."));
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_OP_SUB) {
+ sign = -1.0;
+ tk = _get_token();
+ }
- tk = _get_token();
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant."));
+ return ERR_PARSE_ERROR;
+ }
- sign = 1.0;
+ uniform.hint_range[0] = tk.constant;
+ uniform.hint_range[0] *= sign;
- if (tk.type == TK_OP_SUB) {
- sign = -1.0;
tk = _get_token();
- }
- if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
- _set_error(RTR("Expected an integer constant after ','."));
- return ERR_PARSE_ERROR;
- }
+ if (tk.type != TK_COMMA) {
+ _set_error(RTR("Expected ',' after integer constant."));
+ return ERR_PARSE_ERROR;
+ }
- uniform2.hint_range[1] = tk.constant;
- uniform2.hint_range[1] *= sign;
+ tk = _get_token();
- tk = _get_token();
+ sign = 1.0;
- if (tk.type == TK_COMMA) {
- tk = _get_token();
+ if (tk.type == TK_OP_SUB) {
+ sign = -1.0;
+ tk = _get_token();
+ }
if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
_set_error(RTR("Expected an integer constant after ','."));
return ERR_PARSE_ERROR;
}
- uniform2.hint_range[2] = tk.constant;
+ uniform.hint_range[1] = tk.constant;
+ uniform.hint_range[1] *= sign;
+
tk = _get_token();
- } else {
- if (type == TYPE_INT) {
- uniform2.hint_range[2] = 1;
+
+ if (tk.type == TK_COMMA) {
+ tk = _get_token();
+
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant after ','."));
+ return ERR_PARSE_ERROR;
+ }
+
+ uniform.hint_range[2] = tk.constant;
+ tk = _get_token();
} else {
- uniform2.hint_range[2] = 0.001;
+ if (type == TYPE_INT) {
+ uniform.hint_range[2] = 1;
+ } else {
+ uniform.hint_range[2] = 0.001;
+ }
}
- }
- if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_expected_error(")");
- return ERR_PARSE_ERROR;
- }
- } else if (tk.type == TK_HINT_INSTANCE_INDEX) {
- if (custom_instance_index != -1) {
- _set_error(vformat(RTR("Can only specify '%s' once."), "instance_index"));
- return ERR_PARSE_ERROR;
- }
+ if (tk.type != TK_PARENTHESIS_CLOSE) {
+ _set_expected_error(")");
+ return ERR_PARSE_ERROR;
+ }
- tk = _get_token();
- if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_expected_after_error("(", "instance_index");
- return ERR_PARSE_ERROR;
- }
+ new_hint = ShaderNode::Uniform::HINT_RANGE;
+ } break;
+ case TK_HINT_INSTANCE_INDEX: {
+ if (custom_instance_index != -1) {
+ _set_error(vformat(RTR("Can only specify '%s' once."), "instance_index"));
+ return ERR_PARSE_ERROR;
+ }
- tk = _get_token();
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_expected_after_error("(", "instance_index");
+ return ERR_PARSE_ERROR;
+ }
- if (tk.type == TK_OP_SUB) {
- _set_error(RTR("The instance index can't be negative."));
- return ERR_PARSE_ERROR;
- }
+ tk = _get_token();
- if (!tk.is_integer_constant()) {
- _set_error(RTR("Expected an integer constant."));
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_OP_SUB) {
+ _set_error(RTR("The instance index can't be negative."));
+ return ERR_PARSE_ERROR;
+ }
- custom_instance_index = tk.constant;
+ if (!tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant."));
+ return ERR_PARSE_ERROR;
+ }
+
+ custom_instance_index = tk.constant;
+
+ if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) {
+ _set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1));
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ if (tk.type != TK_PARENTHESIS_CLOSE) {
+ _set_expected_error(")");
+ return ERR_PARSE_ERROR;
+ }
+ } break;
+ case TK_FILTER_NEAREST: {
+ new_filter = FILTER_NEAREST;
+ } break;
+ case TK_FILTER_LINEAR: {
+ new_filter = FILTER_LINEAR;
+ } break;
+ case TK_FILTER_NEAREST_MIPMAP: {
+ new_filter = FILTER_NEAREST_MIPMAP;
+ } break;
+ case TK_FILTER_LINEAR_MIPMAP: {
+ new_filter = FILTER_LINEAR_MIPMAP;
+ } break;
+ case TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC: {
+ new_filter = FILTER_NEAREST_MIPMAP_ANISOTROPIC;
+ } break;
+ case TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC: {
+ new_filter = FILTER_LINEAR_MIPMAP_ANISOTROPIC;
+ } break;
+ case TK_REPEAT_DISABLE: {
+ new_repeat = REPEAT_DISABLE;
+ } break;
+ case TK_REPEAT_ENABLE: {
+ new_repeat = REPEAT_ENABLE;
+ } break;
+ default:
+ break;
+ }
+ if (((new_filter != FILTER_DEFAULT || new_repeat != REPEAT_DEFAULT) || (new_hint != ShaderNode::Uniform::HINT_NONE && new_hint != ShaderNode::Uniform::HINT_SOURCE_COLOR && new_hint != ShaderNode::Uniform::HINT_RANGE)) && !is_sampler_type(type)) {
+ _set_error(RTR("This hint is only for sampler types."));
+ return ERR_PARSE_ERROR;
+ }
- if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) {
- _set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1));
+ if (new_hint != ShaderNode::Uniform::HINT_NONE) {
+ if (uniform.hint != ShaderNode::Uniform::HINT_NONE) {
+ if (uniform.hint == new_hint) {
+ _set_error(vformat(RTR("Duplicated hint: '%s'."), get_uniform_hint_name(new_hint)));
+ } else {
+ _set_error(vformat(RTR("Redefinition of hint: '%s'. The hint has already been set to '%s'."), get_uniform_hint_name(new_hint), get_uniform_hint_name(uniform.hint)));
+ }
return ERR_PARSE_ERROR;
+ } else {
+ uniform.hint = new_hint;
}
+ }
- tk = _get_token();
-
- if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_expected_error(")");
+ if (new_filter != FILTER_DEFAULT) {
+ if (uniform.filter != FILTER_DEFAULT) {
+ if (uniform.filter == new_filter) {
+ _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter)));
+ } else {
+ _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
+ }
return ERR_PARSE_ERROR;
+ } else {
+ uniform.filter = new_filter;
}
- } else if (tk.type == TK_FILTER_LINEAR) {
- uniform2.filter = FILTER_LINEAR;
- } else if (tk.type == TK_FILTER_NEAREST) {
- uniform2.filter = FILTER_NEAREST;
- } else if (tk.type == TK_FILTER_NEAREST_MIPMAP) {
- uniform2.filter = FILTER_NEAREST_MIPMAP;
- } else if (tk.type == TK_FILTER_LINEAR_MIPMAP) {
- uniform2.filter = FILTER_LINEAR_MIPMAP;
- } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC) {
- uniform2.filter = FILTER_NEAREST_MIPMAP_ANISOTROPIC;
- } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC) {
- uniform2.filter = FILTER_LINEAR_MIPMAP_ANISOTROPIC;
- } else if (tk.type == TK_REPEAT_DISABLE) {
- uniform2.repeat = REPEAT_DISABLE;
- } else if (tk.type == TK_REPEAT_ENABLE) {
- uniform2.repeat = REPEAT_ENABLE;
}
- if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
- _set_error(RTR("This hint is only for sampler types."));
- return ERR_PARSE_ERROR;
+ if (new_repeat != REPEAT_DEFAULT) {
+ if (uniform.repeat != REPEAT_DEFAULT) {
+ if (uniform.repeat == new_repeat) {
+ _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat)));
+ } else {
+ _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
+ }
+ return ERR_PARSE_ERROR;
+ } else {
+ uniform.repeat = new_repeat;
+ }
}
tk = _get_token();
@@ -8125,9 +8528,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
if (custom_instance_index >= 0) {
- uniform2.instance_index = custom_instance_index;
+ uniform.instance_index = custom_instance_index;
} else {
- uniform2.instance_index = instance_index++;
+ uniform.instance_index = instance_index++;
if (instance_index > MAX_INSTANCE_UNIFORM_INDICES) {
_set_error(vformat(RTR("Too many '%s' uniforms in shader, maximum supported is %d."), "instance", MAX_INSTANCE_UNIFORM_INDICES));
return ERR_PARSE_ERROR;
@@ -8138,7 +8541,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//reset scope for next uniform
if (tk.type == TK_OP_ASSIGN) {
- if (uniform2.array_size > 0) {
+ if (uniform.array_size > 0) {
_set_error(RTR("Setting default values to uniform arrays is not supported."));
return ERR_PARSE_ERROR;
}
@@ -8154,16 +8557,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ConstantNode *cn = static_cast<ConstantNode *>(expr);
- uniform2.default_value.resize(cn->values.size());
+ uniform.default_value.resize(cn->values.size());
- if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) {
- _set_error(vformat(RTR("Can't convert constant to '%s'."), get_datatype_name(uniform2.type)));
+ if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) {
+ _set_error(vformat(RTR("Can't convert constant to '%s'."), get_datatype_name(uniform.type)));
return ERR_PARSE_ERROR;
}
tk = _get_token();
}
- shader->uniforms[name] = uniform2;
+ shader->uniforms[name] = uniform;
#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_UNIFORM_FLAG)) {
used_uniforms.insert(name, Usage(tk_line));
@@ -8178,6 +8581,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
completion_type = COMPLETION_NONE;
} else { // varying
ShaderNode::Varying varying;
@@ -8240,13 +8646,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (shader->structs.has(tk.text)) {
- if (precision != PRECISION_DEFAULT) {
- _set_error(RTR("The precision modifier cannot be used on structs."));
- return ERR_PARSE_ERROR;
- }
is_struct = true;
struct_name = tk.text;
} else {
+#ifdef DEBUG_ENABLED
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context = CF_UNIFORM_QUALIFIER;
+ }
+ }
+#endif // DEBUG_ENABLED
if (!is_token_datatype(tk.type)) {
_set_error(RTR("Expected constant, function, uniform or varying."));
return ERR_PARSE_ERROR;
@@ -8267,17 +8676,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
type = get_token_datatype(tk.type);
}
+
+ if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) {
+ return ERR_PARSE_ERROR;
+ }
+
prev_pos = _get_tkpos();
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
+
bool unknown_size = false;
bool fixed_array_size = false;
if (tk.type == TK_BRACKET_OPEN) {
- if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Global constant arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
Error error = _parse_array_size(nullptr, constants, !is_constant, nullptr, &array_size, &unknown_size);
if (error != OK) {
return error;
@@ -8322,10 +8736,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.array_size = array_size;
if (tk.type == TK_BRACKET_OPEN) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Global const arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size);
if (error != OK) {
return error;
@@ -8455,7 +8865,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ if (n->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(n)->op == OP_CALL) {
_set_error(RTR("Expected constant expression."));
return ERR_PARSE_ERROR;
}
@@ -8506,13 +8916,24 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
} else {
+#ifdef DEBUG_ENABLED
+ if (constant.type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BOOLEAN;
+ }
+#endif // DEBUG_ENABLED
+
//variable created with assignment! must parse an expression
Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
- if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) {
- OperatorNode *op = ((OperatorNode *)expr);
+#ifdef DEBUG_ENABLED
+ if (constant.type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_GLOBAL_SPACE;
+ }
+#endif // DEBUG_ENABLED
+ if (expr->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) {
+ OperatorNode *op = static_cast<OperatorNode *>(expr);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
_set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1));
@@ -8642,45 +9063,116 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_PARENTHESIS_CLOSE) {
break;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_CONST_KEYWORD | CF_FUNC_DECL_PARAM_SPEC | CF_PRECISION_MODIFIER | CF_FUNC_DECL_PARAM_TYPE; // eg. const in mediump float
+
+ if (_lookup_next(next)) {
+ if (next.type == TK_CONST) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ } else if (is_token_arg_qual(next.type)) {
+ keyword_completion_context = CF_CONST_KEYWORD;
+ } else if (is_token_precision(next.type)) {
+ keyword_completion_context = (CF_CONST_KEYWORD | CF_FUNC_DECL_PARAM_SPEC | CF_FUNC_DECL_PARAM_TYPE);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context = (CF_CONST_KEYWORD | CF_FUNC_DECL_PARAM_SPEC | CF_PRECISION_MODIFIER);
+ }
+ }
+#endif // DEBUG_ENABLED
- bool is_const = false;
+ bool param_is_const = false;
if (tk.type == TK_CONST) {
- is_const = true;
+ param_is_const = true;
tk = _get_token();
- }
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_CONST_KEYWORD) {
+ keyword_completion_context ^= CF_CONST_KEYWORD;
+ }
- ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN;
+ if (_lookup_next(next)) {
+ if (is_token_arg_qual(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ } else if (is_token_precision(next.type)) {
+ keyword_completion_context = (CF_FUNC_DECL_PARAM_SPEC | CF_FUNC_DECL_PARAM_TYPE);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context = (CF_FUNC_DECL_PARAM_SPEC | CF_PRECISION_MODIFIER);
+ }
+ }
+#endif // DEBUG_ENABLED
+ }
- if (tk.type == TK_ARG_IN) {
- qualifier = ARGUMENT_QUALIFIER_IN;
- tk = _get_token();
- } else if (tk.type == TK_ARG_OUT) {
- if (is_const) {
- _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const"));
- return ERR_PARSE_ERROR;
+ ArgumentQualifier param_qualifier = ARGUMENT_QUALIFIER_IN;
+ if (is_token_arg_qual(tk.type)) {
+ bool error = false;
+ switch (tk.type) {
+ case TK_ARG_IN: {
+ param_qualifier = ARGUMENT_QUALIFIER_IN;
+ } break;
+ case TK_ARG_OUT: {
+ if (param_is_const) {
+ _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const"));
+ error = true;
+ }
+ param_qualifier = ARGUMENT_QUALIFIER_OUT;
+ } break;
+ case TK_ARG_INOUT: {
+ if (param_is_const) {
+ _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const"));
+ error = true;
+ }
+ param_qualifier = ARGUMENT_QUALIFIER_INOUT;
+ } break;
+ default:
+ error = true;
+ break;
}
- qualifier = ARGUMENT_QUALIFIER_OUT;
tk = _get_token();
- } else if (tk.type == TK_ARG_INOUT) {
- if (is_const) {
- _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const"));
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_CONST_KEYWORD) {
+ keyword_completion_context ^= CF_CONST_KEYWORD;
+ }
+ if (keyword_completion_context & CF_FUNC_DECL_PARAM_SPEC) {
+ keyword_completion_context ^= CF_FUNC_DECL_PARAM_SPEC;
+ }
+
+ if (_lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context = CF_FUNC_DECL_PARAM_TYPE;
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context = CF_PRECISION_MODIFIER;
+ }
+ }
+#endif // DEBUG_ENABLED
+ if (error) {
return ERR_PARSE_ERROR;
}
- qualifier = ARGUMENT_QUALIFIER_INOUT;
- tk = _get_token();
}
- DataType ptype;
- StringName pname;
+ DataType param_type;
+ StringName param_name;
StringName param_struct_name;
- DataPrecision pprecision = PRECISION_DEFAULT;
- bool use_precision = false;
+ DataPrecision param_precision = PRECISION_DEFAULT;
int arg_array_size = 0;
if (is_token_precision(tk.type)) {
- pprecision = get_token_precision(tk.type);
+ param_precision = get_token_precision(tk.type);
tk = _get_token();
- use_precision = true;
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_CONST_KEYWORD) {
+ keyword_completion_context ^= CF_CONST_KEYWORD;
+ }
+ if (keyword_completion_context & CF_FUNC_DECL_PARAM_SPEC) {
+ keyword_completion_context ^= CF_FUNC_DECL_PARAM_SPEC;
+ }
+ if (keyword_completion_context & CF_PRECISION_MODIFIER) {
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+ }
+
+ if (_lookup_next(next)) {
+ if (is_token_datatype(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ }
+ }
+#endif // DEBUG_ENABLED
}
is_struct = false;
@@ -8693,10 +9185,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
used_structs[param_struct_name].used = true;
}
#endif // DEBUG_ENABLED
- if (use_precision) {
- _set_error(RTR("The precision modifier cannot be used on structs."));
- return ERR_PARSE_ERROR;
- }
}
if (!is_struct && !is_token_datatype(tk.type)) {
@@ -8704,7 +9192,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) {
+ if (param_qualifier == ARGUMENT_QUALIFIER_OUT || param_qualifier == ARGUMENT_QUALIFIER_INOUT) {
if (is_sampler_type(get_token_datatype(tk.type))) {
_set_error(RTR("Opaque types cannot be output parameters."));
return ERR_PARSE_ERROR;
@@ -8712,18 +9200,21 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (is_struct) {
- ptype = TYPE_STRUCT;
+ param_type = TYPE_STRUCT;
} else {
- ptype = get_token_datatype(tk.type);
- if (_validate_datatype(ptype) != OK) {
- return ERR_PARSE_ERROR;
- }
- if (ptype == TYPE_VOID) {
+ param_type = get_token_datatype(tk.type);
+ if (param_type == TYPE_VOID) {
_set_error(RTR("Void type not allowed as argument."));
return ERR_PARSE_ERROR;
}
}
+ if (param_precision != PRECISION_DEFAULT && _validate_precision(param_type, param_precision) != OK) {
+ return ERR_PARSE_ERROR;
+ }
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -8738,32 +9229,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- pname = tk.text;
+ param_name = tk.text;
ShaderLanguage::IdentifierType itype;
- if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) {
+ if (_find_identifier(func_node->body, false, builtins, param_name, (ShaderLanguage::DataType *)nullptr, &itype)) {
if (itype != IDENTIFIER_FUNCTION) {
- _set_redefinition_error(String(pname));
+ _set_redefinition_error(String(param_name));
return ERR_PARSE_ERROR;
}
}
- if (has_builtin(p_functions, pname)) {
- _set_redefinition_error(String(pname));
+ if (has_builtin(p_functions, param_name)) {
+ _set_redefinition_error(String(param_name));
return ERR_PARSE_ERROR;
}
FunctionNode::Argument arg;
- arg.type = ptype;
- arg.name = pname;
+ arg.type = param_type;
+ arg.name = param_name;
arg.type_str = param_struct_name;
- arg.precision = pprecision;
- arg.qualifier = qualifier;
+ arg.precision = param_precision;
+ arg.qualifier = param_qualifier;
arg.tex_argument_check = false;
arg.tex_builtin_check = false;
arg.tex_argument_filter = FILTER_DEFAULT;
arg.tex_argument_repeat = REPEAT_DEFAULT;
- arg.is_const = is_const;
+ arg.is_const = param_is_const;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -8807,11 +9298,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
current_function = name;
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
Error err = _parse_block(func_node->body, builtins);
if (err) {
return err;
}
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
if (func_node->return_type != DataType::TYPE_VOID) {
BlockNode *block = func_node->body;
if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
@@ -8834,7 +9330,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return OK;
}
-bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) {
+bool ShaderLanguage::has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) {
for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : p_functions) {
if (E.value.built_ins.has(p_name)) {
return true;
@@ -8849,7 +9345,7 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper
for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) {
- BlockNode *last_block = (BlockNode *)p_flow->blocks[i];
+ BlockNode *last_block = static_cast<BlockNode *>(p_flow->blocks[i]);
if (_find_last_flow_op_in_block(last_block, p_op) == OK) {
found = true;
break;
@@ -8867,7 +9363,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
for (int i = p_block->statements.size() - 1; i >= 0; i--) {
if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
- ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i];
+ ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]);
if (flow->flow_op == p_op) {
found = true;
break;
@@ -8878,7 +9374,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
}
}
} else if (p_block->statements[i]->type == Node::TYPE_BLOCK) {
- BlockNode *block = (BlockNode *)p_block->statements[i];
+ BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]);
if (_find_last_flow_op_in_block(block, p_op) == OK) {
found = true;
break;
@@ -8976,19 +9472,19 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
#ifdef DEBUG_ENABLED
void ShaderLanguage::_check_warning_accums() {
- for (const KeyValue<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> &E : warnings_check_map2) {
- for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E.value).front(); T; T = T->next()) {
- for (const KeyValue<StringName, Usage> &U : T->get()) {
+ for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) {
+ for (const KeyValue<StringName, HashMap<StringName, Usage>> &T : *E.value) {
+ for (const KeyValue<StringName, Usage> &U : T.value) {
if (!U.value.used) {
_add_warning(E.key, U.value.decl_line, U.key);
}
}
}
}
- for (const KeyValue<ShaderWarning::Code, Map<StringName, Usage> *> &E : warnings_check_map) {
- for (const Map<StringName, Usage>::Element *U = (*E.value).front(); U; U = U->next()) {
- if (!U->get().used) {
- _add_warning(E.key, U->get().decl_line, U->key());
+ for (const KeyValue<ShaderWarning::Code, HashMap<StringName, Usage> *> &E : warnings_check_map) {
+ for (const KeyValue<StringName, Usage> &U : (*E.value)) {
+ if (!U.value.used) {
+ _add_warning(E.key, U.value.decl_line, U.key);
}
}
}
@@ -9034,7 +9530,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
+Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) {
clear();
code = p_code;
@@ -9046,6 +9542,28 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
shader = alloc_node<ShaderNode>();
_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
+#ifdef DEBUG_ENABLED
+ // Adds context keywords.
+ if (keyword_completion_context != CF_UNSPECIFIED) {
+ int sz = sizeof(keyword_list) / sizeof(KeyWord);
+ for (int i = 0; i < sz; i++) {
+ if (keyword_list[i].flags == CF_UNSPECIFIED) {
+ break; // Ignore hint keywords (parsed below).
+ }
+ if (keyword_list[i].flags & keyword_completion_context) {
+ if (keyword_list[i].excluded_shader_types.has(shader_type_identifier)) {
+ continue;
+ }
+ if (!keyword_list[i].functions.is_empty() && !keyword_list[i].functions.has(current_function)) {
+ continue;
+ }
+ ScriptLanguage::CodeCompletionOption option(keyword_list[i].text, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ }
+#endif // DEBUG_ENABLED
+
switch (completion_type) {
case COMPLETION_NONE: {
//do nothing
@@ -9053,7 +9571,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
} break;
case COMPLETION_SHADER_TYPE: {
for (const String &shader_type : p_info.shader_types) {
- ScriptCodeCompletionOption option(shader_type, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ ScriptLanguage::CodeCompletionOption option(shader_type, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
r_options->push_back(option);
}
return OK;
@@ -9073,7 +9591,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (!found) {
for (int j = 0; j < info.options.size(); j++) {
- ScriptCodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
r_options->push_back(option);
}
}
@@ -9081,7 +9599,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
const String name = String(info.name);
if (!shader->render_modes.has(name)) {
- ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
r_options->push_back(option);
}
}
@@ -9093,7 +9611,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (shader->structs.has(completion_struct)) {
StructNode *node = shader->structs[completion_struct].shader_struct;
for (int i = 0; i < node->members.size(); i++) {
- ScriptCodeCompletionOption option(node->members[i]->name, ScriptCodeCompletionOption::KIND_MEMBER);
+ ScriptLanguage::CodeCompletionOption option(node->members[i]->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
r_options->push_back(option);
}
}
@@ -9115,7 +9633,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (found) {
continue;
}
- ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION);
+ ScriptLanguage::CodeCompletionOption option(E.key, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
r_options->push_back(option);
}
@@ -9124,7 +9642,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
case COMPLETION_IDENTIFIER:
case COMPLETION_FUNCTION_CALL: {
bool comp_ident = completion_type == COMPLETION_IDENTIFIER;
- Map<String, ScriptCodeCompletionOption::Kind> matches;
+ HashMap<String, ScriptLanguage::CodeCompletionKind> matches;
StringName skip_function;
BlockNode *block = completion_block;
@@ -9133,7 +9651,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (comp_ident) {
for (const KeyValue<StringName, BlockNode::Variable> &E : block->variables) {
if (E.value.line < completion_line) {
- matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
+ matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE);
}
}
}
@@ -9141,7 +9659,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (block->parent_function) {
if (comp_ident) {
for (int i = 0; i < block->parent_function->arguments.size(); i++) {
- matches.insert(block->parent_function->arguments[i].name, ScriptCodeCompletionOption::KIND_VARIABLE);
+ matches.insert(block->parent_function->arguments[i].name, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE);
}
}
skip_function = block->parent_function->name;
@@ -9152,9 +9670,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (comp_ident) {
if (p_info.functions.has("global")) {
for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
- ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
if (E.value.constant) {
- kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
}
matches.insert(E.key, kind);
}
@@ -9162,9 +9680,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (p_info.functions.has("constants")) {
for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
- ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
if (E.value.constant) {
- kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
}
matches.insert(E.key, kind);
}
@@ -9172,22 +9690,22 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (skip_function != StringName() && p_info.functions.has(skip_function)) {
for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
- ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
if (E.value.constant) {
- kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
}
matches.insert(E.key, kind);
}
}
for (const KeyValue<StringName, ShaderNode::Constant> &E : shader->constants) {
- matches.insert(E.key, ScriptCodeCompletionOption::KIND_CONSTANT);
+ matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
}
for (const KeyValue<StringName, ShaderNode::Varying> &E : shader->varyings) {
- matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
+ matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE);
}
for (const KeyValue<StringName, ShaderNode::Uniform> &E : shader->uniforms) {
- matches.insert(E.key, ScriptCodeCompletionOption::KIND_MEMBER);
+ matches.insert(E.key, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
}
}
@@ -9195,7 +9713,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (!shader->functions[i].callable || shader->functions[i].name == skip_function) {
continue;
}
- matches.insert(String(shader->functions[i].name), ScriptCodeCompletionOption::KIND_FUNCTION);
+ matches.insert(String(shader->functions[i].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
}
int idx = 0;
@@ -9203,7 +9721,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (stages && stages->has(skip_function)) {
for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) {
- matches.insert(String(E.key), ScriptCodeCompletionOption::KIND_FUNCTION);
+ matches.insert(String(E.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
}
}
@@ -9212,7 +9730,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
idx++;
continue;
}
- matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION);
+ matches.insert(String(builtin_func_defs[idx].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
idx++;
}
@@ -9226,15 +9744,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
continue;
}
if (builtin_func_defs[idx].tag == completion_class) {
- matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION);
+ matches.insert(String(builtin_func_defs[idx].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
}
idx++;
}
}
- for (const KeyValue<String, ScriptCodeCompletionOption::Kind> &E : matches) {
- ScriptCodeCompletionOption option(E.key, E.value);
- if (E.value == ScriptCodeCompletionOption::KIND_FUNCTION) {
+ for (const KeyValue<String, ScriptLanguage::CodeCompletionKind> &E : matches) {
+ ScriptLanguage::CodeCompletionOption option(E.key, E.value);
+ if (E.value == ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION) {
option.insert_text += "(";
}
r_options->push_back(option);
@@ -9371,7 +9889,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
}
int idx2 = 0;
- Set<int> out_args;
+ HashSet<int> out_args;
while (builtin_func_out_args[idx2].name != nullptr) {
if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) {
for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) {
@@ -9483,18 +10001,18 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
}
for (int i = 0; i < limit; i++) {
- r_options->push_back(ScriptCodeCompletionOption(String::chr(colv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT));
- r_options->push_back(ScriptCodeCompletionOption(String::chr(coordv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT));
- r_options->push_back(ScriptCodeCompletionOption(String::chr(coordt[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT));
+ r_options->push_back(ScriptLanguage::CodeCompletionOption(String::chr(colv[i]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT));
+ r_options->push_back(ScriptLanguage::CodeCompletionOption(String::chr(coordv[i]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT));
+ r_options->push_back(ScriptLanguage::CodeCompletionOption(String::chr(coordt[i]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT));
}
} break;
case COMPLETION_HINT: {
- if (completion_base == DataType::TYPE_VEC4) {
- ScriptCodeCompletionOption option("hint_color", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ if (completion_base == DataType::TYPE_VEC3 || completion_base == DataType::TYPE_VEC4) {
+ ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
r_options->push_back(option);
} else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) {
- ScriptCodeCompletionOption option("hint_range", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
if (completion_base == DataType::TYPE_INT) {
option.insert_text = "hint_range(0, 100, 1)";
@@ -9513,10 +10031,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("filter_nearest");
options.push_back("filter_nearest_mipmap");
options.push_back("filter_nearest_mipmap_anisotropic");
- options.push_back("hint_albedo");
options.push_back("hint_anisotropy");
- options.push_back("hint_black");
- options.push_back("hint_black_albedo");
+ options.push_back("hint_default_black");
+ options.push_back("hint_default_white");
options.push_back("hint_normal");
options.push_back("hint_roughness_a");
options.push_back("hint_roughness_b");
@@ -9524,18 +10041,18 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_roughness_gray");
options.push_back("hint_roughness_normal");
options.push_back("hint_roughness_r");
- options.push_back("hint_white");
+ options.push_back("source_color");
options.push_back("repeat_enable");
options.push_back("repeat_disable");
}
for (int i = 0; i < options.size(); i++) {
- ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ ScriptLanguage::CodeCompletionOption option(options[i], ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
r_options->push_back(option);
}
}
if (!completion_base_array) {
- ScriptCodeCompletionOption option("instance_index", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ ScriptLanguage::CodeCompletionOption option("instance_index", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
option.insert_text = "instance_index(0)";
r_options->push_back(option);
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index f39b21621d..2b147fbeb1 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -35,7 +35,7 @@
#include "core/string/string_name.h"
#include "core/string/ustring.h"
#include "core/templates/list.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/typedefs.h"
#include "core/variant/variant.h"
@@ -160,8 +160,8 @@ public:
TK_ARG_OUT,
TK_ARG_INOUT,
TK_RENDER_MODE,
- TK_HINT_WHITE_TEXTURE,
- TK_HINT_BLACK_TEXTURE,
+ TK_HINT_DEFAULT_WHITE_TEXTURE,
+ TK_HINT_DEFAULT_BLACK_TEXTURE,
TK_HINT_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_R,
@@ -170,9 +170,7 @@ public:
TK_HINT_ROUGHNESS_A,
TK_HINT_ROUGHNESS_GRAY,
TK_HINT_ANISOTROPY_TEXTURE,
- TK_HINT_ALBEDO_TEXTURE,
- TK_HINT_BLACK_ALBEDO_TEXTURE,
- TK_HINT_COLOR,
+ TK_HINT_SOURCE_COLOR,
TK_HINT_RANGE,
TK_HINT_INSTANCE_INDEX,
TK_FILTER_NEAREST,
@@ -386,7 +384,7 @@ public:
return node;
}
- Node *nodes;
+ Node *nodes = nullptr;
struct OperatorNode : public Node {
DataType return_cache = TYPE_VOID;
@@ -451,8 +449,8 @@ public:
int array_size = 0;
bool is_local = false;
- virtual DataType get_datatype() const override { return datatype_cache; }
- virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual DataType get_datatype() const override { return call_expression ? call_expression->get_datatype() : datatype_cache; }
+ virtual String get_datatype_name() const override { return call_expression ? call_expression->get_datatype_name() : String(struct_name); }
virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr; }
@@ -503,7 +501,7 @@ public:
BlockNode *parent_block = nullptr;
enum BlockType {
- BLOCK_TYPE_STANDART,
+ BLOCK_TYPE_STANDARD,
BLOCK_TYPE_FOR_INIT,
BLOCK_TYPE_FOR_CONDITION,
BLOCK_TYPE_FOR_EXPRESSION,
@@ -512,7 +510,7 @@ public:
BLOCK_TYPE_DEFAULT,
};
- int block_type = BLOCK_TYPE_STANDART;
+ int block_type = BLOCK_TYPE_STANDARD;
SubClassTag block_tag = SubClassTag::TAG_GLOBAL;
struct Variable {
@@ -525,7 +523,7 @@ public:
ConstantNode::Value value;
};
- Map<StringName, Variable> variables;
+ HashMap<StringName, Variable> variables;
List<Node *> statements;
bool single_statement = false;
bool use_comma_between_statements = false;
@@ -558,8 +556,8 @@ public:
Node *call_expression = nullptr;
bool has_swizzling_duplicates = false;
- virtual DataType get_datatype() const override { return datatype; }
- virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual DataType get_datatype() const override { return call_expression ? call_expression->get_datatype() : datatype; }
+ virtual String get_datatype_name() const override { return call_expression ? call_expression->get_datatype_name() : String(struct_name); }
virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
@@ -589,7 +587,7 @@ public:
bool is_const;
int array_size;
- Map<StringName, Set<int>> tex_argument_connect;
+ HashMap<StringName, HashSet<int>> tex_argument_connect;
};
StringName name;
@@ -615,20 +613,20 @@ public:
DataType type;
StringName type_str;
DataPrecision precision;
- ConstantNode *initializer;
+ ConstantNode *initializer = nullptr;
int array_size;
};
struct Function {
StringName name;
- FunctionNode *function;
- Set<StringName> uses_function;
+ FunctionNode *function = nullptr;
+ HashSet<StringName> uses_function;
bool callable;
};
struct Struct {
StringName name;
- StructNode *shader_struct;
+ StructNode *shader_struct = nullptr;
};
struct Varying {
@@ -653,10 +651,8 @@ public:
struct Uniform {
enum Hint {
HINT_NONE,
- HINT_COLOR,
HINT_RANGE,
- HINT_ALBEDO,
- HINT_BLACK_ALBEDO,
+ HINT_SOURCE_COLOR,
HINT_NORMAL,
HINT_ROUGHNESS_NORMAL,
HINT_ROUGHNESS_R,
@@ -664,8 +660,8 @@ public:
HINT_ROUGHNESS_B,
HINT_ROUGHNESS_A,
HINT_ROUGHNESS_GRAY,
- HINT_BLACK,
- HINT_WHITE,
+ HINT_DEFAULT_BLACK,
+ HINT_DEFAULT_WHITE,
HINT_ANISOTROPY,
HINT_MAX
};
@@ -685,6 +681,7 @@ public:
Vector<ConstantNode::Value> default_value;
Scope scope = SCOPE_LOCAL;
Hint hint = HINT_NONE;
+ bool use_color = false;
TextureFilter filter = FILTER_DEFAULT;
TextureRepeat repeat = REPEAT_DEFAULT;
float hint_range[3];
@@ -697,10 +694,10 @@ public:
}
};
- Map<StringName, Constant> constants;
- Map<StringName, Varying> varyings;
- Map<StringName, Uniform> uniforms;
- Map<StringName, Struct> structs;
+ HashMap<StringName, Constant> constants;
+ HashMap<StringName, Varying> varyings;
+ HashMap<StringName, Uniform> uniforms;
+ HashMap<StringName, Struct> structs;
Vector<StringName> render_modes;
Vector<Function> functions;
@@ -715,7 +712,7 @@ public:
bool is_op;
union {
Operator op;
- Node *node;
+ Node *node = nullptr;
};
};
@@ -756,9 +753,13 @@ public:
static bool is_token_interpolation(TokenType p_type);
static DataInterpolation get_token_interpolation(TokenType p_type);
static bool is_token_precision(TokenType p_type);
+ static bool is_token_arg_qual(TokenType p_type);
static DataPrecision get_token_precision(TokenType p_type);
static String get_precision_name(DataPrecision p_type);
static String get_datatype_name(DataType p_type);
+ static String get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint);
+ static String get_texture_filter_name(TextureFilter p_filter);
+ static String get_texture_repeat_name(TextureRepeat p_repeat);
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);
static bool is_token_operator_assign(TokenType p_type);
@@ -856,13 +857,13 @@ public:
};
struct FunctionInfo {
- Map<StringName, BuiltInInfo> built_ins;
- Map<StringName, StageFunctionInfo> stage_functions;
+ HashMap<StringName, BuiltInInfo> built_ins;
+ HashMap<StringName, StageFunctionInfo> stage_functions;
bool can_discard = false;
bool main_function = false;
};
- static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
+ static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
@@ -870,15 +871,18 @@ private:
struct KeyWord {
TokenType token;
const char *text;
+ uint32_t flags;
+ const Vector<String> excluded_shader_types;
+ const Vector<String> functions;
};
static const KeyWord keyword_list[];
- GlobalVariableGetTypeFunc global_var_get_type_func;
+ GlobalVariableGetTypeFunc global_var_get_type_func = nullptr;
- bool error_set;
+ bool error_set = false;
String error_str;
- int error_line;
+ int error_line = 0;
#ifdef DEBUG_ENABLED
struct Usage {
@@ -889,20 +893,20 @@ private:
}
};
- Map<StringName, Usage> used_constants;
- Map<StringName, Usage> used_varyings;
- Map<StringName, Usage> used_uniforms;
- Map<StringName, Usage> used_functions;
- Map<StringName, Usage> used_structs;
- Map<ShaderWarning::Code, Map<StringName, Usage> *> warnings_check_map;
+ HashMap<StringName, Usage> used_constants;
+ HashMap<StringName, Usage> used_varyings;
+ HashMap<StringName, Usage> used_uniforms;
+ HashMap<StringName, Usage> used_functions;
+ HashMap<StringName, Usage> used_structs;
+ HashMap<ShaderWarning::Code, HashMap<StringName, Usage> *> warnings_check_map;
- Map<StringName, Map<StringName, Usage>> used_local_vars;
- Map<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> warnings_check_map2;
+ HashMap<StringName, HashMap<StringName, Usage>> used_local_vars;
+ HashMap<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> warnings_check_map2;
List<ShaderWarning> warnings;
bool check_warnings = false;
- uint32_t warning_flags;
+ uint32_t warning_flags = 0;
void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
warnings.push_back(ShaderWarning(p_code, tk_line, p_subject, p_extra_args));
@@ -917,9 +921,10 @@ private:
#endif // DEBUG_ENABLED
String code;
- int char_idx;
- int tk_line;
+ int char_idx = 0;
+ int tk_line = 0;
+ StringName shader_type_identifier;
StringName current_function;
bool last_const = false;
StringName last_name;
@@ -972,8 +977,9 @@ private:
Token _make_token(TokenType p_type, const StringName &p_text = StringName());
Token _get_token();
+ bool _lookup_next(Token &r_tk);
- ShaderNode *shader;
+ ShaderNode *shader = nullptr;
enum IdentifierType {
IDENTIFIER_FUNCTION,
@@ -1020,16 +1026,20 @@ private:
};
CompletionType completion_type;
- int completion_line;
- BlockNode *completion_block;
+ int completion_line = 0;
+ BlockNode *completion_block = nullptr;
DataType completion_base;
- bool completion_base_array;
+ bool completion_base_array = false;
SubClassTag completion_class;
StringName completion_function;
StringName completion_struct;
- int completion_argument;
+ int completion_argument = 0;
+
+#ifdef DEBUG_ENABLED
+ uint32_t keyword_completion_context;
+#endif // DEBUG_ENABLED
- const Map<StringName, FunctionInfo> *stages = nullptr;
+ const HashMap<StringName, FunctionInfo> *stages = nullptr;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
@@ -1038,7 +1048,7 @@ private:
static bool is_const_suffix_lut_initialized;
- Error _validate_datatype(DataType p_type);
+ Error _validate_precision(DataType p_type, DataPrecision p_precision);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
bool _compare_datatypes_in_nodes(Node *a, Node *b);
@@ -1057,10 +1067,10 @@ private:
Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
Error _parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
- String _get_shader_type_list(const Set<String> &p_shader_types) const;
+ String _get_shader_type_list(const HashSet<String> &p_shader_types) const;
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
- Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types);
+ Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types);
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
@@ -1083,15 +1093,15 @@ public:
static String get_shader_type(const String &p_code);
struct ShaderCompileInfo {
- Map<StringName, FunctionInfo> functions;
+ HashMap<StringName, FunctionInfo> functions;
Vector<ModeInfo> render_modes;
VaryingFunctionNames varying_function_names = VaryingFunctionNames();
- Set<String> shader_types;
+ HashSet<String> shader_types;
GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
};
Error compile(const String &p_code, const ShaderCompileInfo &p_info);
- Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
+ Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
int get_error_line();
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 9ea98dc593..5772179d68 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -31,7 +31,7 @@
#include "shader_types.h"
#include "core/math/math_defs.h"
-const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const {
+const HashMap<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const {
return shader_modes[p_mode].functions;
}
@@ -39,7 +39,7 @@ const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_
return shader_modes[p_mode].modes;
}
-const Set<String> &ShaderTypes::get_types() const {
+const HashSet<String> &ShaderTypes::get_types() const {
return shader_types;
}
@@ -86,10 +86,10 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].main_function = true;
//builtins
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
@@ -145,10 +145,10 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
@@ -163,9 +163,9 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_ANTIALIASING_EDGE"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_TEXTURE_COORDINATE"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
@@ -178,7 +178,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SHADOW_ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["BACKLIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["METALLIC"] = constt(ShaderLanguage::TYPE_FLOAT);
@@ -193,26 +192,26 @@ ShaderTypes::ShaderTypes() {
// spatial render modes
{
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "blend", "mix", "add", "sub", "mul" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_draw", "opaque", "always", "never" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_prepass_alpha" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_test_disabled" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "sss_mode_skin" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "cull", "back", "front", "disabled" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "unshaded" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "wireframe" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "diffuse", "lambert", "lambert_wrap", "burley", "toon" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "specular", "schlick_ggx", "toon", "disabled" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "skip_vertex_transform" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "world_vertex_coords" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ensure_correct_normals" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadows_disabled" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ambient_light_disabled" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadow_to_opacity" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "vertex_lighting" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "particle_trails" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage" });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage_and_one" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_draw"), "opaque", "always", "never" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_prepass_alpha") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("sss_mode_skin") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("cull"), "back", "front", "disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("unshaded") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("wireframe") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("diffuse"), "lambert", "lambert_wrap", "burley", "toon" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("specular"), "schlick_ggx", "toon", "disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("skip_vertex_transform") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("world_vertex_coords") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("ensure_correct_normals") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("shadows_disabled") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("ambient_light_disabled") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("shadow_to_opacity") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("vertex_lighting") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("particle_trails") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage_and_one") });
}
/************ CANVAS ITEM **************************/
@@ -227,7 +226,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
@@ -300,10 +299,10 @@ ShaderTypes::ShaderTypes() {
// canvasitem render modes
{
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "skip_vertex_transform" });
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "blend", "mix", "add", "sub", "mul", "premul_alpha", "disabled" });
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "unshaded" });
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "light_only" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ PNAME("skip_vertex_transform") });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul", "premul_alpha", "disabled" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ PNAME("unshaded") });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ PNAME("light_only") });
}
/************ PARTICLES **************************/
@@ -381,10 +380,10 @@ ShaderTypes::ShaderTypes() {
// particles render modes
{
- shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "collision_use_scale" });
- shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_force" });
- shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_velocity" });
- shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "keep_data" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ PNAME("collision_use_scale") });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ PNAME("disable_force") });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ PNAME("disable_velocity") });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ PNAME("keep_data") });
}
/************ SKY **************************/
@@ -423,6 +422,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
@@ -431,9 +431,9 @@ ShaderTypes::ShaderTypes() {
// sky render modes
{
- shader_modes[RS::SHADER_SKY].modes.push_back({ "use_half_res_pass" });
- shader_modes[RS::SHADER_SKY].modes.push_back({ "use_quarter_res_pass" });
- shader_modes[RS::SHADER_SKY].modes.push_back({ "disable_fog" });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_half_res_pass") });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_quarter_res_pass") });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("disable_fog") });
}
/************ FOG **************************/
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 385083b670..107525cd15 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -31,29 +31,29 @@
#ifndef SHADERTYPES_H
#define SHADERTYPES_H
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/rb_map.h"
#include "servers/rendering_server.h"
#include "shader_language.h"
class ShaderTypes {
struct Type {
- Map<StringName, ShaderLanguage::FunctionInfo> functions;
+ HashMap<StringName, ShaderLanguage::FunctionInfo> functions;
Vector<ShaderLanguage::ModeInfo> modes;
};
- Map<RS::ShaderMode, Type> shader_modes;
+ HashMap<RS::ShaderMode, Type> shader_modes;
static ShaderTypes *singleton;
- Set<String> shader_types;
+ HashSet<String> shader_types;
List<String> shader_types_list;
public:
static ShaderTypes *get_singleton() { return singleton; }
- const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
+ const HashMap<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const;
- const Set<String> &get_types() const;
+ const HashSet<String> &get_types() const;
const List<String> &get_types_list() const;
ShaderTypes();
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
index 639b9bd165..855dc23d94 100644
--- a/servers/rendering/shader_warnings.cpp
+++ b/servers/rendering/shader_warnings.cpp
@@ -109,10 +109,10 @@ ShaderWarning::Code ShaderWarning::get_code_from_name(const String &p_name) {
ERR_FAIL_V_MSG(WARNING_MAX, "Invalid shader warning name: " + p_name);
}
-static Map<int, uint32_t> *code_to_flags_map = nullptr;
+static HashMap<int, uint32_t> *code_to_flags_map = nullptr;
static void init_code_to_flags_map() {
- code_to_flags_map = memnew((Map<int, uint32_t>));
+ code_to_flags_map = memnew((HashMap<int, uint32_t>));
code_to_flags_map->insert(ShaderWarning::FLOAT_COMPARISON, ShaderWarning::FLOAT_COMPARISON_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_CONSTANT, ShaderWarning::UNUSED_CONSTANT_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_FUNCTION, ShaderWarning::UNUSED_FUNCTION_FLAG);
@@ -124,7 +124,7 @@ static void init_code_to_flags_map() {
code_to_flags_map->insert(ShaderWarning::DEVICE_LIMIT_EXCEEDED, ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG);
}
-ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
+ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const HashMap<Code, bool> &p_map) {
uint32_t result = 0U;
if (code_to_flags_map == nullptr) {
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index e309907181..8edf85842f 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -34,8 +34,9 @@
#ifdef DEBUG_ENABLED
#include "core/string/string_name.h"
+#include "core/templates/hash_map.h"
#include "core/templates/list.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/variant/variant.h"
class ShaderWarning {
@@ -82,7 +83,7 @@ public:
static String get_name_from_code(Code p_code);
static Code get_code_from_name(const String &p_name);
- static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map);
+ static CodeFlags get_flags_from_codemap(const HashMap<Code, bool> &p_map);
ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>());
};
diff --git a/servers/rendering/storage/SCsub b/servers/rendering/storage/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/rendering/storage/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
new file mode 100644
index 0000000000..0cb0f35570
--- /dev/null
+++ b/servers/rendering/storage/light_storage.h
@@ -0,0 +1,139 @@
+/*************************************************************************/
+/* light_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIGHT_STORAGE_H
+#define LIGHT_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererLightStorage {
+public:
+ virtual ~RendererLightStorage() {}
+
+ /* Light API */
+
+ virtual RID directional_light_allocate() = 0;
+ virtual void directional_light_initialize(RID p_rid) = 0;
+
+ virtual RID omni_light_allocate() = 0;
+ virtual void omni_light_initialize(RID p_rid) = 0;
+
+ virtual RID spot_light_allocate() = 0;
+ virtual void spot_light_initialize(RID p_rid) = 0;
+
+ virtual void light_free(RID p_rid) = 0;
+
+ 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_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_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 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_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0;
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_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 bool light_has_projector(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_allocate() = 0;
+ virtual void reflection_probe_initialize(RID p_rid) = 0;
+ virtual void reflection_probe_free(RID p_rid) = 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_mesh_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_mesh_lod_threshold(RID p_probe) const = 0;
+
+ /* LIGHTMAP */
+
+ virtual RID lightmap_allocate() = 0;
+ virtual void lightmap_initialize(RID p_rid) = 0;
+ virtual void lightmap_free(RID p_rid) = 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;
+};
+
+#endif // !LIGHT_STORAGE_H
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
new file mode 100644
index 0000000000..f0363f129a
--- /dev/null
+++ b/servers/rendering/storage/material_storage.h
@@ -0,0 +1,101 @@
+/*************************************************************************/
+/* material_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MATERIAL_STORAGE_H
+#define MATERIAL_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererMaterialStorage {
+public:
+ virtual ~RendererMaterialStorage(){};
+
+ /* GLOBAL VARIABLE API */
+ 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;
+
+ /* SHADER API */
+ virtual RID shader_allocate() = 0;
+ virtual void shader_initialize(RID p_rid) = 0;
+ virtual void shader_free(RID p_rid) = 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, int p_index) = 0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) 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;
+
+ /* MATERIAL API */
+
+ virtual RID material_allocate() = 0;
+ virtual void material_initialize(RID p_rid) = 0;
+ virtual void material_free(RID p_rid) = 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, RendererStorage::DependencyTracker *p_instance) = 0;
+};
+
+#endif // !MATERIAL_STORAGE_H
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
new file mode 100644
index 0000000000..1dac51319c
--- /dev/null
+++ b/servers/rendering/storage/mesh_storage.h
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_H
+#define MESH_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererMeshStorage {
+public:
+ virtual ~RendererMeshStorage() {}
+
+ /* MESH API */
+
+ virtual RID mesh_allocate() = 0;
+ virtual void mesh_initialize(RID p_rid) = 0;
+ virtual void mesh_free(RID p_rid) = 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_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_skin_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_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 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_free(RID p_rid) = 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_allocate() = 0;
+ virtual void multimesh_initialize(RID p_rid) = 0;
+ virtual void multimesh_free(RID p_rid) = 0;
+
+ virtual void multimesh_allocate_data(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 Transform3D &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 Transform3D 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;
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() = 0;
+ virtual void skeleton_initialize(RID p_rid) = 0;
+ virtual void skeleton_free(RID p_rid) = 0;
+
+ virtual void skeleton_allocate_data(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 Transform3D &p_transform) = 0;
+ virtual Transform3D 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;
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0;
+};
+
+#endif // !MESH_STORAGE_H
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
new file mode 100644
index 0000000000..268b5473e2
--- /dev/null
+++ b/servers/rendering/storage/particles_storage.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* particles_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PARTICLES_STORAGE_H
+#define PARTICLES_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererParticlesStorage {
+public:
+ virtual ~RendererParticlesStorage() {}
+
+ /* PARTICLES */
+
+ virtual RID particles_allocate() = 0;
+ virtual void particles_initialize(RID p_rid) = 0;
+ virtual void particles_free(RID p_rid) = 0;
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 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, double 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, double p_time) = 0;
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t 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, double 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 RID particles_get_process_material(RID p_particles) const = 0;
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
+
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
+
+ virtual void particles_restart(RID p_particles) = 0;
+ virtual void particles_emit(RID p_particles, const Transform3D &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 Transform3D &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, const Vector3 &p_up_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 particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
+
+ virtual void update_particles() = 0;
+
+ /* PARTICLES COLLISION */
+
+ virtual RID particles_collision_allocate() = 0;
+ virtual void particles_collision_initialize(RID p_rid) = 0;
+ virtual void particles_collision_free(RID p_rid) = 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, real_t 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, real_t p_strength) = 0;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t 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_free(RID p_rid) = 0;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
+};
+
+#endif // !PARTICLES_STORAGE_H
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
new file mode 100644
index 0000000000..e3a969d032
--- /dev/null
+++ b/servers/rendering/storage/texture_storage.h
@@ -0,0 +1,137 @@
+/*************************************************************************/
+/* texture_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEXTURE_STORAGE_H
+#define TEXTURE_STORAGE_H
+
+#include "servers/rendering_server.h"
+
+class RendererTextureStorage {
+public:
+ /* Canvas Texture API */
+
+ virtual RID canvas_texture_allocate() = 0;
+ virtual void canvas_texture_initialize(RID p_rid) = 0;
+ virtual void canvas_texture_free(RID p_rid) = 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;
+
+ /* Texture API */
+ virtual bool can_create_resources_async() const = 0;
+
+ virtual ~RendererTextureStorage(){};
+
+ virtual RID texture_allocate() = 0;
+ virtual void texture_free(RID p_rid) = 0;
+
+ virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
+ virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
+ virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
+ virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
+
+ 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 void texture_2d_placeholder_initialize(RID p_texture) = 0;
+ virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
+ virtual void texture_3d_placeholder_initialize(RID p_texture) = 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;
+
+ /* Decal API */
+ virtual RID decal_allocate() = 0;
+ virtual void decal_initialize(RID p_rid) = 0;
+ virtual void decal_free(RID p_rid) = 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;
+
+ 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;
+
+ /* RENDER TARGET */
+
+ virtual RID render_target_create() = 0;
+ virtual void render_target_free(RID p_rid) = 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, uint32_t p_view_count) = 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_transparent(RID p_render_target, bool p_is_transparent) = 0;
+ virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) = 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 void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
+};
+
+#endif // !TEXTURE_STORAGE_H
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index fe5c7dc0de..26ab8b659e 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -424,7 +424,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
if (src[i * 4 + 3] > 0) {
- value |= 3 << 30;
+ value |= 3UL << 30;
}
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
@@ -440,7 +440,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
if (src[i * 4 + 3] > 0) {
- value |= 3 << 30;
+ value |= 3UL << 30;
}
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
}
@@ -979,7 +979,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Invalid array format for surface.");
Vector<uint8_t> blend_shape_data;
- uint32_t blend_shape_count = 0;
if (p_blend_shapes.size()) {
uint32_t bs_format = format & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK;
@@ -996,7 +995,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
ERR_FAIL_COND_V_MSG(err2 != OK, ERR_INVALID_DATA, "Invalid blend shape array format for surface.");
blend_shape_data.append_array(vertex_array_shape);
- blend_shape_count++;
}
}
Vector<SurfaceData::LOD> lods;
@@ -1095,7 +1093,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Vector2 *w = arr_2d.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
- const float *v = (const float *)&r[j * vertex_elem_size + offsets[i]];
+ const float *v = reinterpret_cast<const float *>(&r[j * vertex_elem_size + offsets[i]]);
w[j] = Vector2(v[0], v[1]);
}
}
@@ -1109,7 +1107,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Vector3 *w = arr_3d.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
- const float *v = (const float *)&r[j * vertex_elem_size + offsets[i]];
+ const float *v = reinterpret_cast<const float *>(&r[j * vertex_elem_size + offsets[i]]);
w[j] = Vector3(v[0], v[1], v[2]);
}
}
@@ -1158,7 +1156,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Color *w = arr.ptrw();
for (int32_t j = 0; j < p_vertex_len; j++) {
- const uint8_t *v = (const uint8_t *)&ar[j * attrib_elem_size + offsets[i]];
+ const uint8_t *v = reinterpret_cast<const uint8_t *>(&ar[j * attrib_elem_size + offsets[i]]);
w[j] = Color(v[0] / 255.0, v[1] / 255.0, v[2] / 255.0, v[3] / 255.0);
}
@@ -1172,7 +1170,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Vector2 *w = arr.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
- const float *v = (const float *)&ar[j * attrib_elem_size + offsets[i]];
+ const float *v = reinterpret_cast<const float *>(&ar[j * attrib_elem_size + offsets[i]]);
w[j] = Vector2(v[0], v[1]);
}
@@ -1186,7 +1184,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
Vector2 *w = arr.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
- const float *v = (const float *)&ar[j * attrib_elem_size + offsets[i]];
+ const float *v = reinterpret_cast<const float *>(&ar[j * attrib_elem_size + offsets[i]]);
w[j] = Vector2(v[0], v[1]);
}
@@ -1211,7 +1209,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
uint8_t *w = arr.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
- const uint8_t *v = (const uint8_t *)&ar[j * attrib_elem_size + offsets[i]];
+ const uint8_t *v = reinterpret_cast<const uint8_t *>(&ar[j * attrib_elem_size + offsets[i]]);
memcpy(&w[j * s], v, s);
}
@@ -1230,7 +1228,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
float *w = arr.ptrw();
for (int j = 0; j < p_vertex_len; j++) {
- const float *v = (const float *)&ar[j * attrib_elem_size + offsets[i]];
+ const float *v = reinterpret_cast<const float *>(&ar[j * attrib_elem_size + offsets[i]]);
memcpy(&w[j * s], v, s * sizeof(float));
}
ret[i] = arr;
@@ -1879,10 +1877,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_set_color", "light", "color"), &RenderingServer::light_set_color);
ClassDB::bind_method(D_METHOD("light_set_param", "light", "param", "value"), &RenderingServer::light_set_param);
ClassDB::bind_method(D_METHOD("light_set_shadow", "light", "enabled"), &RenderingServer::light_set_shadow);
- ClassDB::bind_method(D_METHOD("light_set_shadow_color", "light", "color"), &RenderingServer::light_set_shadow_color);
ClassDB::bind_method(D_METHOD("light_set_projector", "light", "texture"), &RenderingServer::light_set_projector);
ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &RenderingServer::light_set_negative);
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask);
+ ClassDB::bind_method(D_METHOD("light_set_distance_fade", "decal", "enabled", "begin", "shadow", "length"), &RenderingServer::light_set_distance_fade);
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode);
ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode);
ClassDB::bind_method(D_METHOD("light_set_max_sdfgi_cascade", "light", "cascade"), &RenderingServer::light_set_max_sdfgi_cascade);
@@ -1891,7 +1889,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &RenderingServer::light_directional_set_shadow_mode);
ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits);
- ClassDB::bind_method(D_METHOD("light_directional_set_sky_only", "light", "enable"), &RenderingServer::light_directional_set_sky_only);
+ ClassDB::bind_method(D_METHOD("light_directional_set_sky_mode", "light", "mode"), &RenderingServer::light_directional_set_sky_mode);
ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
@@ -1937,6 +1935,10 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS);
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY);
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY);
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY);
+
ClassDB::bind_method(D_METHOD("shadows_quality_set", "quality"), &RenderingServer::shadows_quality_set);
ClassDB::bind_method(D_METHOD("directional_shadow_quality_set", "quality"), &RenderingServer::directional_shadow_quality_set);
ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size);
@@ -2138,8 +2140,11 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("fog_volume_set_material", "fog_volume", "material"), &RenderingServer::fog_volume_set_material);
BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_ELLIPSOID);
+ BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_CONE);
+ BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_CYLINDER);
BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_BOX);
BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_WORLD);
+ BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_MAX);
/* VISIBILITY NOTIFIER */
@@ -2206,6 +2211,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision);
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
ClassDB::bind_method(D_METHOD("viewport_set_screen_space_aa", "viewport", "mode"), &RenderingServer::viewport_set_screen_space_aa);
+ ClassDB::bind_method(D_METHOD("viewport_set_use_taa", "viewport", "enable"), &RenderingServer::viewport_set_use_taa);
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding", "viewport", "enable"), &RenderingServer::viewport_set_use_debanding);
ClassDB::bind_method(D_METHOD("viewport_set_use_occlusion_culling", "viewport", "enable"), &RenderingServer::viewport_set_use_occlusion_culling);
ClassDB::bind_method(D_METHOD("viewport_set_occlusion_rays_per_thread", "rays_per_thread"), &RenderingServer::viewport_set_occlusion_rays_per_thread);
@@ -2292,6 +2298,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_MOTION_VECTORS);
/* SKY API */
@@ -2564,7 +2571,7 @@ void RenderingServer::_bind_methods() {
/* Primitives */
- ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
@@ -2580,6 +2587,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture"), &RenderingServer::canvas_item_add_particles);
ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &RenderingServer::canvas_item_add_set_transform);
ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &RenderingServer::canvas_item_add_clip_ignore);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_animation_slice", "item", "animation_length", "slice_begin", "slice_end", "offset"), &RenderingServer::canvas_item_add_animation_slice, DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &RenderingServer::canvas_item_set_sort_children_by_y);
ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &RenderingServer::canvas_item_set_z_index);
ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &RenderingServer::canvas_item_set_z_as_relative_to_parent);
@@ -2723,6 +2731,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name);
ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &RenderingServer::get_video_adapter_vendor);
ClassDB::bind_method(D_METHOD("get_video_adapter_type"), &RenderingServer::get_video_adapter_type);
+ ClassDB::bind_method(D_METHOD("get_video_adapter_api_version"), &RenderingServer::get_video_adapter_api_version);
ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh);
ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube);
@@ -2814,7 +2823,9 @@ RenderingServer::RenderingServer() {
thread_pool = memnew(RendererThreadPool);
singleton = this;
+}
+void RenderingServer::init() {
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_bptc", false);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc", true);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc", false);
@@ -2881,6 +2892,7 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley.mobile", true);
GLOBAL_DEF("rendering/driver/depth_prepass/enable", true);
+ GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2);
@@ -2894,8 +2906,7 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/environment/ssao/quality", 2);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/quality", PropertyInfo(Variant::INT, "rendering/environment/ssao/quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low (Fast),Medium (Average),High (Slow),Ultra (Custom)"));
- GLOBAL_DEF("rendering/environment/ssao/half_size", false);
- GLOBAL_DEF("rendering/environment/ssao/half_size.mobile", true);
+ GLOBAL_DEF("rendering/environment/ssao/half_size", true);
GLOBAL_DEF("rendering/environment/ssao/adaptive_target", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/adaptive_target", PropertyInfo(Variant::FLOAT, "rendering/environment/ssao/adaptive_target", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
GLOBAL_DEF("rendering/environment/ssao/blur_passes", 2);
@@ -2930,7 +2941,7 @@ RenderingServer::RenderingServer() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode",
PropertyInfo(Variant::INT,
"rendering/scaling_3d/mode",
- PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR (Fast)"));
+ PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/scale",
PropertyInfo(Variant::FLOAT,
@@ -2999,44 +3010,15 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/limits/cluster_builder/max_clustered_elements", 512);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"));
- GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false);
+ // OpenGL limits
+ GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_elements", 65536);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,65536,1"));
+ GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_lights", 32);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "2,256,1"));
+ GLOBAL_DEF_RST("rendering/limits/opengl/max_lights_per_object", 8);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_lights_per_object", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1"));
- GLOBAL_DEF_RST("rendering/2d/options/use_software_skinning", true);
- GLOBAL_DEF_RST("rendering/2d/options/ninepatch_mode", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/options/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/2d/options/ninepatch_mode", PROPERTY_HINT_ENUM, "Fixed,Scaling"));
-
- GLOBAL_DEF_RST("rendering/2d/opengl/batching_send_null", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_send_null", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_send_null", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
- GLOBAL_DEF_RST("rendering/2d/opengl/batching_stream", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_stream", PROPERTY_HINT_ENUM, "Default (Off),Off,On"));
- GLOBAL_DEF_RST("rendering/2d/opengl/legacy_orphan_buffers", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_orphan_buffers", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_orphan_buffers", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
- GLOBAL_DEF_RST("rendering/2d/opengl/legacy_stream", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_stream", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
-
- GLOBAL_DEF("rendering/batching/options/use_batching", false);
- GLOBAL_DEF_RST("rendering/batching/options/use_batching_in_editor", false);
- GLOBAL_DEF("rendering/batching/options/single_rect_fallback", false);
- GLOBAL_DEF("rendering/batching/parameters/max_join_item_commands", 16);
- GLOBAL_DEF("rendering/batching/parameters/colored_vertex_format_threshold", 0.25f);
- GLOBAL_DEF("rendering/batching/lights/scissor_area_threshold", 1.0f);
- GLOBAL_DEF("rendering/batching/lights/max_join_items", 32);
- GLOBAL_DEF("rendering/batching/parameters/batch_buffer_size", 16384);
- GLOBAL_DEF("rendering/batching/parameters/item_reordering_lookahead", 4);
- GLOBAL_DEF("rendering/batching/debug/flash_batching", false);
- GLOBAL_DEF("rendering/batching/debug/diagnose_frame", false);
- GLOBAL_DEF("rendering/gles2/compatibility/disable_half_float", false);
- GLOBAL_DEF("rendering/gles2/compatibility/enable_high_float.Android", false);
- GLOBAL_DEF("rendering/batching/precision/uv_contract", false);
- GLOBAL_DEF("rendering/batching/precision/uv_contract_amount", 100);
-
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/max_join_item_commands", PropertyInfo(Variant::INT, "rendering/batching/parameters/max_join_item_commands", PROPERTY_HINT_RANGE, "0,65535"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/colored_vertex_format_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/parameters/colored_vertex_format_threshold", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/batch_buffer_size", PropertyInfo(Variant::INT, "rendering/batching/parameters/batch_buffer_size", PROPERTY_HINT_RANGE, "1024,65535,1024"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/scissor_area_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/lights/scissor_area_threshold", PROPERTY_HINT_RANGE, "0.0,1.0"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/max_join_items", PropertyInfo(Variant::INT, "rendering/batching/lights/max_join_items", PROPERTY_HINT_RANGE, "0,512"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/item_reordering_lookahead", PropertyInfo(Variant::INT, "rendering/batching/parameters/item_reordering_lookahead", PROPERTY_HINT_RANGE, "0,256"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/precision/uv_contract_amount", PropertyInfo(Variant::INT, "rendering/batching/precision/uv_contract_amount", PROPERTY_HINT_RANGE, "0,10000"));
+ GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false);
}
RenderingServer::~RenderingServer() {
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 5748d8808b..39484e532a 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -47,7 +47,7 @@ class RenderingServer : public Object {
static RenderingServer *singleton;
- int mm_policy;
+ int mm_policy = 0;
bool render_loop_enabled = true;
Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const;
@@ -439,10 +439,10 @@ public:
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, 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_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
enum LightBakeMode {
@@ -469,9 +469,15 @@ public:
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS,
};
+ enum LightDirectionalSkyMode {
+ LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY,
+ LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY,
+ LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY,
+ };
+
virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
- virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0;
+ virtual void light_directional_set_sky_mode(RID p_light, LightDirectionalSkyMode p_mode) = 0;
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
@@ -718,8 +724,11 @@ public:
enum FogVolumeShape {
FOG_VOLUME_SHAPE_ELLIPSOID,
+ FOG_VOLUME_SHAPE_CONE,
+ FOG_VOLUME_SHAPE_CYLINDER,
FOG_VOLUME_SHAPE_BOX,
FOG_VOLUME_SHAPE_WORLD,
+ FOG_VOLUME_SHAPE_MAX,
};
virtual void fog_volume_set_shape(RID p_fog_volume, FogVolumeShape p_shape) = 0;
@@ -868,11 +877,13 @@ public:
virtual void viewport_set_screen_space_aa(RID p_viewport, ViewportScreenSpaceAA p_mode) = 0;
+ virtual void viewport_set_use_taa(RID p_viewport, bool p_use_taa) = 0;
+
virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0;
virtual void viewport_set_mesh_lod_threshold(RID p_viewport, float p_pixels) = 0;
- virtual void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_debanding) = 0;
+ virtual void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) = 0;
virtual void viewport_set_occlusion_rays_per_thread(int p_rays_per_thread) = 0;
enum ViewportOcclusionCullingBuildQuality {
@@ -924,6 +935,7 @@ public:
VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS,
VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES,
VIEWPORT_DEBUG_DRAW_OCCLUDERS,
+ VIEWPORT_DEBUG_DRAW_MOTION_VECTORS,
};
virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0;
@@ -1287,7 +1299,7 @@ public:
NINE_PATCH_TILE_FIT,
};
- virtual 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) = 0;
+ virtual 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, bool p_antialiased = false) = 0;
virtual 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) = 0;
virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0;
virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
@@ -1462,7 +1474,7 @@ public:
virtual void draw(bool p_swap_buffers = true, double frame_step = 0.0) = 0;
virtual void sync() = 0;
virtual bool has_changed() const = 0;
- virtual void init() = 0;
+ virtual void init();
virtual void finish() = 0;
/* STATUS INFORMATION */
@@ -1481,6 +1493,7 @@ public:
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
+ virtual String get_video_adapter_api_version() const = 0;
struct FrameProfileArea {
String name;
@@ -1569,6 +1582,7 @@ VARIANT_ENUM_CAST(RenderingServer::LightParam);
VARIANT_ENUM_CAST(RenderingServer::LightBakeMode);
VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode);
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
+VARIANT_ENUM_CAST(RenderingServer::LightDirectionalSkyMode);
VARIANT_ENUM_CAST(RenderingServer::LightProjectorFilter);
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeAmbientMode);
diff --git a/servers/text/text_server_dummy.h b/servers/text/text_server_dummy.h
new file mode 100644
index 0000000000..c603881b7c
--- /dev/null
+++ b/servers/text/text_server_dummy.h
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* text_server_dummy.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEXT_SERVER_DUMMY_H
+#define TEXT_SERVER_DUMMY_H
+
+#include "servers/text/text_server_extension.h"
+
+/*************************************************************************/
+
+class TextServerDummy : public TextServerExtension {
+ GDCLASS(TextServerDummy, TextServerExtension);
+ _THREAD_SAFE_CLASS_
+
+public:
+ virtual String get_name() const override {
+ return "Dummy";
+ }
+};
+
+#endif // TEXT_SERVER_DUMMY_H
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 5792572dc1..e9a558ac5f 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -31,261 +31,284 @@
#include "text_server_extension.h"
void TextServerExtension::_bind_methods() {
- GDVIRTUAL_BIND(_has_feature, "feature");
- GDVIRTUAL_BIND(_get_name);
- GDVIRTUAL_BIND(_get_features);
+ GDVIRTUAL_BIND(has_feature, "feature");
+ GDVIRTUAL_BIND(get_name);
+ GDVIRTUAL_BIND(get_features);
- GDVIRTUAL_BIND(_free, "rid");
- GDVIRTUAL_BIND(_has, "rid");
- GDVIRTUAL_BIND(_load_support_data, "filename");
+ GDVIRTUAL_BIND(free_rid, "rid");
+ GDVIRTUAL_BIND(has, "rid");
+ GDVIRTUAL_BIND(load_support_data, "filename");
- GDVIRTUAL_BIND(_get_support_data_filename);
- GDVIRTUAL_BIND(_get_support_data_info);
- GDVIRTUAL_BIND(_save_support_data, "filename");
+ GDVIRTUAL_BIND(get_support_data_filename);
+ GDVIRTUAL_BIND(get_support_data_info);
+ GDVIRTUAL_BIND(save_support_data, "filename");
- GDVIRTUAL_BIND(_is_locale_right_to_left, "locale");
+ GDVIRTUAL_BIND(is_locale_right_to_left, "locale");
- GDVIRTUAL_BIND(_name_to_tag, "name");
- GDVIRTUAL_BIND(_tag_to_name, "tag");
+ GDVIRTUAL_BIND(name_to_tag, "name");
+ GDVIRTUAL_BIND(tag_to_name, "tag");
/* Font interface */
- GDVIRTUAL_BIND(_create_font);
+ GDVIRTUAL_BIND(create_font);
- GDVIRTUAL_BIND(_font_set_data, "font_rid", "data");
- GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size");
+ GDVIRTUAL_BIND(font_set_data, "font_rid", "data");
+ GDVIRTUAL_BIND(font_set_data_ptr, "font_rid", "data_ptr", "data_size");
- GDVIRTUAL_BIND(_font_set_style, "font_rid", "style");
- GDVIRTUAL_BIND(_font_get_style, "font_rid");
+ GDVIRTUAL_BIND(font_set_face_index, "font_rid", "face_index");
+ GDVIRTUAL_BIND(font_get_face_index, "font_rid");
- GDVIRTUAL_BIND(_font_set_name, "font_rid", "name");
- GDVIRTUAL_BIND(_font_get_name, "font_rid");
+ GDVIRTUAL_BIND(font_get_face_count, "font_rid");
- GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style");
- GDVIRTUAL_BIND(_font_get_style_name, "font_rid");
+ GDVIRTUAL_BIND(font_set_style, "font_rid", "style");
+ GDVIRTUAL_BIND(font_get_style, "font_rid");
- GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased");
- GDVIRTUAL_BIND(_font_is_antialiased, "font_rid");
+ GDVIRTUAL_BIND(font_set_name, "font_rid", "name");
+ GDVIRTUAL_BIND(font_get_name, "font_rid");
- GDVIRTUAL_BIND(_font_set_multichannel_signed_distance_field, "font_rid", "msdf");
- GDVIRTUAL_BIND(_font_is_multichannel_signed_distance_field, "font_rid");
+ GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style");
+ GDVIRTUAL_BIND(font_get_style_name, "font_rid");
- GDVIRTUAL_BIND(_font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range");
- GDVIRTUAL_BIND(_font_get_msdf_pixel_range, "font_rid");
+ GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased");
+ GDVIRTUAL_BIND(font_is_antialiased, "font_rid");
- GDVIRTUAL_BIND(_font_set_msdf_size, "font_rid", "msdf_size");
- GDVIRTUAL_BIND(_font_get_msdf_size, "font_rid");
+ GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
+ GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid");
- GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size");
- GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid");
+ GDVIRTUAL_BIND(font_set_multichannel_signed_distance_field, "font_rid", "msdf");
+ GDVIRTUAL_BIND(font_is_multichannel_signed_distance_field, "font_rid");
- GDVIRTUAL_BIND(_font_set_force_autohinter, "font_rid", "force_autohinter");
- GDVIRTUAL_BIND(_font_is_force_autohinter, "font_rid");
+ GDVIRTUAL_BIND(font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range");
+ GDVIRTUAL_BIND(font_get_msdf_pixel_range, "font_rid");
- GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting");
- GDVIRTUAL_BIND(_font_get_hinting, "font_rid");
+ GDVIRTUAL_BIND(font_set_msdf_size, "font_rid", "msdf_size");
+ GDVIRTUAL_BIND(font_get_msdf_size, "font_rid");
- GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
- GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid");
+ GDVIRTUAL_BIND(font_set_fixed_size, "font_rid", "fixed_size");
+ GDVIRTUAL_BIND(font_get_fixed_size, "font_rid");
- GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
- GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
+ GDVIRTUAL_BIND(font_set_force_autohinter, "font_rid", "force_autohinter");
+ GDVIRTUAL_BIND(font_is_force_autohinter, "font_rid");
- GDVIRTUAL_BIND(_font_set_oversampling, "font_rid", "oversampling");
- GDVIRTUAL_BIND(_font_get_oversampling, "font_rid");
+ GDVIRTUAL_BIND(font_set_hinting, "font_rid", "hinting");
+ GDVIRTUAL_BIND(font_get_hinting, "font_rid");
- GDVIRTUAL_BIND(_font_get_size_cache_list, "font_rid");
- GDVIRTUAL_BIND(_font_clear_size_cache, "font_rid");
- GDVIRTUAL_BIND(_font_remove_size_cache, "font_rid", "size");
+ GDVIRTUAL_BIND(font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
+ GDVIRTUAL_BIND(font_get_subpixel_positioning, "font_rid");
- GDVIRTUAL_BIND(_font_set_ascent, "font_rid", "size", "ascent");
- GDVIRTUAL_BIND(_font_get_ascent, "font_rid", "size");
+ GDVIRTUAL_BIND(font_set_embolden, "font_rid", "strength");
+ GDVIRTUAL_BIND(font_get_embolden, "font_rid");
- GDVIRTUAL_BIND(_font_set_descent, "font_rid", "size", "descent");
- GDVIRTUAL_BIND(_font_get_descent, "font_rid", "size");
+ GDVIRTUAL_BIND(font_set_transform, "font_rid", "transform");
+ GDVIRTUAL_BIND(font_get_transform, "font_rid");
- GDVIRTUAL_BIND(_font_set_underline_position, "font_rid", "size", "underline_position");
- GDVIRTUAL_BIND(_font_get_underline_position, "font_rid", "size");
+ GDVIRTUAL_BIND(font_set_variation_coordinates, "font_rid", "variation_coordinates");
+ GDVIRTUAL_BIND(font_get_variation_coordinates, "font_rid");
- GDVIRTUAL_BIND(_font_set_underline_thickness, "font_rid", "size", "underline_thickness");
- GDVIRTUAL_BIND(_font_get_underline_thickness, "font_rid", "size");
+ GDVIRTUAL_BIND(font_set_oversampling, "font_rid", "oversampling");
+ GDVIRTUAL_BIND(font_get_oversampling, "font_rid");
- GDVIRTUAL_BIND(_font_set_scale, "font_rid", "size", "scale");
- GDVIRTUAL_BIND(_font_get_scale, "font_rid", "size");
+ GDVIRTUAL_BIND(font_get_size_cache_list, "font_rid");
+ GDVIRTUAL_BIND(font_clear_size_cache, "font_rid");
+ GDVIRTUAL_BIND(font_remove_size_cache, "font_rid", "size");
- GDVIRTUAL_BIND(_font_set_spacing, "font_rid", "size", "spacing", "value");
- GDVIRTUAL_BIND(_font_get_spacing, "font_rid", "size", "spacing");
+ GDVIRTUAL_BIND(font_set_ascent, "font_rid", "size", "ascent");
+ GDVIRTUAL_BIND(font_get_ascent, "font_rid", "size");
- GDVIRTUAL_BIND(_font_get_texture_count, "font_rid", "size");
- GDVIRTUAL_BIND(_font_clear_textures, "font_rid", "size");
- GDVIRTUAL_BIND(_font_remove_texture, "font_rid", "size", "texture_index");
+ GDVIRTUAL_BIND(font_set_descent, "font_rid", "size", "descent");
+ GDVIRTUAL_BIND(font_get_descent, "font_rid", "size");
- GDVIRTUAL_BIND(_font_set_texture_image, "font_rid", "size", "texture_index", "image");
- GDVIRTUAL_BIND(_font_get_texture_image, "font_rid", "size", "texture_index");
+ GDVIRTUAL_BIND(font_set_underline_position, "font_rid", "size", "underline_position");
+ GDVIRTUAL_BIND(font_get_underline_position, "font_rid", "size");
- GDVIRTUAL_BIND(_font_set_texture_offsets, "font_rid", "size", "texture_index", "offset");
- GDVIRTUAL_BIND(_font_get_texture_offsets, "font_rid", "size", "texture_index");
+ GDVIRTUAL_BIND(font_set_underline_thickness, "font_rid", "size", "underline_thickness");
+ GDVIRTUAL_BIND(font_get_underline_thickness, "font_rid", "size");
- GDVIRTUAL_BIND(_font_get_glyph_list, "font_rid", "size");
- GDVIRTUAL_BIND(_font_clear_glyphs, "font_rid", "size");
- GDVIRTUAL_BIND(_font_remove_glyph, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_set_scale, "font_rid", "size", "scale");
+ GDVIRTUAL_BIND(font_get_scale, "font_rid", "size");
- GDVIRTUAL_BIND(_font_get_glyph_advance, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_set_glyph_advance, "font_rid", "size", "glyph", "advance");
+ GDVIRTUAL_BIND(font_set_spacing, "font_rid", "size", "spacing", "value");
+ GDVIRTUAL_BIND(font_get_spacing, "font_rid", "size", "spacing");
- GDVIRTUAL_BIND(_font_get_glyph_offset, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_set_glyph_offset, "font_rid", "size", "glyph", "offset");
+ GDVIRTUAL_BIND(font_get_texture_count, "font_rid", "size");
+ GDVIRTUAL_BIND(font_clear_textures, "font_rid", "size");
+ GDVIRTUAL_BIND(font_remove_texture, "font_rid", "size", "texture_index");
- GDVIRTUAL_BIND(_font_get_glyph_size, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_set_glyph_size, "font_rid", "size", "glyph", "gl_size");
+ GDVIRTUAL_BIND(font_set_texture_image, "font_rid", "size", "texture_index", "image");
+ GDVIRTUAL_BIND(font_get_texture_image, "font_rid", "size", "texture_index");
- GDVIRTUAL_BIND(_font_get_glyph_uv_rect, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect");
+ GDVIRTUAL_BIND(font_set_texture_offsets, "font_rid", "size", "texture_index", "offset");
+ GDVIRTUAL_BIND(font_get_texture_offsets, "font_rid", "size", "texture_index");
- GDVIRTUAL_BIND(_font_get_glyph_texture_idx, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
+ GDVIRTUAL_BIND(font_get_glyph_list, "font_rid", "size");
+ GDVIRTUAL_BIND(font_clear_glyphs, "font_rid", "size");
+ GDVIRTUAL_BIND(font_remove_glyph, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_get_glyph_contours, "font_rid", "size", "index");
+ GDVIRTUAL_BIND(font_get_glyph_advance, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_set_glyph_advance, "font_rid", "size", "glyph", "advance");
- GDVIRTUAL_BIND(_font_get_kerning_list, "font_rid", "size");
- GDVIRTUAL_BIND(_font_clear_kerning_map, "font_rid", "size");
- GDVIRTUAL_BIND(_font_remove_kerning, "font_rid", "size", "glyph_pair");
+ GDVIRTUAL_BIND(font_get_glyph_offset, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_set_glyph_offset, "font_rid", "size", "glyph", "offset");
- GDVIRTUAL_BIND(_font_set_kerning, "font_rid", "size", "glyph_pair", "kerning");
- GDVIRTUAL_BIND(_font_get_kerning, "font_rid", "size", "glyph_pair");
+ GDVIRTUAL_BIND(font_get_glyph_size, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_set_glyph_size, "font_rid", "size", "glyph", "gl_size");
- GDVIRTUAL_BIND(_font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
+ GDVIRTUAL_BIND(font_get_glyph_uv_rect, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect");
- GDVIRTUAL_BIND(_font_has_char, "font_rid", "char");
- GDVIRTUAL_BIND(_font_get_supported_chars, "font_rid");
+ GDVIRTUAL_BIND(font_get_glyph_texture_idx, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
- GDVIRTUAL_BIND(_font_render_range, "font_rid", "size", "start", "end");
- GDVIRTUAL_BIND(_font_render_glyph, "font_rid", "size", "index");
+ GDVIRTUAL_BIND(font_get_glyph_texture_rid, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_get_glyph_texture_size, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(_font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color");
- GDVIRTUAL_BIND(_font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color");
+ GDVIRTUAL_BIND(font_get_glyph_contours, "font_rid", "size", "index");
- GDVIRTUAL_BIND(_font_is_language_supported, "font_rid", "language");
- GDVIRTUAL_BIND(_font_set_language_support_override, "font_rid", "language", "supported");
- GDVIRTUAL_BIND(_font_get_language_support_override, "font_rid", "language");
- GDVIRTUAL_BIND(_font_remove_language_support_override, "font_rid", "language");
- GDVIRTUAL_BIND(_font_get_language_support_overrides, "font_rid");
+ GDVIRTUAL_BIND(font_get_kerning_list, "font_rid", "size");
+ GDVIRTUAL_BIND(font_clear_kerning_map, "font_rid", "size");
+ GDVIRTUAL_BIND(font_remove_kerning, "font_rid", "size", "glyph_pair");
- GDVIRTUAL_BIND(_font_is_script_supported, "font_rid", "script");
- GDVIRTUAL_BIND(_font_set_script_support_override, "font_rid", "script", "supported");
- GDVIRTUAL_BIND(_font_get_script_support_override, "font_rid", "script");
- GDVIRTUAL_BIND(_font_remove_script_support_override, "font_rid", "script");
- GDVIRTUAL_BIND(_font_get_script_support_overrides, "font_rid");
+ GDVIRTUAL_BIND(font_set_kerning, "font_rid", "size", "glyph_pair", "kerning");
+ GDVIRTUAL_BIND(font_get_kerning, "font_rid", "size", "glyph_pair");
- GDVIRTUAL_BIND(_font_set_opentype_feature_overrides, "font_rid", "overrides");
- GDVIRTUAL_BIND(_font_get_opentype_feature_overrides, "font_rid");
+ GDVIRTUAL_BIND(font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
- GDVIRTUAL_BIND(_font_supported_feature_list, "font_rid");
- GDVIRTUAL_BIND(_font_supported_variation_list, "font_rid");
+ GDVIRTUAL_BIND(font_has_char, "font_rid", "char");
+ GDVIRTUAL_BIND(font_get_supported_chars, "font_rid");
- GDVIRTUAL_BIND(_font_get_global_oversampling);
- GDVIRTUAL_BIND(_font_set_global_oversampling, "oversampling");
+ GDVIRTUAL_BIND(font_render_range, "font_rid", "size", "start", "end");
+ GDVIRTUAL_BIND(font_render_glyph, "font_rid", "size", "index");
- GDVIRTUAL_BIND(_get_hex_code_box_size, "size", "index");
- GDVIRTUAL_BIND(_draw_hex_code_box, "canvas", "size", "pos", "index", "color");
+ GDVIRTUAL_BIND(font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color");
+ GDVIRTUAL_BIND(font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color");
+
+ GDVIRTUAL_BIND(font_is_language_supported, "font_rid", "language");
+ GDVIRTUAL_BIND(font_set_language_support_override, "font_rid", "language", "supported");
+ GDVIRTUAL_BIND(font_get_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(font_remove_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(font_get_language_support_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(font_is_script_supported, "font_rid", "script");
+ GDVIRTUAL_BIND(font_set_script_support_override, "font_rid", "script", "supported");
+ GDVIRTUAL_BIND(font_get_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(font_remove_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(font_get_script_support_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(font_set_opentype_feature_overrides, "font_rid", "overrides");
+ GDVIRTUAL_BIND(font_get_opentype_feature_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(font_supported_feature_list, "font_rid");
+ GDVIRTUAL_BIND(font_supported_variation_list, "font_rid");
+
+ GDVIRTUAL_BIND(font_get_global_oversampling);
+ GDVIRTUAL_BIND(font_set_global_oversampling, "oversampling");
+
+ GDVIRTUAL_BIND(get_hex_code_box_size, "size", "index");
+ GDVIRTUAL_BIND(draw_hex_code_box, "canvas", "size", "pos", "index", "color");
/* Shaped text buffer interface */
- GDVIRTUAL_BIND(_create_shaped_text, "direction", "orientation");
+ GDVIRTUAL_BIND(create_shaped_text, "direction", "orientation");
+
+ GDVIRTUAL_BIND(shaped_text_clear, "shaped");
+
+ GDVIRTUAL_BIND(shaped_text_set_direction, "shaped", "direction");
+ GDVIRTUAL_BIND(shaped_text_get_direction, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_inferred_direction, "shaped");
- GDVIRTUAL_BIND(_shaped_text_clear, "shaped");
+ GDVIRTUAL_BIND(shaped_text_set_bidi_override, "shaped", "override");
- GDVIRTUAL_BIND(_shaped_text_set_direction, "shaped", "direction");
- GDVIRTUAL_BIND(_shaped_text_get_direction, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_inferred_direction, "shaped");
+ GDVIRTUAL_BIND(shaped_text_set_custom_punctuation, "shaped", "punct");
+ GDVIRTUAL_BIND(shaped_text_get_custom_punctuation, "shaped");
- GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override");
+ GDVIRTUAL_BIND(shaped_text_set_orientation, "shaped", "orientation");
+ GDVIRTUAL_BIND(shaped_text_get_orientation, "shaped");
- GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct");
- GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped");
+ GDVIRTUAL_BIND(shaped_text_set_preserve_invalid, "shaped", "enabled");
+ GDVIRTUAL_BIND(shaped_text_get_preserve_invalid, "shaped");
- GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation");
- GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped");
+ GDVIRTUAL_BIND(shaped_text_set_preserve_control, "shaped", "enabled");
+ GDVIRTUAL_BIND(shaped_text_get_preserve_control, "shaped");
- GDVIRTUAL_BIND(_shaped_text_set_preserve_invalid, "shaped", "enabled");
- GDVIRTUAL_BIND(_shaped_text_get_preserve_invalid, "shaped");
+ GDVIRTUAL_BIND(shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta");
+ GDVIRTUAL_BIND(shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
+ GDVIRTUAL_BIND(shaped_text_resize_object, "shaped", "key", "size", "inline_align");
- GDVIRTUAL_BIND(_shaped_text_set_preserve_control, "shaped", "enabled");
- GDVIRTUAL_BIND(_shaped_text_get_preserve_control, "shaped");
+ GDVIRTUAL_BIND(shaped_get_span_count, "shaped");
+ GDVIRTUAL_BIND(shaped_get_span_meta, "shaped", "index");
+ GDVIRTUAL_BIND(shaped_set_span_update_font, "shaped", "index", "fonts", "size", "opentype_features");
- GDVIRTUAL_BIND(_shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta");
- GDVIRTUAL_BIND(_shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
- GDVIRTUAL_BIND(_shaped_text_resize_object, "shaped", "key", "size", "inline_align");
+ GDVIRTUAL_BIND(shaped_text_substr, "shaped", "start", "length");
+ GDVIRTUAL_BIND(shaped_text_get_parent, "shaped");
- GDVIRTUAL_BIND(_shaped_get_span_count, "shaped");
- GDVIRTUAL_BIND(_shaped_get_span_meta, "shaped", "index");
- GDVIRTUAL_BIND(_shaped_set_span_update_font, "shaped", "index", "fonts", "size", "opentype_features");
+ GDVIRTUAL_BIND(shaped_text_fit_to_width, "shaped", "width", "jst_flags");
+ GDVIRTUAL_BIND(shaped_text_tab_align, "shaped", "tab_stops");
- GDVIRTUAL_BIND(_shaped_text_substr, "shaped", "start", "length");
- GDVIRTUAL_BIND(_shaped_text_get_parent, "shaped");
+ GDVIRTUAL_BIND(shaped_text_shape, "shaped");
+ GDVIRTUAL_BIND(shaped_text_update_breaks, "shaped");
+ GDVIRTUAL_BIND(shaped_text_update_justification_ops, "shaped");
- GDVIRTUAL_BIND(_shaped_text_fit_to_width, "shaped", "width", "jst_flags");
- GDVIRTUAL_BIND(_shaped_text_tab_align, "shaped", "tab_stops");
+ GDVIRTUAL_BIND(shaped_text_is_ready, "shaped");
- GDVIRTUAL_BIND(_shaped_text_shape, "shaped");
- GDVIRTUAL_BIND(_shaped_text_update_breaks, "shaped");
- GDVIRTUAL_BIND(_shaped_text_update_justification_ops, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_glyphs, "shaped");
+ GDVIRTUAL_BIND(shaped_text_sort_logical, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_glyph_count, "shaped");
- GDVIRTUAL_BIND(_shaped_text_is_ready, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_range, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped");
- GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_glyph_count, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags");
+ GDVIRTUAL_BIND(shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags");
+ GDVIRTUAL_BIND(shaped_text_get_word_breaks, "shaped", "grapheme_flags");
- GDVIRTUAL_BIND(_shaped_text_get_range, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_trim_pos, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_ellipsis_pos, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_ellipsis_glyph_count, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_ellipsis_glyphs, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags");
- GDVIRTUAL_BIND(_shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags");
- GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags");
+ GDVIRTUAL_BIND(shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags");
- GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyph_count, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_objects, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_object_rect, "shaped", "key");
- GDVIRTUAL_BIND(_shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags");
+ GDVIRTUAL_BIND(shaped_text_get_size, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_ascent, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_descent, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_width, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_underline_position, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_underline_thickness, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_objects, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_object_rect, "shaped", "key");
+ GDVIRTUAL_BIND(shaped_text_get_dominant_direction_in_range, "shaped", "start", "end");
- GDVIRTUAL_BIND(_shaped_text_get_size, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_ascent, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_descent, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_width, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_underline_position, "shaped");
- GDVIRTUAL_BIND(_shaped_text_get_underline_thickness, "shaped");
+ GDVIRTUAL_BIND(shaped_text_get_carets, "shaped", "position", "caret");
+ GDVIRTUAL_BIND(shaped_text_get_selection, "shaped", "start", "end");
- GDVIRTUAL_BIND(_shaped_text_get_dominant_direction_in_range, "shaped", "start", "end");
+ GDVIRTUAL_BIND(shaped_text_hit_test_grapheme, "shaped", "coord");
+ GDVIRTUAL_BIND(shaped_text_hit_test_position, "shaped", "coord");
- GDVIRTUAL_BIND(_shaped_text_get_carets, "shaped", "position", "caret");
- GDVIRTUAL_BIND(_shaped_text_get_selection, "shaped", "start", "end");
+ GDVIRTUAL_BIND(shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
+ GDVIRTUAL_BIND(shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
- GDVIRTUAL_BIND(_shaped_text_hit_test_grapheme, "shaped", "coord");
- GDVIRTUAL_BIND(_shaped_text_hit_test_position, "shaped", "coord");
+ GDVIRTUAL_BIND(shaped_text_get_grapheme_bounds, "shaped", "pos");
+ GDVIRTUAL_BIND(shaped_text_next_grapheme_pos, "shaped", "pos");
+ GDVIRTUAL_BIND(shaped_text_prev_grapheme_pos, "shaped", "pos");
- GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
- GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
+ GDVIRTUAL_BIND(format_number, "string", "language");
+ GDVIRTUAL_BIND(parse_number, "string", "language");
+ GDVIRTUAL_BIND(percent_sign, "language");
- GDVIRTUAL_BIND(_shaped_text_get_grapheme_bounds, "shaped", "pos");
- GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos");
- GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos");
+ GDVIRTUAL_BIND(strip_diacritics, "string");
- GDVIRTUAL_BIND(_format_number, "string", "language");
- GDVIRTUAL_BIND(_parse_number, "string", "language");
- GDVIRTUAL_BIND(_percent_sign, "language");
+ GDVIRTUAL_BIND(string_get_word_breaks, "string", "language");
- GDVIRTUAL_BIND(_string_to_upper, "string", "language");
- GDVIRTUAL_BIND(_string_to_lower, "string", "language");
+ GDVIRTUAL_BIND(string_to_upper, "string", "language");
+ GDVIRTUAL_BIND(string_to_lower, "string", "language");
+
+ GDVIRTUAL_BIND(parse_structured_text, "parser_type", "args", "text");
}
bool TextServerExtension::has_feature(Feature p_feature) const {
bool ret;
- if (GDVIRTUAL_CALL(_has_feature, p_feature, ret)) {
+ if (GDVIRTUAL_CALL(has_feature, p_feature, ret)) {
return ret;
}
return false;
@@ -293,27 +316,27 @@ bool TextServerExtension::has_feature(Feature p_feature) const {
String TextServerExtension::get_name() const {
String ret;
- if (GDVIRTUAL_CALL(_get_name, ret)) {
+ if (GDVIRTUAL_CALL(get_name, ret)) {
return ret;
}
return "Unknown";
}
-uint32_t TextServerExtension::get_features() const {
- uint32_t ret;
- if (GDVIRTUAL_CALL(_get_features, ret)) {
+int64_t TextServerExtension::get_features() const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(get_features, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::free(RID p_rid) {
- GDVIRTUAL_CALL(_free, p_rid);
+void TextServerExtension::free_rid(const RID &p_rid) {
+ GDVIRTUAL_CALL(free_rid, p_rid);
}
-bool TextServerExtension::has(RID p_rid) {
+bool TextServerExtension::has(const RID &p_rid) {
bool ret;
- if (GDVIRTUAL_CALL(_has, p_rid, ret)) {
+ if (GDVIRTUAL_CALL(has, p_rid, ret)) {
return ret;
}
return false;
@@ -321,7 +344,7 @@ bool TextServerExtension::has(RID p_rid) {
bool TextServerExtension::load_support_data(const String &p_filename) {
bool ret;
- if (GDVIRTUAL_CALL(_load_support_data, p_filename, ret)) {
+ if (GDVIRTUAL_CALL(load_support_data, p_filename, ret)) {
return ret;
}
return false;
@@ -329,7 +352,7 @@ bool TextServerExtension::load_support_data(const String &p_filename) {
String TextServerExtension::get_support_data_filename() const {
String ret;
- if (GDVIRTUAL_CALL(_get_support_data_filename, ret)) {
+ if (GDVIRTUAL_CALL(get_support_data_filename, ret)) {
return ret;
}
return String();
@@ -337,7 +360,7 @@ String TextServerExtension::get_support_data_filename() const {
String TextServerExtension::get_support_data_info() const {
String ret;
- if (GDVIRTUAL_CALL(_get_support_data_info, ret)) {
+ if (GDVIRTUAL_CALL(get_support_data_info, ret)) {
return ret;
}
return String();
@@ -345,7 +368,7 @@ String TextServerExtension::get_support_data_info() const {
bool TextServerExtension::save_support_data(const String &p_filename) const {
bool ret;
- if (GDVIRTUAL_CALL(_save_support_data, p_filename, ret)) {
+ if (GDVIRTUAL_CALL(save_support_data, p_filename, ret)) {
return ret;
}
return false;
@@ -353,23 +376,23 @@ bool TextServerExtension::save_support_data(const String &p_filename) const {
bool TextServerExtension::is_locale_right_to_left(const String &p_locale) const {
bool ret;
- if (GDVIRTUAL_CALL(_is_locale_right_to_left, p_locale, ret)) {
+ if (GDVIRTUAL_CALL(is_locale_right_to_left, p_locale, ret)) {
return ret;
}
return false;
}
-int32_t TextServerExtension::name_to_tag(const String &p_name) const {
- int32_t ret;
- if (GDVIRTUAL_CALL(_name_to_tag, p_name, ret)) {
+int64_t TextServerExtension::name_to_tag(const String &p_name) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(name_to_tag, p_name, ret)) {
return ret;
}
return 0;
}
-String TextServerExtension::tag_to_name(int32_t p_tag) const {
+String TextServerExtension::tag_to_name(int64_t p_tag) const {
String ret;
- if (GDVIRTUAL_CALL(_tag_to_name, p_tag, ret)) {
+ if (GDVIRTUAL_CALL(tag_to_name, p_tag, ret)) {
return ret;
}
return "";
@@ -381,570 +404,642 @@ String TextServerExtension::tag_to_name(int32_t p_tag) const {
RID TextServerExtension::create_font() {
RID ret;
- if (GDVIRTUAL_CALL(_create_font, ret)) {
+ if (GDVIRTUAL_CALL(create_font, ret)) {
return ret;
}
return RID();
}
-void TextServerExtension::font_set_data(RID p_font_rid, const PackedByteArray &p_data) {
- GDVIRTUAL_CALL(_font_set_data, p_font_rid, p_data);
+void TextServerExtension::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) {
+ GDVIRTUAL_CALL(font_set_data, p_font_rid, p_data);
}
-void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) {
- GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
+void TextServerExtension::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) {
+ GDVIRTUAL_CALL(font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
}
-void TextServerExtension::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) {
- GDVIRTUAL_CALL(_font_set_style, p_font_rid, p_style);
+void TextServerExtension::font_set_face_index(const RID &p_font_rid, int64_t p_index) {
+ GDVIRTUAL_CALL(font_set_face_index, p_font_rid, p_index);
}
-uint32_t /*FontStyle*/ TextServerExtension::font_get_style(RID p_font_rid) const {
- uint32_t ret;
- if (GDVIRTUAL_CALL(_font_get_style, p_font_rid, ret)) {
+int64_t TextServerExtension::font_get_face_index(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_face_index, p_font_rid, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::font_set_style_name(RID p_font_rid, const String &p_name) {
- GDVIRTUAL_CALL(_font_set_style_name, p_font_rid, p_name);
+int64_t TextServerExtension::font_get_face_count(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_face_count, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
+ GDVIRTUAL_CALL(font_set_style, p_font_rid, p_style);
+}
+
+int64_t /*FontStyle*/ TextServerExtension::font_get_style(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_style, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
}
-String TextServerExtension::font_get_style_name(RID p_font_rid) const {
+void TextServerExtension::font_set_style_name(const RID &p_font_rid, const String &p_name) {
+ GDVIRTUAL_CALL(font_set_style_name, p_font_rid, p_name);
+}
+
+String TextServerExtension::font_get_style_name(const RID &p_font_rid) const {
String ret;
- if (GDVIRTUAL_CALL(_font_get_style_name, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_style_name, p_font_rid, ret)) {
return ret;
}
return String();
}
-void TextServerExtension::font_set_name(RID p_font_rid, const String &p_name) {
- GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name);
+void TextServerExtension::font_set_name(const RID &p_font_rid, const String &p_name) {
+ GDVIRTUAL_CALL(font_set_name, p_font_rid, p_name);
}
-String TextServerExtension::font_get_name(RID p_font_rid) const {
+String TextServerExtension::font_get_name(const RID &p_font_rid) const {
String ret;
- if (GDVIRTUAL_CALL(_font_get_name, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_name, p_font_rid, ret)) {
return ret;
}
return String();
}
-void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) {
- GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased);
+void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) {
+ GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased);
+}
+
+bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
+ GDVIRTUAL_CALL(font_set_generate_mipmaps, p_font_rid, p_generate_mipmaps);
}
-bool TextServerExtension::font_is_antialiased(RID p_font_rid) const {
+bool TextServerExtension::font_get_generate_mipmaps(const RID &p_font_rid) const {
bool ret;
- if (GDVIRTUAL_CALL(_font_is_antialiased, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_generate_mipmaps, p_font_rid, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) {
- GDVIRTUAL_CALL(_font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
+void TextServerExtension::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
+ GDVIRTUAL_CALL(font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
}
-bool TextServerExtension::font_is_multichannel_signed_distance_field(RID p_font_rid) const {
+bool TextServerExtension::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const {
bool ret;
- if (GDVIRTUAL_CALL(_font_is_multichannel_signed_distance_field, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_is_multichannel_signed_distance_field, p_font_rid, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) {
- GDVIRTUAL_CALL(_font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range);
+void TextServerExtension::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) {
+ GDVIRTUAL_CALL(font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range);
}
-int TextServerExtension::font_get_msdf_pixel_range(RID p_font_rid) const {
- int ret;
- if (GDVIRTUAL_CALL(_font_get_msdf_pixel_range, p_font_rid, ret)) {
+int64_t TextServerExtension::font_get_msdf_pixel_range(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_msdf_pixel_range, p_font_rid, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::font_set_msdf_size(RID p_font_rid, int p_msdf_size) {
- GDVIRTUAL_CALL(_font_set_msdf_size, p_font_rid, p_msdf_size);
+void TextServerExtension::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) {
+ GDVIRTUAL_CALL(font_set_msdf_size, p_font_rid, p_msdf_size);
}
-int TextServerExtension::font_get_msdf_size(RID p_font_rid) const {
- int ret;
- if (GDVIRTUAL_CALL(_font_get_msdf_size, p_font_rid, ret)) {
+int64_t TextServerExtension::font_get_msdf_size(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_msdf_size, p_font_rid, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::font_set_fixed_size(RID p_font_rid, int p_fixed_size) {
- GDVIRTUAL_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size);
+void TextServerExtension::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) {
+ GDVIRTUAL_CALL(font_set_fixed_size, p_font_rid, p_fixed_size);
}
-int TextServerExtension::font_get_fixed_size(RID p_font_rid) const {
- int ret;
- if (GDVIRTUAL_CALL(_font_get_fixed_size, p_font_rid, ret)) {
+int64_t TextServerExtension::font_get_fixed_size(const RID &p_font_rid) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_fixed_size, p_font_rid, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) {
- GDVIRTUAL_CALL(_font_set_force_autohinter, p_font_rid, p_force_autohinter);
+void TextServerExtension::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
+ GDVIRTUAL_CALL(font_set_force_autohinter, p_font_rid, p_force_autohinter);
}
-bool TextServerExtension::font_is_force_autohinter(RID p_font_rid) const {
+bool TextServerExtension::font_is_force_autohinter(const RID &p_font_rid) const {
bool ret;
- if (GDVIRTUAL_CALL(_font_is_force_autohinter, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_is_force_autohinter, p_font_rid, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) {
- GDVIRTUAL_CALL(_font_set_hinting, p_font_rid, p_hinting);
+void TextServerExtension::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
+ GDVIRTUAL_CALL(font_set_hinting, p_font_rid, p_hinting);
}
-TextServer::Hinting TextServerExtension::font_get_hinting(RID p_font_rid) const {
+TextServer::Hinting TextServerExtension::font_get_hinting(const RID &p_font_rid) const {
TextServer::Hinting ret;
- if (GDVIRTUAL_CALL(_font_get_hinting, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_hinting, p_font_rid, ret)) {
return (TextServer::Hinting)ret;
}
return TextServer::Hinting::HINTING_NONE;
}
-void TextServerExtension::font_set_subpixel_positioning(RID p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
- GDVIRTUAL_CALL(_font_set_subpixel_positioning, p_font_rid, p_subpixel);
+void TextServerExtension::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
+ GDVIRTUAL_CALL(font_set_subpixel_positioning, p_font_rid, p_subpixel);
}
-TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioning(RID p_font_rid) const {
+TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioning(const RID &p_font_rid) const {
TextServer::SubpixelPositioning ret;
- if (GDVIRTUAL_CALL(_font_get_subpixel_positioning, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_subpixel_positioning, p_font_rid, ret)) {
return (TextServer::SubpixelPositioning)ret;
}
return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED;
}
-void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
- GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
+void TextServerExtension::font_set_embolden(const RID &p_font_rid, double p_strength) {
+ GDVIRTUAL_CALL(font_set_embolden, p_font_rid, p_strength);
+}
+
+double TextServerExtension::font_get_embolden(const RID &p_font_rid) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_embolden, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0.0;
+}
+
+void TextServerExtension::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) {
+ GDVIRTUAL_CALL(font_set_transform, p_font_rid, p_transform);
+}
+
+Transform2D TextServerExtension::font_get_transform(const RID &p_font_rid) const {
+ Transform2D ret;
+ if (GDVIRTUAL_CALL(font_get_transform, p_font_rid, ret)) {
+ return ret;
+ }
+ return Transform2D();
}
-Dictionary TextServerExtension::font_get_variation_coordinates(RID p_font_rid) const {
+void TextServerExtension::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) {
+ GDVIRTUAL_CALL(font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
+}
+
+Dictionary TextServerExtension::font_get_variation_coordinates(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(_font_get_variation_coordinates, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_variation_coordinates, p_font_rid, ret)) {
return ret;
}
return Dictionary();
}
-void TextServerExtension::font_set_oversampling(RID p_font_rid, float p_oversampling) {
- GDVIRTUAL_CALL(_font_set_oversampling, p_font_rid, p_oversampling);
+void TextServerExtension::font_set_oversampling(const RID &p_font_rid, double p_oversampling) {
+ GDVIRTUAL_CALL(font_set_oversampling, p_font_rid, p_oversampling);
}
-float TextServerExtension::font_get_oversampling(RID p_font_rid) const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_oversampling, p_font_rid, ret)) {
+double TextServerExtension::font_get_oversampling(const RID &p_font_rid) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_oversampling, p_font_rid, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-Array TextServerExtension::font_get_size_cache_list(RID p_font_rid) const {
+Array TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const {
Array ret;
- if (GDVIRTUAL_CALL(_font_get_size_cache_list, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_size_cache_list, p_font_rid, ret)) {
return ret;
}
return Array();
}
-void TextServerExtension::font_clear_size_cache(RID p_font_rid) {
- GDVIRTUAL_CALL(_font_clear_size_cache, p_font_rid);
+void TextServerExtension::font_clear_size_cache(const RID &p_font_rid) {
+ GDVIRTUAL_CALL(font_clear_size_cache, p_font_rid);
}
-void TextServerExtension::font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(_font_remove_size_cache, p_font_rid, p_size);
+void TextServerExtension::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(font_remove_size_cache, p_font_rid, p_size);
}
-void TextServerExtension::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) {
- GDVIRTUAL_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent);
+void TextServerExtension::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) {
+ GDVIRTUAL_CALL(font_set_ascent, p_font_rid, p_size, p_ascent);
}
-float TextServerExtension::font_get_ascent(RID p_font_rid, int p_size) const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_ascent, p_font_rid, p_size, ret)) {
+double TextServerExtension::font_get_ascent(const RID &p_font_rid, int64_t p_size) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_ascent, p_font_rid, p_size, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-void TextServerExtension::font_set_descent(RID p_font_rid, int p_size, float p_descent) {
- GDVIRTUAL_CALL(_font_set_descent, p_font_rid, p_size, p_descent);
+void TextServerExtension::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) {
+ GDVIRTUAL_CALL(font_set_descent, p_font_rid, p_size, p_descent);
}
-float TextServerExtension::font_get_descent(RID p_font_rid, int p_size) const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_descent, p_font_rid, p_size, ret)) {
+double TextServerExtension::font_get_descent(const RID &p_font_rid, int64_t p_size) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_descent, p_font_rid, p_size, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-void TextServerExtension::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) {
- GDVIRTUAL_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position);
+void TextServerExtension::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) {
+ GDVIRTUAL_CALL(font_set_underline_position, p_font_rid, p_size, p_underline_position);
}
-float TextServerExtension::font_get_underline_position(RID p_font_rid, int p_size) const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_underline_position, p_font_rid, p_size, ret)) {
+double TextServerExtension::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_underline_position, p_font_rid, p_size, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-void TextServerExtension::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) {
- GDVIRTUAL_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
+void TextServerExtension::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) {
+ GDVIRTUAL_CALL(font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
}
-float TextServerExtension::font_get_underline_thickness(RID p_font_rid, int p_size) const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret)) {
+double TextServerExtension::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_underline_thickness, p_font_rid, p_size, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-void TextServerExtension::font_set_scale(RID p_font_rid, int p_size, float p_scale) {
- GDVIRTUAL_CALL(_font_set_scale, p_font_rid, p_size, p_scale);
+void TextServerExtension::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) {
+ GDVIRTUAL_CALL(font_set_scale, p_font_rid, p_size, p_scale);
}
-float TextServerExtension::font_get_scale(RID p_font_rid, int p_size) const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_scale, p_font_rid, p_size, ret)) {
+double TextServerExtension::font_get_scale(const RID &p_font_rid, int64_t p_size) const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_scale, p_font_rid, p_size, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-void TextServerExtension::font_set_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing, int p_value) {
- GDVIRTUAL_CALL(_font_set_spacing, p_font_rid, p_size, p_spacing, p_value);
+void TextServerExtension::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) {
+ GDVIRTUAL_CALL(font_set_spacing, p_font_rid, p_size, p_spacing, p_value);
}
-int TextServerExtension::font_get_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing) const {
- int ret;
- if (GDVIRTUAL_CALL(_font_get_spacing, p_font_rid, p_size, p_spacing, ret)) {
+int64_t TextServerExtension::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_spacing, p_font_rid, p_size, p_spacing, ret)) {
return ret;
}
return 0;
}
-int TextServerExtension::font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const {
- int ret;
- if (GDVIRTUAL_CALL(_font_get_texture_count, p_font_rid, p_size, ret)) {
+int64_t TextServerExtension::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_texture_count, p_font_rid, p_size, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::font_clear_textures(RID p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(_font_clear_textures, p_font_rid, p_size);
+void TextServerExtension::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(font_clear_textures, p_font_rid, p_size);
}
-void TextServerExtension::font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) {
- GDVIRTUAL_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index);
+void TextServerExtension::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) {
+ GDVIRTUAL_CALL(font_remove_texture, p_font_rid, p_size, p_texture_index);
}
-void TextServerExtension::font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
- GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
+void TextServerExtension::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) {
+ GDVIRTUAL_CALL(font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
}
-Ref<Image> TextServerExtension::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
+Ref<Image> TextServerExtension::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
Ref<Image> ret;
- if (GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) {
+ if (GDVIRTUAL_CALL(font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) {
return ret;
}
return Ref<Image>();
}
-void TextServerExtension::font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
- GDVIRTUAL_CALL(_font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset);
+void TextServerExtension::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) {
+ GDVIRTUAL_CALL(font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset);
}
-PackedInt32Array TextServerExtension::font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
+PackedInt32Array TextServerExtension::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(_font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) {
+ if (GDVIRTUAL_CALL(font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) {
return ret;
}
return PackedInt32Array();
}
-Array TextServerExtension::font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const {
+Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
Array ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_list, p_font_rid, p_size, ret)) {
+ if (GDVIRTUAL_CALL(font_get_glyph_list, p_font_rid, p_size, ret)) {
return ret;
}
return Array();
}
-void TextServerExtension::font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(_font_clear_glyphs, p_font_rid, p_size);
+void TextServerExtension::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(font_clear_glyphs, p_font_rid, p_size);
}
-void TextServerExtension::font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) {
- GDVIRTUAL_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph);
+void TextServerExtension::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) {
+ GDVIRTUAL_CALL(font_remove_glyph, p_font_rid, p_size, p_glyph);
}
-Vector2 TextServerExtension::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const {
+Vector2 TextServerExtension::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) {
+ if (GDVIRTUAL_CALL(font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) {
return ret;
}
return Vector2();
}
-void TextServerExtension::font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
- GDVIRTUAL_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
+void TextServerExtension::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) {
+ GDVIRTUAL_CALL(font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
}
-Vector2 TextServerExtension::font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+Vector2 TextServerExtension::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) {
+ if (GDVIRTUAL_CALL(font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) {
return ret;
}
return Vector2();
}
-void TextServerExtension::font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
- GDVIRTUAL_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
+void TextServerExtension::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) {
+ GDVIRTUAL_CALL(font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
}
-Vector2 TextServerExtension::font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+Vector2 TextServerExtension::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) {
+ if (GDVIRTUAL_CALL(font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) {
return ret;
}
return Vector2();
}
-void TextServerExtension::font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
- GDVIRTUAL_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
+void TextServerExtension::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) {
+ GDVIRTUAL_CALL(font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
}
-Rect2 TextServerExtension::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+Rect2 TextServerExtension::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Rect2 ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) {
+ if (GDVIRTUAL_CALL(font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) {
return ret;
}
return Rect2();
}
-void TextServerExtension::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
- GDVIRTUAL_CALL(_font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
+void TextServerExtension::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) {
+ GDVIRTUAL_CALL(font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
}
-int TextServerExtension::font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
- int ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) {
+int64_t TextServerExtension::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) {
return ret;
}
return 0;
}
-void TextServerExtension::font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
- GDVIRTUAL_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
+void TextServerExtension::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) {
+ GDVIRTUAL_CALL(font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
+}
+
+RID TextServerExtension::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ RID ret;
+ if (GDVIRTUAL_CALL(font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return RID();
}
-Dictionary TextServerExtension::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const {
+Size2 TextServerExtension::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ Size2 ret;
+ if (GDVIRTUAL_CALL(font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Size2();
+}
+
+Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) {
+ if (GDVIRTUAL_CALL(font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) {
return ret;
}
return Dictionary();
}
-Array TextServerExtension::font_get_kerning_list(RID p_font_rid, int p_size) const {
+Array TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
Array ret;
- if (GDVIRTUAL_CALL(_font_get_kerning_list, p_font_rid, p_size, ret)) {
+ if (GDVIRTUAL_CALL(font_get_kerning_list, p_font_rid, p_size, ret)) {
return ret;
}
return Array();
}
-void TextServerExtension::font_clear_kerning_map(RID p_font_rid, int p_size) {
- GDVIRTUAL_CALL(_font_clear_kerning_map, p_font_rid, p_size);
+void TextServerExtension::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) {
+ GDVIRTUAL_CALL(font_clear_kerning_map, p_font_rid, p_size);
}
-void TextServerExtension::font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) {
- GDVIRTUAL_CALL(_font_remove_kerning, p_font_rid, p_size, p_glyph_pair);
+void TextServerExtension::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) {
+ GDVIRTUAL_CALL(font_remove_kerning, p_font_rid, p_size, p_glyph_pair);
}
-void TextServerExtension::font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
- GDVIRTUAL_CALL(_font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning);
+void TextServerExtension::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
+ GDVIRTUAL_CALL(font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning);
}
-Vector2 TextServerExtension::font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const {
+Vector2 TextServerExtension::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(_font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) {
+ if (GDVIRTUAL_CALL(font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) {
return ret;
}
return Vector2();
}
-int32_t TextServerExtension::font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const {
- int32_t ret;
- if (GDVIRTUAL_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) {
+int64_t TextServerExtension::font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) {
return ret;
}
return 0;
}
-bool TextServerExtension::font_has_char(RID p_font_rid, char32_t p_char) const {
+bool TextServerExtension::font_has_char(const RID &p_font_rid, int64_t p_char) const {
bool ret;
- if (GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret)) {
+ if (GDVIRTUAL_CALL(font_has_char, p_font_rid, p_char, ret)) {
return ret;
}
return false;
}
-String TextServerExtension::font_get_supported_chars(RID p_font_rid) const {
+String TextServerExtension::font_get_supported_chars(const RID &p_font_rid) const {
String ret;
- if (GDVIRTUAL_CALL(_font_get_supported_chars, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_supported_chars, p_font_rid, ret)) {
return ret;
}
return String();
}
-void TextServerExtension::font_render_range(RID p_font_rid, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
- GDVIRTUAL_CALL(_font_render_range, p_font_rid, p_size, p_start, p_end);
+void TextServerExtension::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) {
+ GDVIRTUAL_CALL(font_render_range, p_font_rid, p_size, p_start, p_end);
}
-void TextServerExtension::font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) {
- GDVIRTUAL_CALL(_font_render_glyph, p_font_rid, p_size, p_index);
+void TextServerExtension::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) {
+ GDVIRTUAL_CALL(font_render_glyph, p_font_rid, p_size, p_index);
}
-void TextServerExtension::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
- GDVIRTUAL_CALL(_font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
+void TextServerExtension::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
+ GDVIRTUAL_CALL(font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
}
-void TextServerExtension::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
- GDVIRTUAL_CALL(_font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
+void TextServerExtension::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
+ GDVIRTUAL_CALL(font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
}
-bool TextServerExtension::font_is_language_supported(RID p_font_rid, const String &p_language) const {
+bool TextServerExtension::font_is_language_supported(const RID &p_font_rid, const String &p_language) const {
bool ret;
- if (GDVIRTUAL_CALL(_font_is_language_supported, p_font_rid, p_language, ret)) {
+ if (GDVIRTUAL_CALL(font_is_language_supported, p_font_rid, p_language, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) {
- GDVIRTUAL_CALL(_font_set_language_support_override, p_font_rid, p_language, p_supported);
+void TextServerExtension::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) {
+ GDVIRTUAL_CALL(font_set_language_support_override, p_font_rid, p_language, p_supported);
}
-bool TextServerExtension::font_get_language_support_override(RID p_font_rid, const String &p_language) {
+bool TextServerExtension::font_get_language_support_override(const RID &p_font_rid, const String &p_language) {
bool ret;
- if (GDVIRTUAL_CALL(_font_get_language_support_override, p_font_rid, p_language, ret)) {
+ if (GDVIRTUAL_CALL(font_get_language_support_override, p_font_rid, p_language, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_remove_language_support_override(RID p_font_rid, const String &p_language) {
- GDVIRTUAL_CALL(_font_remove_language_support_override, p_font_rid, p_language);
+void TextServerExtension::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) {
+ GDVIRTUAL_CALL(font_remove_language_support_override, p_font_rid, p_language);
}
-Vector<String> TextServerExtension::font_get_language_support_overrides(RID p_font_rid) {
- Vector<String> ret;
- if (GDVIRTUAL_CALL(_font_get_language_support_overrides, p_font_rid, ret)) {
+PackedStringArray TextServerExtension::font_get_language_support_overrides(const RID &p_font_rid) {
+ PackedStringArray ret;
+ if (GDVIRTUAL_CALL(font_get_language_support_overrides, p_font_rid, ret)) {
return ret;
}
- return Vector<String>();
+ return PackedStringArray();
}
-bool TextServerExtension::font_is_script_supported(RID p_font_rid, const String &p_script) const {
+bool TextServerExtension::font_is_script_supported(const RID &p_font_rid, const String &p_script) const {
bool ret;
- if (GDVIRTUAL_CALL(_font_is_script_supported, p_font_rid, p_script, ret)) {
+ if (GDVIRTUAL_CALL(font_is_script_supported, p_font_rid, p_script, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) {
- GDVIRTUAL_CALL(_font_set_script_support_override, p_font_rid, p_script, p_supported);
+void TextServerExtension::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) {
+ GDVIRTUAL_CALL(font_set_script_support_override, p_font_rid, p_script, p_supported);
}
-bool TextServerExtension::font_get_script_support_override(RID p_font_rid, const String &p_script) {
+bool TextServerExtension::font_get_script_support_override(const RID &p_font_rid, const String &p_script) {
bool ret;
- if (GDVIRTUAL_CALL(_font_get_script_support_override, p_font_rid, p_script, ret)) {
+ if (GDVIRTUAL_CALL(font_get_script_support_override, p_font_rid, p_script, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::font_remove_script_support_override(RID p_font_rid, const String &p_script) {
- GDVIRTUAL_CALL(_font_remove_script_support_override, p_font_rid, p_script);
+void TextServerExtension::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) {
+ GDVIRTUAL_CALL(font_remove_script_support_override, p_font_rid, p_script);
}
-Vector<String> TextServerExtension::font_get_script_support_overrides(RID p_font_rid) {
- Vector<String> ret;
- if (GDVIRTUAL_CALL(_font_get_script_support_overrides, p_font_rid, ret)) {
+PackedStringArray TextServerExtension::font_get_script_support_overrides(const RID &p_font_rid) {
+ PackedStringArray ret;
+ if (GDVIRTUAL_CALL(font_get_script_support_overrides, p_font_rid, ret)) {
return ret;
}
- return Vector<String>();
+ return PackedStringArray();
}
-void TextServerExtension::font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) {
- GDVIRTUAL_CALL(_font_set_opentype_feature_overrides, p_font_rid, p_overrides);
+void TextServerExtension::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) {
+ GDVIRTUAL_CALL(font_set_opentype_feature_overrides, p_font_rid, p_overrides);
}
-Dictionary TextServerExtension::font_get_opentype_feature_overrides(RID p_font_rid) const {
+Dictionary TextServerExtension::font_get_opentype_feature_overrides(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(_font_get_opentype_feature_overrides, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_get_opentype_feature_overrides, p_font_rid, ret)) {
return ret;
}
return Dictionary();
}
-Dictionary TextServerExtension::font_supported_feature_list(RID p_font_rid) const {
+Dictionary TextServerExtension::font_supported_feature_list(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(_font_supported_feature_list, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_supported_feature_list, p_font_rid, ret)) {
return ret;
}
return Dictionary();
}
-Dictionary TextServerExtension::font_supported_variation_list(RID p_font_rid) const {
+Dictionary TextServerExtension::font_supported_variation_list(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(_font_supported_variation_list, p_font_rid, ret)) {
+ if (GDVIRTUAL_CALL(font_supported_variation_list, p_font_rid, ret)) {
return ret;
}
return Dictionary();
}
-float TextServerExtension::font_get_global_oversampling() const {
- float ret;
- if (GDVIRTUAL_CALL(_font_get_global_oversampling, ret)) {
+double TextServerExtension::font_get_global_oversampling() const {
+ double ret;
+ if (GDVIRTUAL_CALL(font_get_global_oversampling, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-void TextServerExtension::font_set_global_oversampling(float p_oversampling) {
- GDVIRTUAL_CALL(_font_set_global_oversampling, p_oversampling);
+void TextServerExtension::font_set_global_oversampling(double p_oversampling) {
+ GDVIRTUAL_CALL(font_set_global_oversampling, p_oversampling);
}
-Vector2 TextServerExtension::get_hex_code_box_size(int p_size, char32_t p_index) const {
+Vector2 TextServerExtension::get_hex_code_box_size(int64_t p_size, int64_t p_index) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(_get_hex_code_box_size, p_size, p_index, ret)) {
+ if (GDVIRTUAL_CALL(get_hex_code_box_size, p_size, p_index, ret)) {
return ret;
}
return TextServer::get_hex_code_box_size(p_size, p_index);
}
-void TextServerExtension::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const {
- if (!GDVIRTUAL_CALL(_draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) {
+void TextServerExtension::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
+ if (!GDVIRTUAL_CALL(draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) {
TextServer::draw_hex_code_box(p_canvas, p_size, p_pos, p_index, p_color);
}
}
@@ -955,433 +1050,425 @@ void TextServerExtension::draw_hex_code_box(RID p_canvas, int p_size, const Vect
RID TextServerExtension::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
RID ret;
- if (GDVIRTUAL_CALL(_create_shaped_text, p_direction, p_orientation, ret)) {
+ if (GDVIRTUAL_CALL(create_shaped_text, p_direction, p_orientation, ret)) {
return ret;
}
return RID();
}
-void TextServerExtension::shaped_text_clear(RID p_shaped) {
- GDVIRTUAL_CALL(_shaped_text_clear, p_shaped);
+void TextServerExtension::shaped_text_clear(const RID &p_shaped) {
+ GDVIRTUAL_CALL(shaped_text_clear, p_shaped);
}
-void TextServerExtension::shaped_text_set_direction(RID p_shaped, TextServer::Direction p_direction) {
- GDVIRTUAL_CALL(_shaped_text_set_direction, p_shaped, p_direction);
+void TextServerExtension::shaped_text_set_direction(const RID &p_shaped, TextServer::Direction p_direction) {
+ GDVIRTUAL_CALL(shaped_text_set_direction, p_shaped, p_direction);
}
-TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shaped) const {
+TextServer::Direction TextServerExtension::shaped_text_get_direction(const RID &p_shaped) const {
TextServer::Direction ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_direction, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_direction, p_shaped, ret)) {
return (TextServer::Direction)ret;
}
return TextServer::Direction::DIRECTION_AUTO;
}
-TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(RID p_shaped) const {
+TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(const RID &p_shaped) const {
TextServer::Direction ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_inferred_direction, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_inferred_direction, p_shaped, ret)) {
return (TextServer::Direction)ret;
}
return TextServer::Direction::DIRECTION_LTR;
}
-void TextServerExtension::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
- GDVIRTUAL_CALL(_shaped_text_set_orientation, p_shaped, p_orientation);
+void TextServerExtension::shaped_text_set_orientation(const RID &p_shaped, TextServer::Orientation p_orientation) {
+ GDVIRTUAL_CALL(shaped_text_set_orientation, p_shaped, p_orientation);
}
-TextServer::Orientation TextServerExtension::shaped_text_get_orientation(RID p_shaped) const {
+TextServer::Orientation TextServerExtension::shaped_text_get_orientation(const RID &p_shaped) const {
TextServer::Orientation ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_orientation, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_orientation, p_shaped, ret)) {
return (TextServer::Orientation)ret;
}
return TextServer::Orientation::ORIENTATION_HORIZONTAL;
}
-void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
- GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override);
+void TextServerExtension::shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) {
+ GDVIRTUAL_CALL(shaped_text_set_bidi_override, p_shaped, p_override);
}
-void TextServerExtension::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) {
- GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct);
+void TextServerExtension::shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) {
+ GDVIRTUAL_CALL(shaped_text_set_custom_punctuation, p_shaped, p_punct);
}
-String TextServerExtension::shaped_text_get_custom_punctuation(RID p_shaped) const {
+String TextServerExtension::shaped_text_get_custom_punctuation(const RID &p_shaped) const {
String ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_custom_punctuation, p_shaped, ret)) {
return ret;
}
return String();
}
-void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
- GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
+void TextServerExtension::shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) {
+ GDVIRTUAL_CALL(shaped_text_set_preserve_invalid, p_shaped, p_enabled);
}
-bool TextServerExtension::shaped_text_get_preserve_invalid(RID p_shaped) const {
+bool TextServerExtension::shaped_text_get_preserve_invalid(const RID &p_shaped) const {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_preserve_invalid, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_preserve_invalid, p_shaped, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) {
- GDVIRTUAL_CALL(_shaped_text_set_preserve_control, p_shaped, p_enabled);
+void TextServerExtension::shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) {
+ GDVIRTUAL_CALL(shaped_text_set_preserve_control, p_shaped, p_enabled);
}
-bool TextServerExtension::shaped_text_get_preserve_control(RID p_shaped) const {
+bool TextServerExtension::shaped_text_get_preserve_control(const RID &p_shaped) const {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_preserve_control, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_preserve_control, p_shaped, ret)) {
return ret;
}
return false;
}
-bool TextServerExtension::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
+bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
bool ret;
- Array fonts;
- for (int i = 0; i < p_fonts.size(); i++) {
- fonts.push_back(p_fonts[i]);
- }
- if (GDVIRTUAL_CALL(_shaped_text_add_string, p_shaped, p_text, fonts, p_size, p_opentype_features, p_language, p_meta, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret)) {
return ret;
}
return false;
}
-bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) {
+bool TextServerExtension::shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length) {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) {
return ret;
}
return false;
}
-bool TextServerExtension::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
+bool TextServerExtension::shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) {
return ret;
}
return false;
}
-int TextServerExtension::shaped_get_span_count(RID p_shaped) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_get_span_count, p_shaped, ret)) {
+int64_t TextServerExtension::shaped_get_span_count(const RID &p_shaped) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_get_span_count, p_shaped, ret)) {
return ret;
}
return 0;
}
-Variant TextServerExtension::shaped_get_span_meta(RID p_shaped, int p_index) const {
+Variant TextServerExtension::shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const {
Variant ret;
- if (GDVIRTUAL_CALL(_shaped_get_span_meta, p_shaped, p_index, ret)) {
+ if (GDVIRTUAL_CALL(shaped_get_span_meta, p_shaped, p_index, ret)) {
return ret;
}
return false;
}
-void TextServerExtension::shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features) {
- Array fonts;
- for (int i = 0; i < p_fonts.size(); i++) {
- fonts.push_back(p_fonts[i]);
- }
- GDVIRTUAL_CALL(_shaped_set_span_update_font, p_shaped, p_index, fonts, p_size, p_opentype_features);
+void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) {
+ GDVIRTUAL_CALL(shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features);
}
-RID TextServerExtension::shaped_text_substr(RID p_shaped, int p_start, int p_length) const {
+RID TextServerExtension::shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const {
RID ret;
- if (GDVIRTUAL_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_substr, p_shaped, p_start, p_length, ret)) {
return ret;
}
return RID();
}
-RID TextServerExtension::shaped_text_get_parent(RID p_shaped) const {
+RID TextServerExtension::shaped_text_get_parent(const RID &p_shaped) const {
RID ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_parent, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_parent, p_shaped, ret)) {
return ret;
}
return RID();
}
-float TextServerExtension::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t p_jst_flags) {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) {
+double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t p_jst_flags) {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-float TextServerExtension::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_tab_align, p_shaped, p_tab_stops, ret)) {
+double TextServerExtension::shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_tab_align, p_shaped, p_tab_stops, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-bool TextServerExtension::shaped_text_shape(RID p_shaped) {
+bool TextServerExtension::shaped_text_shape(const RID &p_shaped) {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_shape, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_shape, p_shaped, ret)) {
return ret;
}
return false;
}
-bool TextServerExtension::shaped_text_update_breaks(RID p_shaped) {
+bool TextServerExtension::shaped_text_update_breaks(const RID &p_shaped) {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_update_breaks, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_update_breaks, p_shaped, ret)) {
return ret;
}
return false;
}
-bool TextServerExtension::shaped_text_update_justification_ops(RID p_shaped) {
+bool TextServerExtension::shaped_text_update_justification_ops(const RID &p_shaped) {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_update_justification_ops, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_update_justification_ops, p_shaped, ret)) {
return ret;
}
return false;
}
-bool TextServerExtension::shaped_text_is_ready(RID p_shaped) const {
+bool TextServerExtension::shaped_text_is_ready(const RID &p_shaped) const {
bool ret;
- if (GDVIRTUAL_CALL(_shaped_text_is_ready, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_is_ready, p_shaped, ret)) {
return ret;
}
return false;
}
-const Glyph *TextServerExtension::shaped_text_get_glyphs(RID p_shaped) const {
- GDNativePtr<Glyph> ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, ret)) {
+const Glyph *TextServerExtension::shaped_text_get_glyphs(const RID &p_shaped) const {
+ GDNativeConstPtr<const Glyph> ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_glyphs, p_shaped, ret)) {
return ret;
}
return nullptr;
}
-const Glyph *TextServerExtension::shaped_text_sort_logical(RID p_shaped) {
- GDNativePtr<Glyph> ret;
- if (GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, ret)) {
+const Glyph *TextServerExtension::shaped_text_sort_logical(const RID &p_shaped) {
+ GDNativeConstPtr<const Glyph> ret;
+ if (GDVIRTUAL_CALL(shaped_text_sort_logical, p_shaped, ret)) {
return ret;
}
return nullptr;
}
-int TextServerExtension::shaped_text_get_glyph_count(RID p_shaped) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_glyph_count, p_shaped, ret)) {
+int64_t TextServerExtension::shaped_text_get_glyph_count(const RID &p_shaped) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_glyph_count, p_shaped, ret)) {
return ret;
}
return 0;
}
-Vector2i TextServerExtension::shaped_text_get_range(RID p_shaped) const {
+Vector2i TextServerExtension::shaped_text_get_range(const RID &p_shaped) const {
Vector2i ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_range, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_range, p_shaped, ret)) {
return ret;
}
return Vector2i();
}
-PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t p_break_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t p_break_flags) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
return ret;
}
return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
}
-PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t p_break_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t p_break_flags) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
return ret;
}
return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
}
-PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
return ret;
}
return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags);
}
-int TextServerExtension::shaped_text_get_trim_pos(RID p_shaped) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_trim_pos, p_shaped, ret)) {
+int64_t TextServerExtension::shaped_text_get_trim_pos(const RID &p_shaped) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_trim_pos, p_shaped, ret)) {
return ret;
}
return -1;
}
-int TextServerExtension::shaped_text_get_ellipsis_pos(RID p_shaped) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret)) {
+int64_t TextServerExtension::shaped_text_get_ellipsis_pos(const RID &p_shaped) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_pos, p_shaped, ret)) {
return ret;
}
return -1;
}
-const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(RID p_shaped) const {
- GDNativePtr<Glyph> ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret)) {
+const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const {
+ GDNativeConstPtr<const Glyph> ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_glyphs, p_shaped, ret)) {
return ret;
}
return nullptr;
}
-int TextServerExtension::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) {
+int64_t TextServerExtension::shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) {
return ret;
}
return -1;
}
-void TextServerExtension::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) {
- GDVIRTUAL_CALL(_shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
+void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) {
+ GDVIRTUAL_CALL(shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
}
-Array TextServerExtension::shaped_text_get_objects(RID p_shaped) const {
+Array TextServerExtension::shaped_text_get_objects(const RID &p_shaped) const {
Array ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_objects, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_objects, p_shaped, ret)) {
return ret;
}
return Array();
}
-Rect2 TextServerExtension::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const {
+Rect2 TextServerExtension::shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const {
Rect2 ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_object_rect, p_shaped, p_key, ret)) {
return ret;
}
return Rect2();
}
-Size2 TextServerExtension::shaped_text_get_size(RID p_shaped) const {
+Size2 TextServerExtension::shaped_text_get_size(const RID &p_shaped) const {
Size2 ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_size, p_shaped, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_size, p_shaped, ret)) {
return ret;
}
return Size2();
}
-float TextServerExtension::shaped_text_get_ascent(RID p_shaped) const {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_ascent, p_shaped, ret)) {
+double TextServerExtension::shaped_text_get_ascent(const RID &p_shaped) const {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_ascent, p_shaped, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-float TextServerExtension::shaped_text_get_descent(RID p_shaped) const {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_descent, p_shaped, ret)) {
+double TextServerExtension::shaped_text_get_descent(const RID &p_shaped) const {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_descent, p_shaped, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-float TextServerExtension::shaped_text_get_width(RID p_shaped) const {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_width, p_shaped, ret)) {
+double TextServerExtension::shaped_text_get_width(const RID &p_shaped) const {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_width, p_shaped, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-float TextServerExtension::shaped_text_get_underline_position(RID p_shaped) const {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_underline_position, p_shaped, ret)) {
+double TextServerExtension::shaped_text_get_underline_position(const RID &p_shaped) const {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_underline_position, p_shaped, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-float TextServerExtension::shaped_text_get_underline_thickness(RID p_shaped) const {
- float ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_underline_thickness, p_shaped, ret)) {
+double TextServerExtension::shaped_text_get_underline_thickness(const RID &p_shaped) const {
+ double ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_underline_thickness, p_shaped, ret)) {
return ret;
}
- return 0.f;
+ return 0.0;
}
-TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) {
+TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) {
return (TextServer::Direction)ret;
}
return TextServer::shaped_text_get_dominant_direction_in_range(p_shaped, p_start, p_end);
}
-CaretInfo TextServerExtension::shaped_text_get_carets(RID p_shaped, int p_position) const {
+CaretInfo TextServerExtension::shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const {
CaretInfo ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_carets, p_shaped, p_position, &ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_carets, p_shaped, p_position, &ret)) {
return ret;
}
return TextServer::shaped_text_get_carets(p_shaped, p_position);
}
-Vector<Vector2> TextServerExtension::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
+Vector<Vector2> TextServerExtension::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
Vector<Vector2> ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_selection, p_shaped, p_start, p_end, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_selection, p_shaped, p_start, p_end, ret)) {
return ret;
}
return TextServer::shaped_text_get_selection(p_shaped, p_start, p_end);
}
-int TextServerExtension::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) {
+int64_t TextServerExtension::shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) {
return ret;
}
return TextServer::shaped_text_hit_test_grapheme(p_shaped, p_coords);
}
-int TextServerExtension::shaped_text_hit_test_position(RID p_shaped, float p_coords) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_hit_test_position, p_shaped, p_coords, ret)) {
+int64_t TextServerExtension::shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_hit_test_position, p_shaped, p_coords, ret)) {
return ret;
}
return TextServer::shaped_text_hit_test_position(p_shaped, p_coords);
}
-void TextServerExtension::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const {
- if (GDVIRTUAL_CALL(_shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) {
+void TextServerExtension::shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, const Color &p_color) const {
+ if (GDVIRTUAL_CALL(shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) {
return;
}
TextServer::shaped_text_draw(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color);
}
-void TextServerExtension::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
- if (GDVIRTUAL_CALL(_shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) {
+void TextServerExtension::shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, int64_t p_outline_size, const Color &p_color) const {
+ if (GDVIRTUAL_CALL(shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) {
return;
}
- shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color);
+ TextServer::shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color);
}
-Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const {
+Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(_shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) {
+ if (GDVIRTUAL_CALL(shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) {
return ret;
}
return TextServer::shaped_text_get_grapheme_bounds(p_shaped, p_pos);
}
-int TextServerExtension::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
+int64_t TextServerExtension::shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
return ret;
}
return TextServer::shaped_text_next_grapheme_pos(p_shaped, p_pos);
}
-int TextServerExtension::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
- int ret;
- if (GDVIRTUAL_CALL(_shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) {
+int64_t TextServerExtension::shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) {
return ret;
}
return TextServer::shaped_text_prev_grapheme_pos(p_shaped, p_pos);
@@ -1389,31 +1476,39 @@ int TextServerExtension::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos)
String TextServerExtension::format_number(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(format_number, p_string, p_language, ret)) {
return ret;
}
- return TextServer::format_number(p_string, p_language);
+ return p_string;
}
String TextServerExtension::parse_number(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(parse_number, p_string, p_language, ret)) {
return ret;
}
- return TextServer::parse_number(p_string, p_language);
+ return p_string;
}
String TextServerExtension::percent_sign(const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(_percent_sign, p_language, ret)) {
+ if (GDVIRTUAL_CALL(percent_sign, p_language, ret)) {
return ret;
}
- return TextServer::percent_sign(p_language);
+ return "%";
+}
+
+String TextServerExtension::strip_diacritics(const String &p_string) const {
+ String ret;
+ if (GDVIRTUAL_CALL(strip_diacritics, p_string, ret)) {
+ return ret;
+ }
+ return TextServer::strip_diacritics(p_string);
}
String TextServerExtension::string_to_upper(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(_string_to_upper, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(string_to_upper, p_string, p_language, ret)) {
return ret;
}
return p_string;
@@ -1421,12 +1516,28 @@ String TextServerExtension::string_to_upper(const String &p_string, const String
String TextServerExtension::string_to_lower(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(_string_to_lower, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(string_to_lower, p_string, p_language, ret)) {
return ret;
}
return p_string;
}
+Array TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(parse_structured_text, p_parser_type, p_args, p_text, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(string_get_word_breaks, p_string, p_language, ret)) {
+ return ret;
+ }
+ return PackedInt32Array();
+}
+
TextServerExtension::TextServerExtension() {
//NOP
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index d185e44806..9ca0939247 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -48,423 +48,461 @@ protected:
public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
- virtual uint32_t get_features() const override;
- GDVIRTUAL1RC(bool, _has_feature, Feature);
- GDVIRTUAL0RC(String, _get_name);
- GDVIRTUAL0RC(uint32_t, _get_features);
+ virtual int64_t get_features() const override;
+ GDVIRTUAL1RC(bool, has_feature, Feature);
+ GDVIRTUAL0RC(String, get_name);
+ GDVIRTUAL0RC(int64_t, get_features);
- virtual void free(RID p_rid) override;
- virtual bool has(RID p_rid) override;
+ virtual void free_rid(const RID &p_rid) override;
+ virtual bool has(const RID &p_rid) override;
virtual bool load_support_data(const String &p_filename) override;
- GDVIRTUAL1(_free, RID);
- GDVIRTUAL1R(bool, _has, RID);
- GDVIRTUAL1R(bool, _load_support_data, const String &);
+ GDVIRTUAL1(free_rid, RID);
+ GDVIRTUAL1R(bool, has, RID);
+ GDVIRTUAL1R(bool, load_support_data, const String &);
virtual String get_support_data_filename() const override;
virtual String get_support_data_info() const override;
virtual bool save_support_data(const String &p_filename) const override;
- GDVIRTUAL0RC(String, _get_support_data_filename);
- GDVIRTUAL0RC(String, _get_support_data_info);
- GDVIRTUAL1RC(bool, _save_support_data, const String &);
+ GDVIRTUAL0RC(String, get_support_data_filename);
+ GDVIRTUAL0RC(String, get_support_data_info);
+ GDVIRTUAL1RC(bool, save_support_data, const String &);
virtual bool is_locale_right_to_left(const String &p_locale) const override;
- GDVIRTUAL1RC(bool, _is_locale_right_to_left, const String &);
+ GDVIRTUAL1RC(bool, is_locale_right_to_left, const String &);
- virtual int32_t name_to_tag(const String &p_name) const override;
- virtual String tag_to_name(int32_t p_tag) const override;
- GDVIRTUAL1RC(int32_t, _name_to_tag, const String &);
- GDVIRTUAL1RC(String, _tag_to_name, int32_t);
+ virtual int64_t name_to_tag(const String &p_name) const override;
+ virtual String tag_to_name(int64_t p_tag) const override;
+ GDVIRTUAL1RC(int64_t, name_to_tag, const String &);
+ GDVIRTUAL1RC(String, tag_to_name, int64_t);
/* Font interface */
virtual RID create_font() override;
- GDVIRTUAL0R(RID, _create_font);
-
- virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override;
- virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override;
- GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &);
- GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t);
-
- virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override;
- virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_style, RID, uint32_t);
- GDVIRTUAL1RC(uint32_t, _font_get_style, RID);
-
- virtual void font_set_name(RID p_font_rid, const String &p_name) override;
- virtual String font_get_name(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_name, RID, const String &);
- GDVIRTUAL1RC(String, _font_get_name, RID);
-
- virtual void font_set_style_name(RID p_font_rid, const String &p_name) override;
- virtual String font_get_style_name(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_style_name, RID, const String &);
- GDVIRTUAL1RC(String, _font_get_style_name, RID);
-
- virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override;
- virtual bool font_is_antialiased(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_antialiased, RID, bool);
- GDVIRTUAL1RC(bool, _font_is_antialiased, RID);
-
- virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) override;
- virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_multichannel_signed_distance_field, RID, bool);
- GDVIRTUAL1RC(bool, _font_is_multichannel_signed_distance_field, RID);
-
- virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) override;
- virtual int font_get_msdf_pixel_range(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_msdf_pixel_range, RID, int);
- GDVIRTUAL1RC(int, _font_get_msdf_pixel_range, RID);
-
- virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) override;
- virtual int font_get_msdf_size(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_msdf_size, RID, int);
- GDVIRTUAL1RC(int, _font_get_msdf_size, RID);
-
- virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) override;
- virtual int font_get_fixed_size(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_fixed_size, RID, int);
- GDVIRTUAL1RC(int, _font_get_fixed_size, RID);
-
- virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) override;
- virtual bool font_is_force_autohinter(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_force_autohinter, RID, bool);
- GDVIRTUAL1RC(bool, _font_is_force_autohinter, RID);
-
- virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) override;
- virtual Hinting font_get_hinting(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_hinting, RID, Hinting);
- GDVIRTUAL1RC(Hinting, _font_get_hinting, RID);
-
- virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
- virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
- GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID);
-
- virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
- virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
- GDVIRTUAL1RC(Dictionary, _font_get_variation_coordinates, RID);
-
- virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override;
- virtual float font_get_oversampling(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_oversampling, RID, float);
- GDVIRTUAL1RC(float, _font_get_oversampling, RID);
-
- virtual Array font_get_size_cache_list(RID p_font_rid) const override;
- virtual void font_clear_size_cache(RID p_font_rid) override;
- virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override;
- GDVIRTUAL1RC(Array, _font_get_size_cache_list, RID);
- GDVIRTUAL1(_font_clear_size_cache, RID);
- GDVIRTUAL2(_font_remove_size_cache, RID, const Vector2i &);
-
- virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override;
- virtual float font_get_ascent(RID p_font_rid, int p_size) const override;
- GDVIRTUAL3(_font_set_ascent, RID, int, float);
- GDVIRTUAL2RC(float, _font_get_ascent, RID, int);
-
- virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override;
- virtual float font_get_descent(RID p_font_rid, int p_size) const override;
- GDVIRTUAL3(_font_set_descent, RID, int, float);
- GDVIRTUAL2RC(float, _font_get_descent, RID, int);
-
- virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override;
- virtual float font_get_underline_position(RID p_font_rid, int p_size) const override;
- GDVIRTUAL3(_font_set_underline_position, RID, int, float);
- GDVIRTUAL2RC(float, _font_get_underline_position, RID, int);
-
- virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override;
- virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override;
- GDVIRTUAL3(_font_set_underline_thickness, RID, int, float);
- GDVIRTUAL2RC(float, _font_get_underline_thickness, RID, int);
-
- virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override;
- virtual float font_get_scale(RID p_font_rid, int p_size) const override;
- GDVIRTUAL3(_font_set_scale, RID, int, float);
- GDVIRTUAL2RC(float, _font_get_scale, RID, int);
-
- virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override;
- virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override;
- GDVIRTUAL4(_font_set_spacing, RID, int, SpacingType, int);
- GDVIRTUAL3RC(int, _font_get_spacing, RID, int, SpacingType);
-
- virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const override;
- virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) override;
- virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) override;
- GDVIRTUAL2RC(int, _font_get_texture_count, RID, const Vector2i &);
- GDVIRTUAL2(_font_clear_textures, RID, const Vector2i &);
- GDVIRTUAL3(_font_remove_texture, RID, const Vector2i &, int);
-
- virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) override;
- virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
- GDVIRTUAL4(_font_set_texture_image, RID, const Vector2i &, int, const Ref<Image> &);
- GDVIRTUAL3RC(Ref<Image>, _font_get_texture_image, RID, const Vector2i &, int);
-
- virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) override;
- virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
- GDVIRTUAL4(_font_set_texture_offsets, RID, const Vector2i &, int, const PackedInt32Array &);
- GDVIRTUAL3RC(PackedInt32Array, _font_get_texture_offsets, RID, const Vector2i &, int);
-
- virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const override;
- virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) override;
- virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) override;
- GDVIRTUAL2RC(Array, _font_get_glyph_list, RID, const Vector2i &);
- GDVIRTUAL2(_font_clear_glyphs, RID, const Vector2i &);
- GDVIRTUAL3(_font_remove_glyph, RID, const Vector2i &, int32_t);
-
- virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const override;
- virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) override;
- GDVIRTUAL3RC(Vector2, _font_get_glyph_advance, RID, int, int32_t);
- GDVIRTUAL4(_font_set_glyph_advance, RID, int, int32_t, const Vector2 &);
-
- virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
- virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) override;
- GDVIRTUAL3RC(Vector2, _font_get_glyph_offset, RID, const Vector2i &, int32_t);
- GDVIRTUAL4(_font_set_glyph_offset, RID, const Vector2i &, int32_t, const Vector2 &);
-
- virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
- virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) override;
- GDVIRTUAL3RC(Vector2, _font_get_glyph_size, RID, const Vector2i &, int32_t);
- GDVIRTUAL4(_font_set_glyph_size, RID, const Vector2i &, int32_t, const Vector2 &);
-
- virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
- virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) override;
- GDVIRTUAL3RC(Rect2, _font_get_glyph_uv_rect, RID, const Vector2i &, int32_t);
- GDVIRTUAL4(_font_set_glyph_uv_rect, RID, const Vector2i &, int32_t, const Rect2 &);
-
- virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
- virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override;
- GDVIRTUAL3RC(int, _font_get_glyph_texture_idx, RID, const Vector2i &, int32_t);
- GDVIRTUAL4(_font_set_glyph_texture_idx, RID, const Vector2i &, int32_t, int);
-
- virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override;
- GDVIRTUAL3RC(Dictionary, _font_get_glyph_contours, RID, int, int32_t);
-
- virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override;
- virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override;
- virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) override;
- GDVIRTUAL2RC(Array, _font_get_kerning_list, RID, int);
- GDVIRTUAL2(_font_clear_kerning_map, RID, int);
- GDVIRTUAL3(_font_remove_kerning, RID, int, const Vector2i &);
-
- virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override;
- virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const override;
- GDVIRTUAL4(_font_set_kerning, RID, int, const Vector2i &, const Vector2 &);
- GDVIRTUAL3RC(Vector2, _font_get_kerning, RID, int, const Vector2i &);
-
- virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector = 0) const override;
- GDVIRTUAL4RC(int32_t, _font_get_glyph_index, RID, int, char32_t, char32_t);
-
- virtual bool font_has_char(RID p_font_rid, char32_t p_char) const override;
- virtual String font_get_supported_chars(RID p_font_rid) const override;
- GDVIRTUAL2RC(bool, _font_has_char, RID, char32_t);
- GDVIRTUAL1RC(String, _font_get_supported_chars, RID);
-
- virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) override;
- virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) override;
- GDVIRTUAL4(_font_render_range, RID, const Vector2i &, char32_t, char32_t);
- GDVIRTUAL3(_font_render_glyph, RID, const Vector2i &, int32_t);
-
- virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
- virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
- GDVIRTUAL6C(_font_draw_glyph, RID, RID, int, const Vector2 &, int32_t, const Color &);
- GDVIRTUAL7C(_font_draw_glyph_outline, RID, RID, int, int, const Vector2 &, int32_t, const Color &);
-
- virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const override;
- virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) override;
- virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) override;
- virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) override;
- virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) override;
- GDVIRTUAL2RC(bool, _font_is_language_supported, RID, const String &);
- GDVIRTUAL3(_font_set_language_support_override, RID, const String &, bool);
- GDVIRTUAL2R(bool, _font_get_language_support_override, RID, const String &);
- GDVIRTUAL2(_font_remove_language_support_override, RID, const String &);
- GDVIRTUAL1R(Vector<String>, _font_get_language_support_overrides, RID);
-
- virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const override;
- virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) override;
- virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) override;
- virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) override;
- virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) override;
- GDVIRTUAL2RC(bool, _font_is_script_supported, RID, const String &);
- GDVIRTUAL3(_font_set_script_support_override, RID, const String &, bool);
- GDVIRTUAL2R(bool, _font_get_script_support_override, RID, const String &);
- GDVIRTUAL2(_font_remove_script_support_override, RID, const String &);
- GDVIRTUAL1R(Vector<String>, _font_get_script_support_overrides, RID);
-
- virtual void font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) override;
- virtual Dictionary font_get_opentype_feature_overrides(RID p_font_rid) const override;
- GDVIRTUAL2(_font_set_opentype_feature_overrides, RID, const Dictionary &);
- GDVIRTUAL1RC(Dictionary, _font_get_opentype_feature_overrides, RID);
-
- virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
- virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
- GDVIRTUAL1RC(Dictionary, _font_supported_feature_list, RID);
- GDVIRTUAL1RC(Dictionary, _font_supported_variation_list, RID);
-
- virtual float font_get_global_oversampling() const override;
- virtual void font_set_global_oversampling(float p_oversampling) override;
- GDVIRTUAL0RC(float, _font_get_global_oversampling);
- GDVIRTUAL1(_font_set_global_oversampling, float);
-
- virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const override;
- virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const override;
- GDVIRTUAL2RC(Vector2, _get_hex_code_box_size, int, char32_t);
- GDVIRTUAL5C(_draw_hex_code_box, RID, int, const Vector2 &, char32_t, const Color &);
+ GDVIRTUAL0R(RID, create_font);
+
+ virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) override;
+ virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) override;
+ GDVIRTUAL2(font_set_data, RID, const PackedByteArray &);
+ GDVIRTUAL3(font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, int64_t);
+
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) override;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_face_index, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, font_get_face_index, RID);
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(int64_t, font_get_face_count, RID);
+
+ virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
+ virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_style, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, font_get_style, RID);
+
+ virtual void font_set_name(const RID &p_font_rid, const String &p_name) override;
+ virtual String font_get_name(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_name, RID, const String &);
+ GDVIRTUAL1RC(String, font_get_name, RID);
+
+ virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override;
+ virtual String font_get_style_name(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_style_name, RID, const String &);
+ GDVIRTUAL1RC(String, font_get_style_name, RID);
+
+ virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override;
+ virtual bool font_is_antialiased(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_antialiased, RID, bool);
+ GDVIRTUAL1RC(bool, font_is_antialiased, RID);
+
+ virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
+ virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_generate_mipmaps, RID, bool);
+ GDVIRTUAL1RC(bool, font_get_generate_mipmaps, RID);
+
+ virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override;
+ virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_multichannel_signed_distance_field, RID, bool);
+ GDVIRTUAL1RC(bool, font_is_multichannel_signed_distance_field, RID);
+
+ virtual void font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) override;
+ virtual int64_t font_get_msdf_pixel_range(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_msdf_pixel_range, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, font_get_msdf_pixel_range, RID);
+
+ virtual void font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) override;
+ virtual int64_t font_get_msdf_size(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_msdf_size, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, font_get_msdf_size, RID);
+
+ virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) override;
+ virtual int64_t font_get_fixed_size(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_fixed_size, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, font_get_fixed_size, RID);
+
+ virtual void font_set_subpixel_positioning(const RID &p_font_rid, SubpixelPositioning p_subpixel) override;
+ virtual SubpixelPositioning font_get_subpixel_positioning(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_subpixel_positioning, RID, SubpixelPositioning);
+ GDVIRTUAL1RC(SubpixelPositioning, font_get_subpixel_positioning, RID);
+
+ virtual void font_set_embolden(const RID &p_font_rid, double p_strength) override;
+ virtual double font_get_embolden(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_embolden, RID, double);
+ GDVIRTUAL1RC(double, font_get_embolden, RID);
+
+ virtual void font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) override;
+ virtual Transform2D font_get_transform(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_transform, RID, Transform2D);
+ GDVIRTUAL1RC(Transform2D, font_get_transform, RID);
+
+ virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) override;
+ virtual bool font_is_force_autohinter(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_force_autohinter, RID, bool);
+ GDVIRTUAL1RC(bool, font_is_force_autohinter, RID);
+
+ virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) override;
+ virtual Hinting font_get_hinting(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_hinting, RID, Hinting);
+ GDVIRTUAL1RC(Hinting, font_get_hinting, RID);
+
+ virtual void font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) override;
+ virtual Dictionary font_get_variation_coordinates(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_variation_coordinates, RID, Dictionary);
+ GDVIRTUAL1RC(Dictionary, font_get_variation_coordinates, RID);
+
+ virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) override;
+ virtual double font_get_oversampling(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_oversampling, RID, double);
+ GDVIRTUAL1RC(double, font_get_oversampling, RID);
+
+ virtual Array font_get_size_cache_list(const RID &p_font_rid) const override;
+ virtual void font_clear_size_cache(const RID &p_font_rid) override;
+ virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) override;
+ GDVIRTUAL1RC(Array, font_get_size_cache_list, RID);
+ GDVIRTUAL1(font_clear_size_cache, RID);
+ GDVIRTUAL2(font_remove_size_cache, RID, const Vector2i &);
+
+ virtual void font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) override;
+ virtual double font_get_ascent(const RID &p_font_rid, int64_t p_size) const override;
+ GDVIRTUAL3(font_set_ascent, RID, int64_t, double);
+ GDVIRTUAL2RC(double, font_get_ascent, RID, int64_t);
+
+ virtual void font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) override;
+ virtual double font_get_descent(const RID &p_font_rid, int64_t p_size) const override;
+ GDVIRTUAL3(font_set_descent, RID, int64_t, double);
+ GDVIRTUAL2RC(double, font_get_descent, RID, int64_t);
+
+ virtual void font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) override;
+ virtual double font_get_underline_position(const RID &p_font_rid, int64_t p_size) const override;
+ GDVIRTUAL3(font_set_underline_position, RID, int64_t, double);
+ GDVIRTUAL2RC(double, font_get_underline_position, RID, int64_t);
+
+ virtual void font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) override;
+ virtual double font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const override;
+ GDVIRTUAL3(font_set_underline_thickness, RID, int64_t, double);
+ GDVIRTUAL2RC(double, font_get_underline_thickness, RID, int64_t);
+
+ virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override;
+ virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override;
+ GDVIRTUAL3(font_set_scale, RID, int64_t, double);
+ GDVIRTUAL2RC(double, font_get_scale, RID, int64_t);
+
+ virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
+ virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
+ GDVIRTUAL4(font_set_spacing, RID, int64_t, SpacingType, int64_t);
+ GDVIRTUAL3RC(int64_t, font_get_spacing, RID, int64_t, SpacingType);
+
+ virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
+ virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
+ virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
+ GDVIRTUAL2RC(int64_t, font_get_texture_count, RID, const Vector2i &);
+ GDVIRTUAL2(font_clear_textures, RID, const Vector2i &);
+ GDVIRTUAL3(font_remove_texture, RID, const Vector2i &, int64_t);
+
+ virtual void font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) override;
+ virtual Ref<Image> font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override;
+ GDVIRTUAL4(font_set_texture_image, RID, const Vector2i &, int64_t, const Ref<Image> &);
+ GDVIRTUAL3RC(Ref<Image>, font_get_texture_image, RID, const Vector2i &, int64_t);
+
+ virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) override;
+ virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override;
+ GDVIRTUAL4(font_set_texture_offsets, RID, const Vector2i &, int64_t, const PackedInt32Array &);
+ GDVIRTUAL3RC(PackedInt32Array, font_get_texture_offsets, RID, const Vector2i &, int64_t);
+
+ virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override;
+ virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) override;
+ virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) override;
+ GDVIRTUAL2RC(Array, font_get_glyph_list, RID, const Vector2i &);
+ GDVIRTUAL2(font_clear_glyphs, RID, const Vector2i &);
+ GDVIRTUAL3(font_remove_glyph, RID, const Vector2i &, int64_t);
+
+ virtual Vector2 font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const override;
+ virtual void font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) override;
+ GDVIRTUAL3RC(Vector2, font_get_glyph_advance, RID, int64_t, int64_t);
+ GDVIRTUAL4(font_set_glyph_advance, RID, int64_t, int64_t, const Vector2 &);
+
+ virtual Vector2 font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ virtual void font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) override;
+ GDVIRTUAL3RC(Vector2, font_get_glyph_offset, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(font_set_glyph_offset, RID, const Vector2i &, int64_t, const Vector2 &);
+
+ virtual Vector2 font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ virtual void font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) override;
+ GDVIRTUAL3RC(Vector2, font_get_glyph_size, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(font_set_glyph_size, RID, const Vector2i &, int64_t, const Vector2 &);
+
+ virtual Rect2 font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ virtual void font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) override;
+ GDVIRTUAL3RC(Rect2, font_get_glyph_uv_rect, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(font_set_glyph_uv_rect, RID, const Vector2i &, int64_t, const Rect2 &);
+
+ virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override;
+ GDVIRTUAL3RC(int64_t, font_get_glyph_texture_idx, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(font_set_glyph_texture_idx, RID, const Vector2i &, int64_t, int64_t);
+
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ GDVIRTUAL3RC(RID, font_get_glyph_texture_rid, RID, const Vector2i &, int64_t);
+
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ GDVIRTUAL3RC(Size2, font_get_glyph_texture_size, RID, const Vector2i &, int64_t);
+
+ virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override;
+ GDVIRTUAL3RC(Dictionary, font_get_glyph_contours, RID, int64_t, int64_t);
+
+ virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override;
+ virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) override;
+ virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) override;
+ GDVIRTUAL2RC(Array, font_get_kerning_list, RID, int64_t);
+ GDVIRTUAL2(font_clear_kerning_map, RID, int64_t);
+ GDVIRTUAL3(font_remove_kerning, RID, int64_t, const Vector2i &);
+
+ virtual void font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override;
+ virtual Vector2 font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const override;
+ GDVIRTUAL4(font_set_kerning, RID, int64_t, const Vector2i &, const Vector2 &);
+ GDVIRTUAL3RC(Vector2, font_get_kerning, RID, int64_t, const Vector2i &);
+
+ virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector = 0) const override;
+ GDVIRTUAL4RC(int64_t, font_get_glyph_index, RID, int64_t, int64_t, int64_t);
+
+ virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const override;
+ virtual String font_get_supported_chars(const RID &p_font_rid) const override;
+ GDVIRTUAL2RC(bool, font_has_char, RID, int64_t);
+ GDVIRTUAL1RC(String, font_get_supported_chars, RID);
+
+ virtual void font_render_range(const RID &p_font, const Vector2i &p_size, int64_t p_start, int64_t p_end) override;
+ virtual void font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) override;
+ GDVIRTUAL4(font_render_range, RID, const Vector2i &, int64_t, int64_t);
+ GDVIRTUAL3(font_render_glyph, RID, const Vector2i &, int64_t);
+
+ virtual void font_draw_glyph(const RID &p_font, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual void font_draw_glyph_outline(const RID &p_font, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ GDVIRTUAL6C(font_draw_glyph, RID, RID, int64_t, const Vector2 &, int64_t, const Color &);
+ GDVIRTUAL7C(font_draw_glyph_outline, RID, RID, int64_t, int64_t, const Vector2 &, int64_t, const Color &);
+
+ virtual bool font_is_language_supported(const RID &p_font_rid, const String &p_language) const override;
+ virtual void font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) override;
+ virtual bool font_get_language_support_override(const RID &p_font_rid, const String &p_language) override;
+ virtual void font_remove_language_support_override(const RID &p_font_rid, const String &p_language) override;
+ virtual PackedStringArray font_get_language_support_overrides(const RID &p_font_rid) override;
+ GDVIRTUAL2RC(bool, font_is_language_supported, RID, const String &);
+ GDVIRTUAL3(font_set_language_support_override, RID, const String &, bool);
+ GDVIRTUAL2R(bool, font_get_language_support_override, RID, const String &);
+ GDVIRTUAL2(font_remove_language_support_override, RID, const String &);
+ GDVIRTUAL1R(PackedStringArray, font_get_language_support_overrides, RID);
+
+ virtual bool font_is_script_supported(const RID &p_font_rid, const String &p_script) const override;
+ virtual void font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) override;
+ virtual bool font_get_script_support_override(const RID &p_font_rid, const String &p_script) override;
+ virtual void font_remove_script_support_override(const RID &p_font_rid, const String &p_script) override;
+ virtual PackedStringArray font_get_script_support_overrides(const RID &p_font_rid) override;
+ GDVIRTUAL2RC(bool, font_is_script_supported, RID, const String &);
+ GDVIRTUAL3(font_set_script_support_override, RID, const String &, bool);
+ GDVIRTUAL2R(bool, font_get_script_support_override, RID, const String &);
+ GDVIRTUAL2(font_remove_script_support_override, RID, const String &);
+ GDVIRTUAL1R(PackedStringArray, font_get_script_support_overrides, RID);
+
+ virtual void font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) override;
+ virtual Dictionary font_get_opentype_feature_overrides(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_opentype_feature_overrides, RID, const Dictionary &);
+ GDVIRTUAL1RC(Dictionary, font_get_opentype_feature_overrides, RID);
+
+ virtual Dictionary font_supported_feature_list(const RID &p_font_rid) const override;
+ virtual Dictionary font_supported_variation_list(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(Dictionary, font_supported_feature_list, RID);
+ GDVIRTUAL1RC(Dictionary, font_supported_variation_list, RID);
+
+ virtual double font_get_global_oversampling() const override;
+ virtual void font_set_global_oversampling(double p_oversampling) override;
+ GDVIRTUAL0RC(double, font_get_global_oversampling);
+ GDVIRTUAL1(font_set_global_oversampling, double);
+
+ virtual Vector2 get_hex_code_box_size(int64_t p_size, int64_t p_index) const override;
+ virtual void draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override;
+ GDVIRTUAL2RC(Vector2, get_hex_code_box_size, int64_t, int64_t);
+ GDVIRTUAL5C(draw_hex_code_box, RID, int64_t, const Vector2 &, int64_t, const Color &);
/* Shaped text buffer interface */
virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
- GDVIRTUAL2R(RID, _create_shaped_text, Direction, Orientation);
-
- virtual void shaped_text_clear(RID p_shaped) override;
- GDVIRTUAL1(_shaped_text_clear, RID);
-
- virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
- virtual Direction shaped_text_get_direction(RID p_shaped) const override;
- virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const override;
- GDVIRTUAL2(_shaped_text_set_direction, RID, Direction);
- GDVIRTUAL1RC(Direction, _shaped_text_get_direction, RID);
- GDVIRTUAL1RC(Direction, _shaped_text_get_inferred_direction, RID);
-
- virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
- GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &);
-
- virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override;
- virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override;
- GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String);
- GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID);
-
- virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
- virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
- GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);
- GDVIRTUAL1RC(Orientation, _shaped_text_get_orientation, RID);
-
- virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) override;
- virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const override;
- GDVIRTUAL2(_shaped_text_set_preserve_invalid, RID, bool);
- GDVIRTUAL1RC(bool, _shaped_text_get_preserve_invalid, RID);
-
- virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) override;
- virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
- GDVIRTUAL2(_shaped_text_set_preserve_control, RID, bool);
- GDVIRTUAL1RC(bool, _shaped_text_get_preserve_control, RID);
-
- virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) override;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
- GDVIRTUAL7R(bool, _shaped_text_add_string, RID, const String &, const Array &, int, const Dictionary &, const String &, const Variant &);
- GDVIRTUAL5R(bool, _shaped_text_add_object, RID, Variant, const Size2 &, InlineAlignment, int);
- GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, Variant, const Size2 &, InlineAlignment);
-
- virtual int shaped_get_span_count(RID p_shaped) const override;
- virtual Variant shaped_get_span_meta(RID p_shaped, int p_index) const override;
- virtual void shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary()) override;
- GDVIRTUAL1RC(int, _shaped_get_span_count, RID);
- GDVIRTUAL2RC(Variant, _shaped_get_span_meta, RID, int);
- GDVIRTUAL5(_shaped_set_span_update_font, RID, int, const Array &, int, const Dictionary &);
-
- virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
- virtual RID shaped_text_get_parent(RID p_shaped) const override;
- GDVIRTUAL3RC(RID, _shaped_text_substr, RID, int, int);
- GDVIRTUAL1RC(RID, _shaped_text_get_parent, RID);
-
- virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
- virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override;
- GDVIRTUAL3R(float, _shaped_text_fit_to_width, RID, float, uint16_t);
- GDVIRTUAL2R(float, _shaped_text_tab_align, RID, const PackedFloat32Array &);
-
- virtual bool shaped_text_shape(RID p_shaped) override;
- virtual bool shaped_text_update_breaks(RID p_shaped) override;
- virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
- GDVIRTUAL1R(bool, _shaped_text_shape, RID);
- GDVIRTUAL1R(bool, _shaped_text_update_breaks, RID);
- GDVIRTUAL1R(bool, _shaped_text_update_justification_ops, RID);
-
- virtual bool shaped_text_is_ready(RID p_shaped) const override;
- GDVIRTUAL1RC(bool, _shaped_text_is_ready, RID);
-
- virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override;
- virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override;
- virtual int shaped_text_get_glyph_count(RID p_shaped) const override;
- GDVIRTUAL1RC(GDNativePtr<Glyph>, _shaped_text_get_glyphs, RID);
- GDVIRTUAL1R(GDNativePtr<Glyph>, _shaped_text_sort_logical, RID);
- GDVIRTUAL1RC(int, _shaped_text_get_glyph_count, RID);
-
- virtual Vector2i shaped_text_get_range(RID p_shaped) const override;
- GDVIRTUAL1RC(Vector2i, _shaped_text_get_range, RID);
-
- virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
- GDVIRTUAL5RC(PackedInt32Array, _shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int, bool, uint16_t);
- GDVIRTUAL4RC(PackedInt32Array, _shaped_text_get_line_breaks, RID, float, int, uint16_t);
- GDVIRTUAL2RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, int);
-
- virtual int shaped_text_get_trim_pos(RID p_shaped) const override;
- virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override;
- virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override;
- virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override;
- GDVIRTUAL1RC(int, _shaped_text_get_trim_pos, RID);
- GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_pos, RID);
- GDVIRTUAL1RC(GDNativePtr<Glyph>, _shaped_text_get_ellipsis_glyphs, RID);
- GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_glyph_count, RID);
-
- virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override;
- GDVIRTUAL3(_shaped_text_overrun_trim_to_width, RID, float, uint16_t);
-
- virtual Array shaped_text_get_objects(RID p_shaped) const override;
- virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
- GDVIRTUAL1RC(Array, _shaped_text_get_objects, RID);
- GDVIRTUAL2RC(Rect2, _shaped_text_get_object_rect, RID, Variant);
-
- virtual Size2 shaped_text_get_size(RID p_shaped) const override;
- virtual float shaped_text_get_ascent(RID p_shaped) const override;
- virtual float shaped_text_get_descent(RID p_shaped) const override;
- virtual float shaped_text_get_width(RID p_shaped) const override;
- virtual float shaped_text_get_underline_position(RID p_shaped) const override;
- virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
- GDVIRTUAL1RC(Size2, _shaped_text_get_size, RID);
- GDVIRTUAL1RC(float, _shaped_text_get_ascent, RID);
- GDVIRTUAL1RC(float, _shaped_text_get_descent, RID);
- GDVIRTUAL1RC(float, _shaped_text_get_width, RID);
- GDVIRTUAL1RC(float, _shaped_text_get_underline_position, RID);
- GDVIRTUAL1RC(float, _shaped_text_get_underline_thickness, RID);
-
- virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const override;
- GDVIRTUAL3RC(int, _shaped_text_get_dominant_direction_in_range, RID, int, int);
-
- virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const override;
- virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const override;
- GDVIRTUAL3C(_shaped_text_get_carets, RID, int, GDNativePtr<CaretInfo>);
- GDVIRTUAL3RC(Vector<Vector2>, _shaped_text_get_selection, RID, int, int);
-
- virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const override;
- virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const override;
- GDVIRTUAL2RC(int, _shaped_text_hit_test_grapheme, RID, float);
- GDVIRTUAL2RC(int, _shaped_text_hit_test_position, RID, float);
-
- virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const override;
- virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override;
- GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, float, float, const Color &);
- GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, float, float, int, const Color &);
-
- virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const override;
- virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const override;
- virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const override;
- GDVIRTUAL2RC(Vector2, _shaped_text_get_grapheme_bounds, RID, int);
- GDVIRTUAL2RC(int, _shaped_text_next_grapheme_pos, RID, int);
- GDVIRTUAL2RC(int, _shaped_text_prev_grapheme_pos, RID, int);
+ GDVIRTUAL2R(RID, create_shaped_text, Direction, Orientation);
+
+ virtual void shaped_text_clear(const RID &p_shaped) override;
+ GDVIRTUAL1(shaped_text_clear, RID);
+
+ virtual void shaped_text_set_direction(const RID &p_shaped, Direction p_direction = DIRECTION_AUTO) override;
+ virtual Direction shaped_text_get_direction(const RID &p_shaped) const override;
+ virtual Direction shaped_text_get_inferred_direction(const RID &p_shaped) const override;
+ GDVIRTUAL2(shaped_text_set_direction, RID, Direction);
+ GDVIRTUAL1RC(Direction, shaped_text_get_direction, RID);
+ GDVIRTUAL1RC(Direction, shaped_text_get_inferred_direction, RID);
+
+ virtual void shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) override;
+ GDVIRTUAL2(shaped_text_set_bidi_override, RID, const Array &);
+
+ virtual void shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) override;
+ virtual String shaped_text_get_custom_punctuation(const RID &p_shaped) const override;
+ GDVIRTUAL2(shaped_text_set_custom_punctuation, RID, String);
+ GDVIRTUAL1RC(String, shaped_text_get_custom_punctuation, RID);
+
+ virtual void shaped_text_set_orientation(const RID &p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
+ virtual Orientation shaped_text_get_orientation(const RID &p_shaped) const override;
+ GDVIRTUAL2(shaped_text_set_orientation, RID, Orientation);
+ GDVIRTUAL1RC(Orientation, shaped_text_get_orientation, RID);
+
+ virtual void shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) override;
+ virtual bool shaped_text_get_preserve_invalid(const RID &p_shaped) const override;
+ GDVIRTUAL2(shaped_text_set_preserve_invalid, RID, bool);
+ GDVIRTUAL1RC(bool, shaped_text_get_preserve_invalid, RID);
+
+ virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override;
+ virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override;
+ GDVIRTUAL2(shaped_text_set_preserve_control, RID, bool);
+ GDVIRTUAL1RC(bool, shaped_text_get_preserve_control, RID);
+
+ virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
+ virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
+ virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
+ GDVIRTUAL7R(bool, shaped_text_add_string, RID, const String &, const Array &, int64_t, const Dictionary &, const String &, const Variant &);
+ GDVIRTUAL5R(bool, shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t);
+ GDVIRTUAL4R(bool, shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment);
+
+ virtual int64_t shaped_get_span_count(const RID &p_shaped) const override;
+ virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const override;
+ virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) override;
+ GDVIRTUAL1RC(int64_t, shaped_get_span_count, RID);
+ GDVIRTUAL2RC(Variant, shaped_get_span_meta, RID, int64_t);
+ GDVIRTUAL5(shaped_set_span_update_font, RID, int64_t, const Array &, int64_t, const Dictionary &);
+
+ virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override;
+ virtual RID shaped_text_get_parent(const RID &p_shaped) const override;
+ GDVIRTUAL3RC(RID, shaped_text_substr, RID, int64_t, int64_t);
+ GDVIRTUAL1RC(RID, shaped_text_get_parent, RID);
+
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
+ virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override;
+ GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, int64_t);
+ GDVIRTUAL2R(double, shaped_text_tab_align, RID, const PackedFloat32Array &);
+
+ virtual bool shaped_text_shape(const RID &p_shaped) override;
+ virtual bool shaped_text_update_breaks(const RID &p_shaped) override;
+ virtual bool shaped_text_update_justification_ops(const RID &p_shaped) override;
+ GDVIRTUAL1R(bool, shaped_text_shape, RID);
+ GDVIRTUAL1R(bool, shaped_text_update_breaks, RID);
+ GDVIRTUAL1R(bool, shaped_text_update_justification_ops, RID);
+
+ virtual bool shaped_text_is_ready(const RID &p_shaped) const override;
+ GDVIRTUAL1RC(bool, shaped_text_is_ready, RID);
+
+ virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const override;
+ virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) override;
+ virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const override;
+ GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_glyphs, RID);
+ GDVIRTUAL1R(GDNativeConstPtr<const Glyph>, shaped_text_sort_logical, RID);
+ GDVIRTUAL1RC(int64_t, shaped_text_get_glyph_count, RID);
+
+ virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override;
+ GDVIRTUAL1RC(Vector2i, shaped_text_get_range, RID);
+
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
+ GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, int64_t);
+ GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, int64_t);
+ GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, int64_t);
+
+ virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override;
+ virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override;
+ virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override;
+ virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override;
+ GDVIRTUAL1RC(int64_t, shaped_text_get_trim_pos, RID);
+ GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_pos, RID);
+ GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_ellipsis_glyphs, RID);
+ GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_glyph_count, RID);
+
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override;
+ GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, int64_t);
+
+ virtual Array shaped_text_get_objects(const RID &p_shaped) const override;
+ virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override;
+ GDVIRTUAL1RC(Array, shaped_text_get_objects, RID);
+ GDVIRTUAL2RC(Rect2, shaped_text_get_object_rect, RID, const Variant &);
+
+ virtual Size2 shaped_text_get_size(const RID &p_shaped) const override;
+ virtual double shaped_text_get_ascent(const RID &p_shaped) const override;
+ virtual double shaped_text_get_descent(const RID &p_shaped) const override;
+ virtual double shaped_text_get_width(const RID &p_shaped) const override;
+ virtual double shaped_text_get_underline_position(const RID &p_shaped) const override;
+ virtual double shaped_text_get_underline_thickness(const RID &p_shaped) const override;
+ GDVIRTUAL1RC(Size2, shaped_text_get_size, RID);
+ GDVIRTUAL1RC(double, shaped_text_get_ascent, RID);
+ GDVIRTUAL1RC(double, shaped_text_get_descent, RID);
+ GDVIRTUAL1RC(double, shaped_text_get_width, RID);
+ GDVIRTUAL1RC(double, shaped_text_get_underline_position, RID);
+ GDVIRTUAL1RC(double, shaped_text_get_underline_thickness, RID);
+
+ virtual Direction shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const override;
+ GDVIRTUAL3RC(int64_t, shaped_text_get_dominant_direction_in_range, RID, int64_t, int64_t);
+
+ virtual CaretInfo shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const override;
+ virtual Vector<Vector2> shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const override;
+ GDVIRTUAL3C(shaped_text_get_carets, RID, int64_t, GDNativePtr<CaretInfo>);
+ GDVIRTUAL3RC(Vector<Vector2>, shaped_text_get_selection, RID, int64_t, int64_t);
+
+ virtual int64_t shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const override;
+ virtual int64_t shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const override;
+ GDVIRTUAL2RC(int64_t, shaped_text_hit_test_grapheme, RID, double);
+ GDVIRTUAL2RC(int64_t, shaped_text_hit_test_position, RID, double);
+
+ virtual void shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual void shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, int64_t p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override;
+ GDVIRTUAL6C(shaped_text_draw, RID, RID, const Vector2 &, double, double, const Color &);
+ GDVIRTUAL7C(shaped_text_draw_outline, RID, RID, const Vector2 &, double, double, int64_t, const Color &);
+
+ virtual Vector2 shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const override;
+ virtual int64_t shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const override;
+ virtual int64_t shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const override;
+ GDVIRTUAL2RC(Vector2, shaped_text_get_grapheme_bounds, RID, int64_t);
+ GDVIRTUAL2RC(int64_t, shaped_text_next_grapheme_pos, RID, int64_t);
+ GDVIRTUAL2RC(int64_t, shaped_text_prev_grapheme_pos, RID, int64_t);
virtual String format_number(const String &p_string, const String &p_language = "") const override;
virtual String parse_number(const String &p_string, const String &p_language = "") const override;
virtual String percent_sign(const String &p_language = "") const override;
- GDVIRTUAL2RC(String, _format_number, const String &, const String &);
- GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
- GDVIRTUAL1RC(String, _percent_sign, const String &);
+ GDVIRTUAL2RC(String, format_number, const String &, const String &);
+ GDVIRTUAL2RC(String, parse_number, const String &, const String &);
+ GDVIRTUAL1RC(String, percent_sign, const String &);
+
+ virtual String strip_diacritics(const String &p_string) const override;
+ GDVIRTUAL1RC(String, strip_diacritics, const String &);
+
+ virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override;
+ GDVIRTUAL2RC(PackedInt32Array, string_get_word_breaks, const String &, const String &);
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
- GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &);
- GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &);
+ GDVIRTUAL2RC(String, string_to_upper, const String &, const String &);
+ GDVIRTUAL2RC(String, string_to_lower, const String &, const String &);
+
+ Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &);
TextServerExtension();
~TextServerExtension();
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 37cc6599b1..41d9c74d82 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -75,7 +75,7 @@ void TextServerManager::remove_interface(const Ref<TextServer> &p_interface) {
};
};
- ERR_FAIL_COND(idx == -1);
+ ERR_FAIL_COND_MSG(idx == -1, "Interface not found.");
print_verbose("TextServer: Removed interface \"" + p_interface->get_name() + "\"");
emit_signal(SNAME("interface_removed"), p_interface->get_name());
interfaces.remove_at(idx);
@@ -99,7 +99,7 @@ Ref<TextServer> TextServerManager::find_interface(const String &p_name) const {
};
};
- ERR_FAIL_COND_V(idx == -1, nullptr);
+ ERR_FAIL_COND_V_MSG(idx == -1, nullptr, "Interface not found.");
return interfaces[idx];
}
@@ -200,7 +200,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("tag_to_name", "tag"), &TextServer::tag_to_name);
ClassDB::bind_method(D_METHOD("has", "rid"), &TextServer::has);
- ClassDB::bind_method(D_METHOD("free_rid", "rid"), &TextServer::free); // shouldn't conflict with Object::free()
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &TextServer::free_rid);
/* Font Interface */
@@ -208,6 +208,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data);
+ ClassDB::bind_method(D_METHOD("font_set_face_index", "font_rid", "face_index"), &TextServer::font_set_face_index);
+ ClassDB::bind_method(D_METHOD("font_get_face_index", "font_rid"), &TextServer::font_get_face_index);
+
+ ClassDB::bind_method(D_METHOD("font_get_face_count", "font_rid"), &TextServer::font_get_face_count);
+
ClassDB::bind_method(D_METHOD("font_set_style", "font_rid", "style"), &TextServer::font_set_style);
ClassDB::bind_method(D_METHOD("font_get_style", "font_rid"), &TextServer::font_get_style);
@@ -220,6 +225,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
+ ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps);
+
ClassDB::bind_method(D_METHOD("font_set_multichannel_signed_distance_field", "font_rid", "msdf"), &TextServer::font_set_multichannel_signed_distance_field);
ClassDB::bind_method(D_METHOD("font_is_multichannel_signed_distance_field", "font_rid"), &TextServer::font_is_multichannel_signed_distance_field);
@@ -241,6 +249,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("font_set_embolden", "font_rid", "strength"), &TextServer::font_set_embolden);
+ ClassDB::bind_method(D_METHOD("font_get_embolden", "font_rid"), &TextServer::font_get_embolden);
+
+ ClassDB::bind_method(D_METHOD("font_set_transform", "font_rid", "transform"), &TextServer::font_set_transform);
+ ClassDB::bind_method(D_METHOD("font_get_transform", "font_rid"), &TextServer::font_get_transform);
+
ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates);
ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates);
@@ -298,6 +312,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_get_glyph_texture_idx", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_idx);
ClassDB::bind_method(D_METHOD("font_set_glyph_texture_idx", "font_rid", "size", "glyph", "texture_idx"), &TextServer::font_set_glyph_texture_idx);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_texture_rid", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_rid);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_texture_size", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_size);
+
ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::font_get_glyph_contours);
ClassDB::bind_method(D_METHOD("font_get_kerning_list", "font_rid", "size"), &TextServer::font_get_kerning_list);
@@ -389,7 +406,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range);
ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION));
ClassDB::bind_method(D_METHOD("shaped_text_get_trim_pos", "shaped"), &TextServer::shaped_text_get_trim_pos);
ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_pos", "shaped"), &TextServer::shaped_text_get_ellipsis_pos);
@@ -427,11 +444,15 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("percent_sign", "language"), &TextServer::percent_sign, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL(""));
+
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text);
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
@@ -487,13 +508,19 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_AUTO);
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_HALF);
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_QUARTER);
+ BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
+ BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE);
/* Feature */
+ BIND_ENUM_CONSTANT(FEATURE_SIMPLE_LAYOUT);
BIND_ENUM_CONSTANT(FEATURE_BIDI_LAYOUT);
BIND_ENUM_CONSTANT(FEATURE_VERTICAL_LAYOUT);
BIND_ENUM_CONSTANT(FEATURE_SHAPING);
BIND_ENUM_CONSTANT(FEATURE_KASHIDA_JUSTIFICATION);
BIND_ENUM_CONSTANT(FEATURE_BREAK_ITERATORS);
+ BIND_ENUM_CONSTANT(FEATURE_FONT_BITMAP);
+ BIND_ENUM_CONSTANT(FEATURE_FONT_DYNAMIC);
+ BIND_ENUM_CONSTANT(FEATURE_FONT_MSDF);
BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM);
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION);
@@ -514,9 +541,18 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FONT_BOLD);
BIND_ENUM_CONSTANT(FONT_ITALIC);
BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH);
+
+ /* Structured text parser */
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_URI);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
}
-Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const {
+Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const {
int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3));
int sp = MAX(0, w - 1);
int sz = MAX(1, Math::round(p_size / 15.f));
@@ -524,7 +560,7 @@ Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const {
return Vector2(4 + 3 * w + sp + 1, 15) * sz;
}
-void TextServer::_draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const {
+void TextServer::_draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const {
static uint8_t chars[] = { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x77, 0x1F, 0x4E, 0x3D, 0x4F, 0x47, 0x00 };
uint8_t x = chars[p_index];
if (x & (1 << 6)) {
@@ -550,7 +586,7 @@ void TextServer::_draw_hex_code_box_number(RID p_canvas, int p_size, const Vecto
}
}
-void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const {
+void TextServer::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
if (p_index == 0) {
return;
}
@@ -594,7 +630,7 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po
}
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t /*TextBreakFlag*/ p_break_flags) const {
PackedInt32Array lines;
ERR_FAIL_COND_V(p_width.is_empty(), lines);
@@ -670,13 +706,13 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t /*TextBreakFlag*/ p_break_flags) const {
PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
- float width = 0.f;
+ double width = 0.f;
int line_start = MAX(p_start, range.x);
int last_safe_break = -1;
int word_count = 0;
@@ -738,7 +774,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
+PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
PackedInt32Array words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
@@ -746,27 +782,31 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_gra
int word_start = range.x;
- int l_size = shaped_text_get_glyph_count(p_shaped);
+ const int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].count > 0) {
if ((l_gl[i].flags & p_grapheme_flags) != 0) {
- words.push_back(word_start);
- words.push_back(l_gl[i].start);
+ if (word_start != l_gl[i].start) {
+ words.push_back(word_start);
+ words.push_back(l_gl[i].start);
+ }
word_start = l_gl[i].end;
}
}
}
if (l_size > 0) {
- words.push_back(word_start);
- words.push_back(range.y);
+ if (word_start != range.y) {
+ words.push_back(word_start);
+ words.push_back(range.y);
+ }
}
return words;
}
-CaretInfo TextServer::shaped_text_get_carets(RID p_shaped, int p_position) const {
+CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const {
Vector<Rect2> carets;
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
@@ -916,7 +956,7 @@ CaretInfo TextServer::shaped_text_get_carets(RID p_shaped, int p_position) const
return caret;
}
-Dictionary TextServer::_shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const {
+Dictionary TextServer::_shaped_text_get_carets_wrapper(const RID &p_shaped, int64_t p_position) const {
Dictionary ret;
CaretInfo caret = shaped_text_get_carets(p_shaped, p_position);
@@ -929,7 +969,7 @@ Dictionary TextServer::_shaped_text_get_carets_wrapper(RID p_shaped, int p_posit
return ret;
}
-TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const {
+TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
if (p_start == p_end) {
return DIRECTION_AUTO;
}
@@ -963,7 +1003,15 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(RI
}
}
-Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
+_FORCE_INLINE_ void _push_range(Vector<Vector2> &r_vector, real_t p_start, real_t p_end) {
+ if (!r_vector.is_empty() && Math::is_equal_approx(r_vector[r_vector.size() - 1].y, p_start, (real_t)UNIT_EPSILON)) {
+ r_vector.write[r_vector.size() - 1].y = p_end;
+ } else {
+ r_vector.push_back(Vector2(p_start, p_end));
+ }
+}
+
+Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
Vector<Vector2> ranges;
if (p_start == p_end) {
@@ -987,7 +1035,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
- ranges.push_back(Vector2(off, off + advance));
+ _push_range(ranges, off, off + advance);
}
// Only start of grapheme is in selection range.
if (glyphs[i].start >= start && glyphs[i].end > end) {
@@ -997,9 +1045,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + advance));
+ _push_range(ranges, off + char_adv * (glyphs[i].end - end), off + advance);
} else {
- ranges.push_back(Vector2(off, off + char_adv * (end - glyphs[i].start)));
+ _push_range(ranges, off, off + char_adv * (end - glyphs[i].start));
}
}
// Only end of grapheme is in selection range.
@@ -1010,9 +1058,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off, off + char_adv * (glyphs[i].end - start)));
+ _push_range(ranges, off, off + char_adv * (glyphs[i].end - start));
} else {
- ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + advance));
+ _push_range(ranges, off + char_adv * (start - glyphs[i].start), off + advance);
}
}
// Selection range is within grapheme.
@@ -1023,9 +1071,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start)));
+ _push_range(ranges, off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start));
} else {
- ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + char_adv * (end - glyphs[i].start)));
+ _push_range(ranges, off + char_adv * (start - glyphs[i].start), off + char_adv * (end - glyphs[i].start));
}
}
}
@@ -1034,31 +1082,12 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
}
- // Merge intersecting ranges.
- int i = 0;
- while (i < ranges.size()) {
- i++;
- }
- i = 0;
- while (i < ranges.size()) {
- int j = i + 1;
- while (j < ranges.size()) {
- if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) {
- ranges.write[i].y = ranges[j].y;
- ranges.remove_at(j);
- continue;
- }
- j++;
- }
- i++;
- }
-
return ranges;
}
-int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const {
+int64_t TextServer::shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const {
// Exact grapheme hit test, return -1 if missed.
- float off = 0.0f;
+ double off = 0.0f;
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1074,7 +1103,7 @@ int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) cons
return -1;
}
-int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) const {
+int64_t TextServer::shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const {
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1167,7 +1196,7 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) cons
return 0;
}
-Vector2 TextServer::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const {
+Vector2 TextServer::shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const {
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1188,7 +1217,7 @@ Vector2 TextServer::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) con
return Vector2();
}
-int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
+int64_t TextServer::shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const {
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
@@ -1199,7 +1228,7 @@ int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
return p_pos;
}
-int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
+int64_t TextServer::shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const {
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
@@ -1211,7 +1240,7 @@ int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
return p_pos;
}
-void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const {
+void TextServer::shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, const Color &p_color) const {
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped);
@@ -1257,11 +1286,11 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
if (p_clip_r > 0) {
// Clip right / bottom.
if (orientation == ORIENTATION_HORIZONTAL) {
- if (ofs.x - p_pos.x > p_clip_r) {
+ if (ofs.x - p_pos.x + glyphs[i].advance > p_clip_r) {
return;
}
} else {
- if (ofs.y - p_pos.y > p_clip_r) {
+ if (ofs.y - p_pos.y + glyphs[i].advance > p_clip_r) {
return;
}
}
@@ -1308,7 +1337,7 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
-void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
+void TextServer::shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, int64_t p_outline_size, const Color &p_color) const {
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool rtl = (shaped_text_get_inferred_direction(p_shaped) == DIRECTION_RTL);
@@ -1352,11 +1381,11 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
if (p_clip_r > 0) {
// Clip right / bottom.
if (orientation == ORIENTATION_HORIZONTAL) {
- if (ofs.x - p_pos.x > p_clip_r) {
+ if (ofs.x - p_pos.x + glyphs[i].advance > p_clip_r) {
return;
}
} else {
- if (ofs.y - p_pos.y > p_clip_r) {
+ if (ofs.y - p_pos.y + glyphs[i].advance > p_clip_r) {
return;
}
}
@@ -1528,7 +1557,84 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
-Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const {
+Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ Array ret;
+ switch (p_parser_type) {
+ case STRUCTURED_TEXT_URI: {
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, i));
+ }
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ }
+ }
+ if (prev != p_text.length()) {
+ ret.push_back(Vector2i(prev, p_text.length()));
+ }
+ } break;
+ case STRUCTURED_TEXT_FILE: {
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, i));
+ }
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ }
+ }
+ if (prev != p_text.length()) {
+ ret.push_back(Vector2i(prev, p_text.length()));
+ }
+ } break;
+ case STRUCTURED_TEXT_EMAIL: {
+ bool local = true;
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ if ((p_text[i] == '@') && local) { // Add full "local" as single context.
+ local = false;
+ ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, i));
+ }
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ }
+ }
+ if (prev != p_text.length()) {
+ ret.push_back(Vector2i(prev, p_text.length()));
+ }
+ } break;
+ case STRUCTURED_TEXT_LIST: {
+ if (p_args.size() == 1 && p_args[0].get_type() == Variant::STRING) {
+ Vector<String> tags = p_text.split(String(p_args[0]));
+ int prev = 0;
+ for (int i = 0; i < tags.size(); i++) {
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, prev + tags[i].length()));
+ }
+ ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
+ prev = prev + tags[i].length() + 1;
+ }
+ }
+ } break;
+ case STRUCTURED_TEXT_CUSTOM:
+ case STRUCTURED_TEXT_NONE:
+ case STRUCTURED_TEXT_DEFAULT:
+ default: {
+ ret.push_back(Vector2i(0, p_text.length()));
+ }
+ }
+ return ret;
+}
+
+Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
Array ret;
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1553,7 +1659,7 @@ Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const {
return ret;
}
-Array TextServer::_shaped_text_sort_logical_wrapper(RID p_shaped) {
+Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
Array ret;
const Glyph *glyphs = shaped_text_sort_logical(p_shaped);
@@ -1578,7 +1684,7 @@ Array TextServer::_shaped_text_sort_logical_wrapper(RID p_shaped) {
return ret;
}
-Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const {
+Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
Array ret;
const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
diff --git a/servers/text_server.h b/servers/text_server.h
index 38ad496490..a67ad8fc9e 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -102,25 +102,29 @@ public:
};
enum SubpixelPositioning {
- SUBPIXEL_POSITIONING_DISABLED,
- SUBPIXEL_POSITIONING_AUTO,
- SUBPIXEL_POSITIONING_ONE_HALF,
- SUBPIXEL_POSITIONING_ONE_QUARTER,
- };
+ SUBPIXEL_POSITIONING_DISABLED = 0,
+ SUBPIXEL_POSITIONING_AUTO = 1,
+ SUBPIXEL_POSITIONING_ONE_HALF = 2,
+ SUBPIXEL_POSITIONING_ONE_QUARTER = 3,
- const int SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE = 20;
- const int SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE = 16;
+ SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE = 20,
+ SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE = 16,
+ };
enum Feature {
- FEATURE_BIDI_LAYOUT = 1 << 0,
- FEATURE_VERTICAL_LAYOUT = 1 << 1,
- FEATURE_SHAPING = 1 << 2,
- FEATURE_KASHIDA_JUSTIFICATION = 1 << 3,
- FEATURE_BREAK_ITERATORS = 1 << 4,
- FEATURE_FONT_SYSTEM = 1 << 5,
- FEATURE_FONT_VARIABLE = 1 << 6,
- FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 7,
- FEATURE_USE_SUPPORT_DATA = 1 << 8,
+ FEATURE_SIMPLE_LAYOUT = 1 << 0,
+ FEATURE_BIDI_LAYOUT = 1 << 1,
+ FEATURE_VERTICAL_LAYOUT = 1 << 2,
+ FEATURE_SHAPING = 1 << 3,
+ FEATURE_KASHIDA_JUSTIFICATION = 1 << 4,
+ FEATURE_BREAK_ITERATORS = 1 << 5,
+ FEATURE_FONT_BITMAP = 1 << 6,
+ FEATURE_FONT_DYNAMIC = 1 << 7,
+ FEATURE_FONT_MSDF = 1 << 8,
+ FEATURE_FONT_SYSTEM = 1 << 9,
+ FEATURE_FONT_VARIABLE = 1 << 10,
+ FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 11,
+ FEATURE_USE_SUPPORT_DATA = 1 << 12,
};
enum ContourPointTag {
@@ -142,63 +146,20 @@ public:
FONT_FIXED_WIDTH = 1 << 2,
};
- void _draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const;
-
-protected:
- struct TrimData {
- int trim_pos = -1;
- int ellipsis_pos = -1;
- Vector<Glyph> ellipsis_glyph_buf;
+ enum StructuredTextParser {
+ STRUCTURED_TEXT_DEFAULT,
+ STRUCTURED_TEXT_URI,
+ STRUCTURED_TEXT_FILE,
+ STRUCTURED_TEXT_EMAIL,
+ STRUCTURED_TEXT_LIST,
+ STRUCTURED_TEXT_NONE,
+ STRUCTURED_TEXT_CUSTOM
};
- struct ShapedTextData {
- Mutex mutex;
-
- /* Source data */
- RID parent; // Substring parent ShapedTextData.
-
- int start = 0; // Substring start offset in the parent string.
- int end = 0; // Substring end offset in the parent string.
-
- String text;
- String custom_punct;
- TextServer::Direction direction = DIRECTION_LTR; // Desired text direction.
- TextServer::Orientation orientation = ORIENTATION_HORIZONTAL;
-
- struct EmbeddedObject {
- int pos = 0;
- InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER;
- Rect2 rect;
- };
- Map<Variant, EmbeddedObject> objects;
-
- /* Shaped data */
- TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction.
- bool valid = false; // String is shaped.
- bool line_breaks_valid = false; // Line and word break flags are populated (and virtual zero width spaces inserted).
- bool justification_ops_valid = false; // Virtual elongation glyphs are added to the string.
- bool sort_valid = false;
- bool text_trimmed = false;
-
- bool preserve_invalid = true; // Draw hex code box instead of missing characters.
- bool preserve_control = false; // Draw control characters.
-
- float ascent = 0.f; // Ascent for horizontal layout, 1/2 of width for vertical.
- float descent = 0.f; // Descent for horizontal layout, 1/2 of width for vertical.
- float width = 0.f; // Width for horizontal layout, height for vertical.
- float width_trimmed = 0.f;
-
- float upos = 0.f;
- float uthk = 0.f;
-
- TrimData overrun_trim_data;
- bool fit_width_minimum_reached = false;
+ void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const;
- Vector<Glyph> glyphs;
- Vector<Glyph> glyphs_logical;
- };
-
- Map<char32_t, char32_t> diacritics_map;
+protected:
+ HashMap<char32_t, char32_t> diacritics_map;
void _diacritics_map_add(const String &p_from, char32_t p_to);
void _init_diacritics_map();
@@ -207,10 +168,10 @@ protected:
public:
virtual bool has_feature(Feature p_feature) const = 0;
virtual String get_name() const = 0;
- virtual uint32_t get_features() const = 0;
+ virtual int64_t get_features() const = 0;
- virtual void free(RID p_rid) = 0;
- virtual bool has(RID p_rid) = 0;
+ virtual void free_rid(const RID &p_rid) = 0;
+ virtual bool has(const RID &p_rid) = 0;
virtual bool load_support_data(const String &p_filename) = 0;
virtual String get_support_data_filename() const = 0;
@@ -219,245 +180,264 @@ public:
virtual bool is_locale_right_to_left(const String &p_locale) const = 0;
- virtual int32_t name_to_tag(const String &p_name) const { return 0; };
- virtual String tag_to_name(int32_t p_tag) const { return ""; };
+ virtual int64_t name_to_tag(const String &p_name) const { return 0; };
+ virtual String tag_to_name(int64_t p_tag) const { return ""; };
/* Font interface */
virtual RID create_font() = 0;
- virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0;
- virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0;
+ virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) = 0;
+ virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) = 0;
+
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) = 0;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const = 0;
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const = 0;
+
+ virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) = 0;
+ virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const = 0;
+
+ virtual void font_set_name(const RID &p_font_rid, const String &p_name) = 0;
+ virtual String font_get_name(const RID &p_font_rid) const = 0;
- virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) = 0;
- virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const = 0;
+ virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0;
+ virtual String font_get_style_name(const RID &p_font_rid) const = 0;
- virtual void font_set_name(RID p_font_rid, const String &p_name) = 0;
- virtual String font_get_name(RID p_font_rid) const = 0;
+ virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0;
+ virtual bool font_is_antialiased(const RID &p_font_rid) const = 0;
- virtual void font_set_style_name(RID p_font_rid, const String &p_name) = 0;
- virtual String font_get_style_name(RID p_font_rid) const = 0;
+ virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0;
+ virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0;
- virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0;
- virtual bool font_is_antialiased(RID p_font_rid) const = 0;
+ virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) = 0;
+ virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const = 0;
- virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) = 0;
- virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const = 0;
+ virtual void font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) = 0;
+ virtual int64_t font_get_msdf_pixel_range(const RID &p_font_rid) const = 0;
- virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) = 0;
- virtual int font_get_msdf_pixel_range(RID p_font_rid) const = 0;
+ virtual void font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) = 0;
+ virtual int64_t font_get_msdf_size(const RID &p_font_rid) const = 0;
- virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) = 0;
- virtual int font_get_msdf_size(RID p_font_rid) const = 0;
+ virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) = 0;
+ virtual int64_t font_get_fixed_size(const RID &p_font_rid) const = 0;
- virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) = 0;
- virtual int font_get_fixed_size(RID p_font_rid) const = 0;
+ virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) = 0;
+ virtual bool font_is_force_autohinter(const RID &p_font_rid) const = 0;
- virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) = 0;
- virtual bool font_is_force_autohinter(RID p_font_rid) const = 0;
+ virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) = 0;
+ virtual Hinting font_get_hinting(const RID &p_font_rid) const = 0;
- virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) = 0;
- virtual Hinting font_get_hinting(RID p_font_rid) const = 0;
+ virtual void font_set_subpixel_positioning(const RID &p_font_rid, SubpixelPositioning p_subpixel) = 0;
+ virtual SubpixelPositioning font_get_subpixel_positioning(const RID &p_font_rid) const = 0;
- virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0;
- virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0;
+ virtual void font_set_embolden(const RID &p_font_rid, double p_strength) = 0;
+ virtual double font_get_embolden(const RID &p_font_rid) const = 0;
- virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
- virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;
+ virtual void font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) = 0;
+ virtual Transform2D font_get_transform(const RID &p_font_rid) const = 0;
- virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) = 0;
- virtual float font_get_oversampling(RID p_font_rid) const = 0;
+ virtual void font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) = 0;
+ virtual Dictionary font_get_variation_coordinates(const RID &p_font_rid) const = 0;
- virtual Array font_get_size_cache_list(RID p_font_rid) const = 0;
- virtual void font_clear_size_cache(RID p_font_rid) = 0;
- virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) = 0;
+ virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) = 0;
+ virtual double font_get_oversampling(const RID &p_font_rid) const = 0;
- virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) = 0;
- virtual float font_get_ascent(RID p_font_rid, int p_size) const = 0;
+ virtual Array font_get_size_cache_list(const RID &p_font_rid) const = 0;
+ virtual void font_clear_size_cache(const RID &p_font_rid) = 0;
+ virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) = 0;
- virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) = 0;
- virtual float font_get_descent(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) = 0;
+ virtual double font_get_ascent(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) = 0;
- virtual float font_get_underline_position(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) = 0;
+ virtual double font_get_descent(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) = 0;
- virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) = 0;
+ virtual double font_get_underline_position(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) = 0;
- virtual float font_get_scale(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) = 0;
+ virtual double font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) = 0;
- virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const = 0;
+ virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) = 0;
+ virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const = 0;
- virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) = 0;
- virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) = 0;
+ virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) = 0;
+ virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const = 0;
- virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) = 0;
- virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0;
+ virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const = 0;
+ virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) = 0;
+ virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) = 0;
- virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) = 0;
- virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0;
+ virtual void font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) = 0;
+ virtual Ref<Image> font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const = 0;
- virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const = 0;
- virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) = 0;
- virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) = 0;
+ virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) = 0;
+ virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const = 0;
- virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const = 0;
- virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) = 0;
+ virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0;
+ virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) = 0;
+ virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) = 0;
- virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
- virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) = 0;
+ virtual Vector2 font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const = 0;
+ virtual void font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) = 0;
- virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
- virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) = 0;
+ virtual Vector2 font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
+ virtual void font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) = 0;
- virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
- virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) = 0;
+ virtual Vector2 font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
+ virtual void font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) = 0;
- virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
- virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) = 0;
+ virtual Rect2 font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
+ virtual void font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) = 0;
- virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const = 0;
+ virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
+ virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) = 0;
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
- virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const = 0;
- virtual void font_clear_kerning_map(RID p_font_rid, int p_size) = 0;
- virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) = 0;
+ virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0;
- virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) = 0;
- virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const = 0;
+ virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0;
+ virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) = 0;
+ virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) = 0;
- virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const = 0;
+ virtual void font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) = 0;
+ virtual Vector2 font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const = 0;
- virtual bool font_has_char(RID p_font_rid, char32_t p_char) const = 0;
- virtual String font_get_supported_chars(RID p_font_rid) const = 0;
+ virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const = 0;
- virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) = 0;
- virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) = 0;
+ virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const = 0;
+ virtual String font_get_supported_chars(const RID &p_font_rid) const = 0;
- virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
- virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
+ virtual void font_render_range(const RID &p_font, const Vector2i &p_size, int64_t p_start, int64_t p_end) = 0;
+ virtual void font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) = 0;
- virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const = 0;
- virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) = 0;
- virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) = 0;
- virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) = 0;
- virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) = 0;
+ virtual void font_draw_glyph(const RID &p_font, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
+ virtual void font_draw_glyph_outline(const RID &p_font, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
- virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const = 0;
- virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) = 0;
- virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) = 0;
- virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) = 0;
- virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) = 0;
+ virtual bool font_is_language_supported(const RID &p_font_rid, const String &p_language) const = 0;
+ virtual void font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) = 0;
+ virtual bool font_get_language_support_override(const RID &p_font_rid, const String &p_language) = 0;
+ virtual void font_remove_language_support_override(const RID &p_font_rid, const String &p_language) = 0;
+ virtual PackedStringArray font_get_language_support_overrides(const RID &p_font_rid) = 0;
- virtual void font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) = 0;
- virtual Dictionary font_get_opentype_feature_overrides(RID p_font_rid) const = 0;
+ virtual bool font_is_script_supported(const RID &p_font_rid, const String &p_script) const = 0;
+ virtual void font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) = 0;
+ virtual bool font_get_script_support_override(const RID &p_font_rid, const String &p_script) = 0;
+ virtual void font_remove_script_support_override(const RID &p_font_rid, const String &p_script) = 0;
+ virtual PackedStringArray font_get_script_support_overrides(const RID &p_font_rid) = 0;
- virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0;
- virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0;
+ virtual void font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) = 0;
+ virtual Dictionary font_get_opentype_feature_overrides(const RID &p_font_rid) const = 0;
- virtual float font_get_global_oversampling() const = 0;
- virtual void font_set_global_oversampling(float p_oversampling) = 0;
+ virtual Dictionary font_supported_feature_list(const RID &p_font_rid) const = 0;
+ virtual Dictionary font_supported_variation_list(const RID &p_font_rid) const = 0;
- virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const;
- virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const;
+ virtual double font_get_global_oversampling() const = 0;
+ virtual void font_set_global_oversampling(double p_oversampling) = 0;
+
+ virtual Vector2 get_hex_code_box_size(int64_t p_size, int64_t p_index) const;
+ virtual void draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const;
/* Shaped text buffer interface */
virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
- virtual void shaped_text_clear(RID p_shaped) = 0;
+ virtual void shaped_text_clear(const RID &p_shaped) = 0;
- virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) = 0;
- virtual Direction shaped_text_get_direction(RID p_shaped) const = 0;
- virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const = 0;
+ virtual void shaped_text_set_direction(const RID &p_shaped, Direction p_direction = DIRECTION_AUTO) = 0;
+ virtual Direction shaped_text_get_direction(const RID &p_shaped) const = 0;
+ virtual Direction shaped_text_get_inferred_direction(const RID &p_shaped) const = 0;
- virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0;
+ virtual void shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) = 0;
- virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) = 0;
- virtual String shaped_text_get_custom_punctuation(RID p_shaped) const = 0;
+ virtual void shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) = 0;
+ virtual String shaped_text_get_custom_punctuation(const RID &p_shaped) const = 0;
- virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
- virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0;
+ virtual void shaped_text_set_orientation(const RID &p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
+ virtual Orientation shaped_text_get_orientation(const RID &p_shaped) const = 0;
- virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) = 0;
- virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const = 0;
+ virtual void shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) = 0;
+ virtual bool shaped_text_get_preserve_invalid(const RID &p_shaped) const = 0;
- virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) = 0;
- virtual bool shaped_text_get_preserve_control(RID p_shaped) const = 0;
+ virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) = 0;
+ virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const = 0;
- virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) = 0;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0;
+ virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0;
+ virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) = 0;
+ virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0;
- virtual int shaped_get_span_count(RID p_shaped) const = 0;
- virtual Variant shaped_get_span_meta(RID p_shaped, int p_index) const = 0;
- virtual void shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary()) = 0;
+ virtual int64_t shaped_get_span_count(const RID &p_shaped) const = 0;
+ virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const = 0;
+ virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) = 0;
- virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
- virtual RID shaped_text_get_parent(RID p_shaped) const = 0;
+ virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
+ virtual RID shaped_text_get_parent(const RID &p_shaped) const = 0;
- virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
- virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) = 0;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
+ virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) = 0;
- virtual bool shaped_text_shape(RID p_shaped) = 0;
- virtual bool shaped_text_update_breaks(RID p_shaped) = 0;
- virtual bool shaped_text_update_justification_ops(RID p_shaped) = 0;
+ virtual bool shaped_text_shape(const RID &p_shaped) = 0;
+ virtual bool shaped_text_update_breaks(const RID &p_shaped) = 0;
+ virtual bool shaped_text_update_justification_ops(const RID &p_shaped) = 0;
- virtual bool shaped_text_is_ready(RID p_shaped) const = 0;
+ virtual bool shaped_text_is_ready(const RID &p_shaped) const = 0;
- virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const = 0;
- Array _shaped_text_get_glyphs_wrapper(RID p_shaped) const;
- virtual const Glyph *shaped_text_sort_logical(RID p_shaped) = 0;
- Array _shaped_text_sort_logical_wrapper(RID p_shaped);
- virtual int shaped_text_get_glyph_count(RID p_shaped) const = 0;
+ virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const = 0;
+ Array _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const;
+ virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) = 0;
+ Array _shaped_text_sort_logical_wrapper(const RID &p_shaped);
+ virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const = 0;
- virtual Vector2i shaped_text_get_range(RID p_shaped) const = 0;
+ virtual Vector2i shaped_text_get_range(const RID &p_shaped) const = 0;
- virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
- virtual int shaped_text_get_trim_pos(RID p_shaped) const = 0;
- virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const = 0;
- virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const = 0;
- Array _shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const;
- virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const = 0;
+ virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0;
+ virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0;
+ virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const = 0;
+ Array _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const;
+ virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const = 0;
- virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) = 0;
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) = 0;
- virtual Array shaped_text_get_objects(RID p_shaped) const = 0;
- virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0;
+ virtual Array shaped_text_get_objects(const RID &p_shaped) const = 0;
+ virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const = 0;
- virtual Size2 shaped_text_get_size(RID p_shaped) const = 0;
- virtual float shaped_text_get_ascent(RID p_shaped) const = 0;
- virtual float shaped_text_get_descent(RID p_shaped) const = 0;
- virtual float shaped_text_get_width(RID p_shaped) const = 0;
- virtual float shaped_text_get_underline_position(RID p_shaped) const = 0;
- virtual float shaped_text_get_underline_thickness(RID p_shaped) const = 0;
+ virtual Size2 shaped_text_get_size(const RID &p_shaped) const = 0;
+ virtual double shaped_text_get_ascent(const RID &p_shaped) const = 0;
+ virtual double shaped_text_get_descent(const RID &p_shaped) const = 0;
+ virtual double shaped_text_get_width(const RID &p_shaped) const = 0;
+ virtual double shaped_text_get_underline_position(const RID &p_shaped) const = 0;
+ virtual double shaped_text_get_underline_thickness(const RID &p_shaped) const = 0;
- virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const;
+ virtual Direction shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const;
- virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const;
- Dictionary _shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const;
+ virtual CaretInfo shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const;
+ Dictionary _shaped_text_get_carets_wrapper(const RID &p_shaped, int64_t p_position) const;
- virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const;
+ virtual Vector<Vector2> shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const;
- virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index.
- virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const; // Return caret/selection position.
+ virtual int64_t shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const; // Return grapheme index.
+ virtual int64_t shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const; // Return caret/selection position.
- virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const;
- virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const;
- virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const;
+ virtual Vector2 shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const;
+ virtual int64_t shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const;
+ virtual int64_t shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const;
// The pen position is always placed on the baseline and moveing left to right.
- virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const;
- virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const;
+ virtual void shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, const Color &p_color = Color(1, 1, 1)) const;
+ virtual void shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, int64_t p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const;
// Number conversion.
- virtual String format_number(const String &p_string, const String &p_language = "") const { return p_string; };
- virtual String parse_number(const String &p_string, const String &p_language = "") const { return p_string; };
- virtual String percent_sign(const String &p_language = "") const { return "%"; };
+ virtual String format_number(const String &p_string, const String &p_language = "") const = 0;
+ virtual String parse_number(const String &p_string, const String &p_language = "") const = 0;
+ virtual String percent_sign(const String &p_language = "") const = 0;
+
+ // String functions.
+ virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0;
virtual String strip_diacritics(const String &p_string) const;
@@ -465,6 +445,8 @@ public:
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0;
+ Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+
TextServer();
~TextServer();
};
@@ -501,23 +483,6 @@ struct CaretInfo {
TextServer::Direction t_dir;
};
-struct GlyphCompare { // For line breaking reordering.
- _FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {
- if (l.start == r.start) {
- if (l.count == r.count) {
- if ((l.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
- return false;
- } else {
- return true;
- }
- }
- return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
- } else {
- return l.start < r.start;
- }
- }
-};
-
/*************************************************************************/
class TextServerManager : public Object {
@@ -569,6 +534,7 @@ VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
VARIANT_ENUM_CAST(TextServer::FontStyle);
+VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(CaretInfo);
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 6e105ffc26..62eba2f00b 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -45,7 +45,7 @@ struct BlitToScreen;
If the user wants to enable AR/VR the choose the interface they want to use and initialize it.
- Note that we may make this into a fully instantiable class for GDNative support.
+ Note that we may make this into a fully instantiable class for GDExtension support.
*/
class XRInterface : public RefCounted {
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 18131c1e89..a0bec0f95b 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -30,6 +30,7 @@
#include "xr_interface_extension.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/rendering_server_globals.h"
@@ -339,10 +340,10 @@ void XRInterfaceExtension::notification(int p_what) {
RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
// In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
// So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
- RendererStorageRD *rd_storage = RendererStorageRD::base_singleton;
- ERR_FAIL_NULL_V_MSG(rd_storage, RID(), "Renderer storage not setup");
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_NULL_V_MSG(texture_storage, RID(), "Texture storage not setup");
- return rd_storage->render_target_get_rd_texture(p_render_target);
+ return texture_storage->render_target_get_rd_texture(p_render_target);
}
/*
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index 671eb7a111..4857167a8e 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -49,6 +49,10 @@ void XRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRPositionalTracker::set_tracker_desc);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc");
+ ClassDB::bind_method(D_METHOD("get_tracker_profile"), &XRPositionalTracker::get_tracker_profile);
+ ClassDB::bind_method(D_METHOD("set_tracker_profile", "profile"), &XRPositionalTracker::set_tracker_profile);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "profile"), "set_tracker_profile", "get_tracker_profile");
+
ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRPositionalTracker::get_tracker_hand);
ClassDB::bind_method(D_METHOD("set_tracker_hand", "hand"), &XRPositionalTracker::set_tracker_hand);
ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Unknown,Left,Right"), "set_tracker_hand", "get_tracker_hand");
@@ -65,6 +69,7 @@ void XRPositionalTracker::_bind_methods() {
ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
+ ADD_SIGNAL(MethodInfo("profile_changed", PropertyInfo(Variant::STRING, "role")));
};
void XRPositionalTracker::set_tracker_type(XRServer::TrackerType p_type) {
@@ -95,6 +100,18 @@ String XRPositionalTracker::get_tracker_desc() const {
return description;
}
+void XRPositionalTracker::set_tracker_profile(const String &p_profile) {
+ if (profile != p_profile) {
+ profile = p_profile;
+
+ emit_signal("profile_changed", profile);
+ }
+}
+
+String XRPositionalTracker::get_tracker_profile() const {
+ return profile;
+}
+
XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const {
return hand;
};
diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h
index ccb30bbbe6..8371dfcbb5 100644
--- a/servers/xr/xr_positional_tracker.h
+++ b/servers/xr/xr_positional_tracker.h
@@ -56,11 +56,12 @@ public:
private:
XRServer::TrackerType type; // type of tracker
StringName name; // (unique) name of the tracker
- String description; // description of the tracker, this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
+ String description; // description of the tracker
+ String profile; // this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
TrackerHand hand; // if known, the hand this tracker is held in
- Map<StringName, Ref<XRPose>> poses;
- Map<StringName, Variant> inputs;
+ HashMap<StringName, Ref<XRPose>> poses;
+ HashMap<StringName, Variant> inputs;
protected:
static void _bind_methods();
@@ -72,6 +73,8 @@ public:
StringName get_tracker_name() const;
void set_tracker_desc(const String &p_desc);
String get_tracker_desc() const;
+ void set_tracker_profile(const String &p_profile);
+ String get_tracker_profile() const;
XRPositionalTracker::TrackerHand get_tracker_hand() const;
void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand);
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index e32b41c7ae..ad61aa94bc 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -131,13 +131,13 @@ void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) {
// remove our tilt
if (p_rotation_mode == 1) {
// take the Y out of our Z
- new_reference_frame.basis.set_axis(2, Vector3(new_reference_frame.basis.elements[0][2], 0.0, new_reference_frame.basis.elements[2][2]).normalized());
+ new_reference_frame.basis.set_column(2, Vector3(new_reference_frame.basis.rows[0][2], 0.0, new_reference_frame.basis.rows[2][2]).normalized());
// Y is straight up
- new_reference_frame.basis.set_axis(1, Vector3(0.0, 1.0, 0.0));
+ new_reference_frame.basis.set_column(1, Vector3(0.0, 1.0, 0.0));
// and X is our cross reference
- new_reference_frame.basis.set_axis(0, new_reference_frame.basis.get_axis(1).cross(new_reference_frame.basis.get_axis(2)).normalized());
+ new_reference_frame.basis.set_column(0, new_reference_frame.basis.get_column(1).cross(new_reference_frame.basis.get_column(2)).normalized());
} else if (p_rotation_mode == 2) {
// remove our rotation, we're only interesting in centering on position
new_reference_frame.basis = Basis();
@@ -184,7 +184,7 @@ void XRServer::remove_interface(const Ref<XRInterface> &p_interface) {
};
};
- ERR_FAIL_COND(idx == -1);
+ ERR_FAIL_COND_MSG(idx == -1, "Interface not found.");
print_verbose("XR: Removed interface" + p_interface->get_name());
@@ -211,7 +211,7 @@ Ref<XRInterface> XRServer::find_interface(const String &p_name) const {
};
};
- ERR_FAIL_COND_V(idx == -1, nullptr);
+ ERR_FAIL_COND_V_MSG(idx == -1, nullptr, "Interface not found.");
return interfaces[idx];
};