summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_driver_dummy.cpp19
-rw-r--r--servers/audio/audio_driver_dummy.h6
-rw-r--r--servers/audio/audio_stream.cpp2
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp4
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp10
-rw-r--r--servers/audio/effects/audio_effect_chorus.h2
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp14
-rw-r--r--servers/audio/effects/audio_effect_compressor.h2
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp57
-rw-r--r--servers/audio/effects/audio_effect_delay.h29
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp4
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp2
-rw-r--r--servers/audio/effects/audio_effect_filter.h18
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp14
-rw-r--r--servers/audio_server.cpp18
-rw-r--r--servers/audio_server.h8
-rw-r--r--servers/camera_server.cpp5
-rw-r--r--servers/camera_server.h4
-rw-r--r--servers/display_server.cpp68
-rw-r--r--servers/display_server.h46
-rw-r--r--servers/extensions/physics_server_3d_extension.cpp3
-rw-r--r--servers/extensions/physics_server_3d_extension.h3
-rw-r--r--servers/movie_writer/movie_writer.cpp2
-rw-r--r--servers/navigation_server_2d.cpp53
-rw-r--r--servers/navigation_server_2d.h25
-rw-r--r--servers/navigation_server_3d.cpp10
-rw-r--r--servers/navigation_server_3d.h8
-rw-r--r--servers/physics_2d/godot_area_2d.cpp8
-rw-r--r--servers/physics_2d/godot_body_2d.cpp18
-rw-r--r--servers/physics_2d/godot_body_2d.h2
-rw-r--r--servers/physics_2d/godot_collision_object_2d.h8
-rw-r--r--servers/physics_2d/godot_physics_server_2d.cpp14
-rw-r--r--servers/physics_2d/godot_physics_server_2d.h3
-rw-r--r--servers/physics_2d/godot_space_2d.cpp20
-rw-r--r--servers/physics_2d/godot_step_2d.cpp2
-rw-r--r--servers/physics_3d/godot_area_3d.cpp8
-rw-r--r--servers/physics_3d/godot_body_3d.cpp20
-rw-r--r--servers/physics_3d/godot_body_3d.h2
-rw-r--r--servers/physics_3d/godot_collision_object_3d.h8
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.cpp18
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.h2
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp14
-rw-r--r--servers/physics_3d/godot_physics_server_3d.h3
-rw-r--r--servers/physics_3d/godot_space_3d.cpp18
-rw-r--r--servers/physics_3d/godot_step_3d.cpp2
-rw-r--r--servers/physics_server_2d.cpp50
-rw-r--r--servers/physics_server_2d.h18
-rw-r--r--servers/physics_server_2d_wrap_mt.h3
-rw-r--r--servers/physics_server_3d.cpp52
-rw-r--r--servers/physics_server_3d.h19
-rw-r--r--servers/physics_server_3d_wrap_mt.h3
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h57
-rw-r--r--servers/rendering/dummy/storage/material_storage.h4
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.cpp58
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h58
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h2
-rw-r--r--servers/rendering/dummy/storage/utilities.cpp43
-rw-r--r--servers/rendering/dummy/storage/utilities.h20
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp52
-rw-r--r--servers/rendering/renderer_canvas_cull.h1
-rw-r--r--servers/rendering/renderer_canvas_render.h3
-rw-r--r--servers/rendering/renderer_geometry_instance.cpp4
-rw-r--r--servers/rendering/renderer_geometry_instance.h6
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h4
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp2
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp16
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h2
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp87
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h16
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp18
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp36
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp21
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h3
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp30
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp19
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h2
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.cpp64
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.h310
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp111
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h5
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp80
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h66
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl13
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl24
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl93
-rw-r--r--servers/rendering/renderer_rd/shaders/light_data_inc.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl52
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl50
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl64
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp5
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h7
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp25
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp41
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h8
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp89
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h5
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp5
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.h4
-rw-r--r--servers/rendering/renderer_scene.h8
-rw-r--r--servers/rendering/renderer_scene_cull.cpp100
-rw-r--r--servers/rendering/renderer_scene_cull.h16
-rw-r--r--servers/rendering/renderer_viewport.cpp75
-rw-r--r--servers/rendering/renderer_viewport.h22
-rw-r--r--servers/rendering/rendering_device.cpp2
-rw-r--r--servers/rendering/rendering_device.h13
-rw-r--r--servers/rendering/rendering_device_binds.h6
-rw-r--r--servers/rendering/rendering_server_default.h14
-rw-r--r--servers/rendering/shader_compiler.cpp46
-rw-r--r--servers/rendering/shader_compiler.h1
-rw-r--r--servers/rendering/shader_language.cpp110
-rw-r--r--servers/rendering/shader_language.h8
-rw-r--r--servers/rendering/shader_preprocessor.cpp377
-rw-r--r--servers/rendering/shader_preprocessor.h52
-rw-r--r--servers/rendering/shader_types.cpp10
-rw-r--r--servers/rendering/storage/material_storage.h4
-rw-r--r--servers/rendering/storage/texture_storage.h1
-rw-r--r--servers/rendering_server.cpp128
-rw-r--r--servers/rendering_server.h44
-rw-r--r--servers/text/text_server_extension.cpp68
-rw-r--r--servers/text/text_server_extension.h33
-rw-r--r--servers/text_server.cpp63
-rw-r--r--servers/text_server.h47
-rw-r--r--servers/xr_server.cpp2
-rw-r--r--servers/xr_server.h2
136 files changed, 2820 insertions, 939 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 60eb657923..729f278d4b 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -36,9 +36,8 @@
AudioDriverDummy *AudioDriverDummy::singleton = nullptr;
Error AudioDriverDummy::init() {
- active = false;
- thread_exited = false;
- exit_thread = false;
+ active.clear();
+ exit_thread.clear();
samples_in = nullptr;
if (mix_rate == -1) {
@@ -60,23 +59,23 @@ void AudioDriverDummy::thread_func(void *p_udata) {
uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000;
- while (!ad->exit_thread) {
- if (ad->active) {
+ while (!ad->exit_thread.is_set()) {
+ if (ad->active.is_set()) {
ad->lock();
+ ad->start_counting_ticks();
ad->audio_server_process(ad->buffer_frames, ad->samples_in);
+ ad->stop_counting_ticks();
ad->unlock();
};
OS::get_singleton()->delay_usec(usdelay);
};
-
- ad->thread_exited = true;
};
void AudioDriverDummy::start() {
- active = true;
+ active.set();
};
int AudioDriverDummy::get_mix_rate() const {
@@ -113,7 +112,7 @@ uint32_t AudioDriverDummy::get_channels() const {
}
void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) {
- ERR_FAIL_COND(!active); // If not active, should not mix.
+ ERR_FAIL_COND(!active.is_set()); // If not active, should not mix.
ERR_FAIL_COND(use_threads == true); // If using threads, this will not work well.
uint32_t todo = p_frames;
@@ -136,7 +135,7 @@ void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) {
void AudioDriverDummy::finish() {
if (use_threads) {
- exit_thread = true;
+ exit_thread.set();
thread.wait_to_finish();
}
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 8f47e64d8b..46dd2e1439 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -35,6 +35,7 @@
#include "core/os/mutex.h"
#include "core/os/thread.h"
+#include "core/templates/safe_refcount.h"
class AudioDriverDummy : public AudioDriver {
Thread thread;
@@ -50,9 +51,8 @@ class AudioDriverDummy : public AudioDriver {
int channels;
- bool active;
- bool thread_exited;
- mutable bool exit_thread;
+ SafeFlag active;
+ SafeFlag exit_thread;
bool use_threads = true;
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 80485845c9..4252131161 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -782,7 +782,7 @@ void AudioStreamPlaybackRandomizer::start(float p_from_pos) {
float range_to = randomizer->random_volume_offset_db;
float volume_offset_db = range_from + Math::randf() * (range_to - range_from);
- volume_scale = Math::db2linear(volume_offset_db);
+ volume_scale = Math::db_to_linear(volume_offset_db);
}
if (playing.is_valid()) {
diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp
index 87d46f8bbe..2889562173 100644
--- a/servers/audio/effects/audio_effect_amplify.cpp
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -33,8 +33,8 @@
void AudioEffectAmplifyInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
//multiply volume interpolating to avoid clicks if this changes
float volume_db = base->volume_db;
- float vol = Math::db2linear(mix_volume_db);
- float vol_inc = (Math::db2linear(volume_db) - vol) / float(p_frame_count);
+ float vol = Math::db_to_linear(mix_volume_db);
+ float vol_inc = (Math::db_to_linear(volume_db) - vol) / float(p_frame_count);
for (int i = 0; i < p_frame_count; i++) {
p_dst_frames[i] = p_src_frames[i] * vol;
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index e5434eac02..69b416f5f7 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -95,7 +95,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A
//vol modifier
- AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db2linear(v.level);
+ AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db_to_linear(v.level);
vol_modifier.l *= CLAMP(1.0 - v.pan, 0, 1);
vol_modifier.r *= CLAMP(1.0 + v.pan, 0, 1);
@@ -272,11 +272,11 @@ float AudioEffectChorus::get_dry() const {
return dry;
}
-void AudioEffectChorus::_validate_property(PropertyInfo &property) const {
- if (property.name.begins_with("voice/")) {
- int voice_idx = property.name.get_slice("/", 1).to_int();
+void AudioEffectChorus::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name.begins_with("voice/")) {
+ int voice_idx = p_property.name.get_slice("/", 1).to_int();
if (voice_idx > voice_count) {
- property.usage = PROPERTY_USAGE_NONE;
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
}
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index 72b495f7f9..dd4b431e7a 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -96,7 +96,7 @@ private:
float dry;
protected:
- void _validate_property(PropertyInfo &property) const override;
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index ee71a6dba7..43b210e450 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -32,7 +32,7 @@
#include "servers/audio_server.h"
void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
- float threshold = Math::db2linear(base->threshold);
+ float threshold = Math::db_to_linear(base->threshold);
float sample_rate = AudioServer::get_singleton()->get_mix_rate();
float ratatcoef = exp(-1 / (0.00001f * sample_rate));
@@ -42,7 +42,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi
float atcoef = exp(-1 / (attime * sample_rate));
float relcoef = exp(-1 / (reltime * sample_rate));
- float makeup = Math::db2linear(base->gain);
+ float makeup = Math::db_to_linear(base->gain);
float mix = base->mix;
float gr_meter_decay = exp(1 / (1 * sample_rate));
@@ -64,7 +64,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi
float peak = MAX(s.l, s.r);
- float overdb = 2.08136898f * Math::linear2db(peak / threshold);
+ float overdb = 2.08136898f * Math::linear_to_db(peak / threshold);
if (overdb < 0.0) { //we only care about what goes over to compress
overdb = 0.0;
@@ -94,7 +94,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi
}
float gr = -overdb * (cratio - 1) / cratio;
- float grv = Math::db2linear(gr);
+ float grv = Math::db_to_linear(gr);
runmax = maxover + relcoef * (runmax - maxover); // highest peak for setting att/rel decays in reltime
maxover = runmax;
@@ -184,15 +184,15 @@ StringName AudioEffectCompressor::get_sidechain() const {
return sidechain;
}
-void AudioEffectCompressor::_validate_property(PropertyInfo &property) const {
- if (property.name == "sidechain") {
+void AudioEffectCompressor::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "sidechain") {
String buses = "";
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
buses += ",";
buses += AudioServer::get_singleton()->get_bus_name(i);
}
- property.hint_string = buses;
+ p_property.hint_string = buses;
}
}
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index 998bd3c978..886255b958 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -61,7 +61,7 @@ class AudioEffectCompressor : public AudioEffect {
StringName sidechain;
protected:
- void _validate_property(PropertyInfo &property) const override;
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
public:
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index 80e7a8223c..f71ff05b23 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_effect_delay.h"
+
#include "core/math/math_funcs.h"
#include "servers/audio_server.h"
@@ -52,13 +53,13 @@ void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames, Au
float mix_rate = AudioServer::get_singleton()->get_mix_rate();
- float tap_1_level_f = base->tap_1_active ? Math::db2linear(base->tap_1_level) : 0.0;
+ float tap_1_level_f = base->tap_1_active ? Math::db_to_linear(base->tap_1_level) : 0.0;
int tap_1_delay_frames = int((base->tap_1_delay_ms / 1000.0) * mix_rate);
- float tap_2_level_f = base->tap_2_active ? Math::db2linear(base->tap_2_level) : 0.0;
+ float tap_2_level_f = base->tap_2_active ? Math::db_to_linear(base->tap_2_level) : 0.0;
int tap_2_delay_frames = int((base->tap_2_delay_ms / 1000.0) * mix_rate);
- float feedback_level_f = base->feedback_active ? Math::db2linear(base->feedback_level) : 0.0;
+ float feedback_level_f = base->feedback_active ? Math::db_to_linear(base->feedback_level) : 0.0;
unsigned int feedback_delay_frames = int((base->feedback_delay_ms / 1000.0) * mix_rate);
AudioFrame tap1_vol = AudioFrame(tap_1_level_f, tap_1_level_f);
@@ -286,37 +287,21 @@ 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,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,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,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");
-}
-
-AudioEffectDelay::AudioEffectDelay() {
- tap_1_active = true;
- tap_1_delay_ms = 250;
- tap_1_level = -6;
- tap_1_pan = 0.2;
-
- tap_2_active = true;
- tap_2_delay_ms = 500;
- tap_2_level = -12;
- tap_2_pan = -0.4;
-
- feedback_active = false;
- feedback_delay_ms = 340;
- feedback_level = -6;
- feedback_lowpass = 16000;
-
- dry = 1.0;
+ ADD_GROUP("Tap 1", "tap1_");
+ 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,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_GROUP("Tap 2", "tap2_");
+ 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,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_GROUP("Feedback", "feedback_");
+ 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,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_delay.h b/servers/audio/effects/audio_effect_delay.h
index 137a4e7dbe..020d45e79b 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -37,6 +37,7 @@ class AudioEffectDelay;
class AudioEffectDelayInstance : public AudioEffectInstance {
GDCLASS(AudioEffectDelayInstance, AudioEffectInstance);
+
friend class AudioEffectDelay;
Ref<AudioEffectDelay> base;
@@ -66,22 +67,22 @@ class AudioEffectDelay : public AudioEffect {
MAX_TAPS = 2
};
- float dry;
+ float dry = 1.0f;
- bool tap_1_active;
- float tap_1_delay_ms;
- float tap_1_level;
- float tap_1_pan;
+ bool tap_1_active = true;
+ float tap_1_delay_ms = 250.0f;
+ float tap_1_level = -6.0f;
+ float tap_1_pan = 0.2f;
- bool tap_2_active;
- float tap_2_delay_ms;
- float tap_2_level;
- float tap_2_pan;
+ bool tap_2_active = true;
+ float tap_2_delay_ms = 500.0f;
+ float tap_2_level = -12.0f;
+ float tap_2_pan = -0.4f;
- bool feedback_active;
- float feedback_delay_ms;
- float feedback_level;
- float feedback_lowpass;
+ bool feedback_active = false;
+ float feedback_delay_ms = 340.0f;
+ float feedback_level = -6.0f;
+ float feedback_lowpass = 16000.0f;
protected:
static void _bind_methods();
@@ -128,7 +129,7 @@ public:
Ref<AudioEffectInstance> instantiate() override;
- AudioEffectDelay();
+ AudioEffectDelay() {}
};
#endif // AUDIO_EFFECT_DELAY_H
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 6820d796a4..5987ed7bb2 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -41,8 +41,8 @@ void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, Audi
float lpf_ic = 1.0 - lpf_c;
float drive_f = base->drive;
- float pregain_f = Math::db2linear(base->pre_gain);
- float postgain_f = Math::db2linear(base->post_gain);
+ float pregain_f = Math::db_to_linear(base->pre_gain);
+ float postgain_f = Math::db_to_linear(base->post_gain);
float atan_mult = pow(10, drive_f * drive_f * 3.0) - 1.0 + 0.001;
float atan_div = 1.0 / (atanf(atan_mult) * (1.0 + drive_f * 8));
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index 500abd3a6f..14ece8d93e 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -38,7 +38,7 @@ void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame *
EQ::BandProcess *proc_r = bands[1].ptrw();
float *bgain = gains.ptrw();
for (int i = 0; i < band_count; i++) {
- bgain[i] = Math::db2linear(base->gain[i]);
+ bgain[i] = Math::db_to_linear(base->gain[i]);
}
for (int i = 0; i < p_frame_count; i++) {
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index a40af2f13c..1510ee2af7 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -98,9 +98,9 @@ VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB)
class AudioEffectLowPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter);
- void _validate_property(PropertyInfo &property) const override {
- if (property.name == "gain") {
- property.usage = PROPERTY_USAGE_NONE;
+ void _validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "gain") {
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -111,9 +111,9 @@ public:
class AudioEffectHighPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter);
- void _validate_property(PropertyInfo &property) const override {
- if (property.name == "gain") {
- property.usage = PROPERTY_USAGE_NONE;
+ void _validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "gain") {
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -124,9 +124,9 @@ public:
class AudioEffectBandPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter);
- void _validate_property(PropertyInfo &property) const override {
- if (property.name == "gain") {
- property.usage = PROPERTY_USAGE_NONE;
+ void _validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "gain") {
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 7bcd68d48b..99653cf5b6 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -32,11 +32,11 @@
void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
float threshdb = base->threshold;
- float ceiling = Math::db2linear(base->ceiling);
+ float ceiling = Math::db_to_linear(base->ceiling);
float ceildb = base->ceiling;
- float makeup = Math::db2linear(ceildb - threshdb);
+ float makeup = Math::db_to_linear(ceildb - threshdb);
float sc = -base->soft_clip;
- float scv = Math::db2linear(sc);
+ float scv = Math::db_to_linear(sc);
float peakdb = ceildb + 25;
float scmult = Math::abs((ceildb - sc) / (peakdb - sc));
@@ -49,14 +49,14 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFr
float sign1 = (spl1 < 0.0 ? -1.0 : 1.0);
float abs0 = Math::abs(spl0);
float abs1 = Math::abs(spl1);
- float overdb0 = Math::linear2db(abs0) - ceildb;
- float overdb1 = Math::linear2db(abs1) - ceildb;
+ float overdb0 = Math::linear_to_db(abs0) - ceildb;
+ float overdb1 = Math::linear_to_db(abs1) - ceildb;
if (abs0 > scv) {
- spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult));
+ spl0 = sign0 * (scv + Math::db_to_linear(overdb0 * scmult));
}
if (abs1 > scv) {
- spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult));
+ spl1 = sign1 * (scv + Math::db_to_linear(overdb1 * scmult));
}
spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0);
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 9052f8e05e..1254a6740a 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -144,8 +144,8 @@ int AudioDriver::get_total_channels_by_speaker_mode(AudioDriver::SpeakerMode p_m
ERR_FAIL_V(2);
}
-Array AudioDriver::get_device_list() {
- Array list;
+PackedStringArray AudioDriver::get_device_list() {
+ PackedStringArray list;
list.push_back("Default");
@@ -156,8 +156,8 @@ String AudioDriver::get_device() {
return "Default";
}
-Array AudioDriver::capture_get_device_list() {
- Array list;
+PackedStringArray AudioDriver::capture_get_device_list() {
+ PackedStringArray list;
list.push_back("Default");
@@ -547,7 +547,7 @@ void AudioServer::_mix_step() {
AudioFrame peak = AudioFrame(0, 0);
- float volume = Math::db2linear(bus->volume_db);
+ float volume = Math::db_to_linear(bus->volume_db);
if (solo_mode) {
if (!bus->soloed) {
@@ -573,12 +573,12 @@ void AudioServer::_mix_step() {
}
}
- bus->channels.write[k].peak_volume = AudioFrame(Math::linear2db(peak.l + AUDIO_PEAK_OFFSET), Math::linear2db(peak.r + AUDIO_PEAK_OFFSET));
+ bus->channels.write[k].peak_volume = AudioFrame(Math::linear_to_db(peak.l + AUDIO_PEAK_OFFSET), Math::linear_to_db(peak.r + AUDIO_PEAK_OFFSET));
if (!bus->channels[k].used) {
//see if any audio is contained, because channel was not used
- if (MAX(peak.r, peak.l) > Math::db2linear(channel_disable_threshold_db)) {
+ if (MAX(peak.r, peak.l) > Math::db_to_linear(channel_disable_threshold_db)) {
bus->channels.write[k].last_mix_with_audio = mix_frames;
} else if (mix_frames - bus->channels[k].last_mix_with_audio > channel_disable_frames) {
bus->channels.write[k].active = false;
@@ -1637,7 +1637,7 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const {
return state;
}
-Array AudioServer::get_device_list() {
+PackedStringArray AudioServer::get_device_list() {
return AudioDriver::get_singleton()->get_device_list();
}
@@ -1649,7 +1649,7 @@ void AudioServer::set_device(String device) {
AudioDriver::get_singleton()->set_device(device);
}
-Array AudioServer::capture_get_device_list() {
+PackedStringArray AudioServer::capture_get_device_list() {
return AudioDriver::get_singleton()->capture_get_device_list();
}
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 5613267909..588107c25d 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -94,7 +94,7 @@ public:
virtual void start() = 0;
virtual int get_mix_rate() const = 0;
virtual SpeakerMode get_speaker_mode() const = 0;
- virtual Array get_device_list();
+ virtual PackedStringArray get_device_list();
virtual String get_device();
virtual void set_device(String device) {}
virtual void lock() = 0;
@@ -105,7 +105,7 @@ public:
virtual Error capture_stop() { return FAILED; }
virtual void capture_set_device(const String &p_name) {}
virtual String capture_get_device() { return "Default"; }
- virtual Array capture_get_device_list(); // TODO: convert this and get_device_list to PackedStringArray
+ virtual PackedStringArray capture_get_device_list();
virtual float get_latency() { return 0; }
@@ -419,11 +419,11 @@ public:
void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout);
Ref<AudioBusLayout> generate_bus_layout() const;
- Array get_device_list();
+ PackedStringArray get_device_list();
String get_device();
void set_device(String device);
- Array capture_get_device_list();
+ PackedStringArray capture_get_device_list();
String capture_get_device();
void capture_set_device(const String &p_name);
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp
index 91df3afadd..b83b41a571 100644
--- a/servers/camera_server.cpp
+++ b/servers/camera_server.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "camera_server.h"
+#include "core/variant/typed_array.h"
#include "rendering_server.h"
#include "servers/camera/camera_feed.h"
@@ -143,8 +144,8 @@ int CameraServer::get_feed_count() {
return feeds.size();
};
-Array CameraServer::get_feeds() {
- Array return_feeds;
+TypedArray<CameraFeed> CameraServer::get_feeds() {
+ TypedArray<CameraFeed> return_feeds;
int cc = get_feed_count();
return_feeds.resize(cc);
diff --git a/servers/camera_server.h b/servers/camera_server.h
index b70938c34f..c6fb906b3c 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -43,6 +43,8 @@
**/
class CameraFeed;
+template <typename T>
+class TypedArray;
class CameraServer : public Object {
GDCLASS(CameraServer, Object);
@@ -100,7 +102,7 @@ public:
// Get our feeds.
Ref<CameraFeed> get_feed(int p_index);
int get_feed_count();
- Array get_feeds();
+ TypedArray<CameraFeed> get_feeds();
// Intended for use with custom CameraServer implementation.
RID feed_texture(int p_id, FeedImage p_texture);
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index e9bc28873b..22f42ca343 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -44,40 +44,49 @@ 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, Key p_accel, int p_index) {
+int 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.");
+ return -1;
}
-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) {
+int 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.");
+ return -1;
}
-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) {
+int 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.");
+ return -1;
}
-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) {
+int 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.");
+ return -1;
}
-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) {
+int 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.");
+ return -1;
}
-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) {
+int 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.");
+ return -1;
}
-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) {
+int 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.");
+ return -1;
}
-void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
+int 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.");
+ return -1;
}
-void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) {
+int DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const {
@@ -159,6 +168,11 @@ Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_roo
return Ref<Texture2D>();
}
+int DisplayServer::global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return 0;
+}
+
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.");
}
@@ -207,6 +221,10 @@ void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_i
WARN_PRINT("Global menus not supported by this display server.");
}
+void DisplayServer::global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level) {
+ 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;
@@ -238,14 +256,14 @@ void DisplayServer::tts_resume() {
WARN_PRINT("TTS is not supported by this display server.");
}
-Array DisplayServer::tts_get_voices() const {
+TypedArray<Dictionary> DisplayServer::tts_get_voices() const {
WARN_PRINT("TTS is not supported by this display server.");
- return Array();
+ return TypedArray<Dictionary>();
}
PackedStringArray DisplayServer::tts_get_voices_for_language(const String &p_language) const {
PackedStringArray ret;
- Array voices = tts_get_voices();
+ TypedArray<Dictionary> 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)) {
@@ -400,7 +418,7 @@ String DisplayServer::ime_get_text() const {
ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server.");
}
-void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
+void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
WARN_PRINT("Virtual keyboard not supported by this display server.");
}
@@ -494,11 +512,11 @@ int64_t DisplayServer::window_get_native_handle(HandleType p_handle_type, Window
}
void DisplayServer::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
- WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ WARN_PRINT("Changing the V-Sync mode is not supported by this display server.");
}
DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) const {
- WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ WARN_PRINT("Changing the V-Sync mode is not supported by this display server.");
return VSyncMode::VSYNC_ENABLED;
}
@@ -535,6 +553,7 @@ void DisplayServer::_bind_methods() {
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_get_item_indentation_level", "menu_root", "idx"), &DisplayServer::global_menu_get_item_indentation_level);
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);
@@ -549,6 +568,7 @@ void DisplayServer::_bind_methods() {
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_set_item_indentation_level", "menu_root", "idx", "level"), &DisplayServer::global_menu_set_item_indentation_level);
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);
@@ -643,6 +663,8 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_flag", "flag", "enabled", "window_id"), &DisplayServer::window_set_flag, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_flag", "flag", "window_id"), &DisplayServer::window_get_flag, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_get_safe_title_margins", "window_id"), &DisplayServer::window_get_safe_title_margins, DEFVAL(MAIN_WINDOW_ID));
+
ClassDB::bind_method(D_METHOD("window_request_attention", "window_id"), &DisplayServer::window_request_attention, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_move_to_foreground", "window_id"), &DisplayServer::window_move_to_foreground, DEFVAL(MAIN_WINDOW_ID));
@@ -657,10 +679,13 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_maximize_on_title_dbl_click"), &DisplayServer::window_maximize_on_title_dbl_click);
+ ClassDB::bind_method(D_METHOD("window_minimize_on_title_dbl_click"), &DisplayServer::window_minimize_on_title_dbl_click);
+
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
- ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "type", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(KEYBOARD_TYPE_DEFAULT), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
@@ -713,6 +738,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS);
BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY);
BIND_ENUM_CONSTANT(FEATURE_TEXT_TO_SPEECH);
+ BIND_ENUM_CONSTANT(FEATURE_EXTEND_TO_TITLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
@@ -732,6 +758,15 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(SCREEN_SENSOR_PORTRAIT);
BIND_ENUM_CONSTANT(SCREEN_SENSOR);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL);
+
BIND_ENUM_CONSTANT(CURSOR_ARROW);
BIND_ENUM_CONSTANT(CURSOR_IBEAM);
BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND);
@@ -763,6 +798,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_FLAG_TRANSPARENT);
BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS);
BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP);
+ BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE);
BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX);
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER);
diff --git a/servers/display_server.h b/servers/display_server.h
index 7a15df2f92..0b162fe491 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -122,20 +122,21 @@ public:
FEATURE_KEEP_SCREEN_ON,
FEATURE_CLIPBOARD_PRIMARY,
FEATURE_TEXT_TO_SPEECH,
+ FEATURE_EXTEND_TO_TITLE,
};
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 = 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_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 int 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 int 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 int 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 int 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 int 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 int 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 int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1);
+ virtual int 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;
@@ -153,6 +154,7 @@ public:
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 int global_menu_get_item_indentation_level(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);
@@ -167,6 +169,7 @@ public:
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 void global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level);
virtual int global_menu_get_item_count(const String &p_menu_root) const;
@@ -196,7 +199,7 @@ private:
public:
virtual bool tts_is_speaking() const;
virtual bool tts_is_paused() const;
- virtual Array tts_get_voices() const;
+ virtual TypedArray<Dictionary> 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);
@@ -228,7 +231,7 @@ 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 TypedArray<Rect2> get_display_cutouts() const { return TypedArray<Rect2>(); }
virtual Rect2i get_display_safe_area() const { return screen_get_usable_rect(); }
enum {
@@ -287,6 +290,7 @@ public:
WINDOW_FLAG_TRANSPARENT,
WINDOW_FLAG_NO_FOCUS,
WINDOW_FLAG_POPUP,
+ WINDOW_FLAG_EXTEND_TO_TITLE,
WINDOW_FLAG_MAX,
};
@@ -298,6 +302,7 @@ public:
WINDOW_FLAG_TRANSPARENT_BIT = (1 << WINDOW_FLAG_TRANSPARENT),
WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS),
WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP),
+ WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE),
};
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
@@ -369,6 +374,8 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0;
+ virtual Vector2i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector2i(); };
+
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual bool can_any_window_draw() const = 0;
@@ -376,13 +383,27 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual bool window_maximize_on_title_dbl_click() const { return false; }
+ virtual bool window_minimize_on_title_dbl_click() const { return false; }
+
// necessary for GL focus, may be able to use one of the existing functions for this, not sure yet
virtual void gl_window_make_current(DisplayServer::WindowID p_window_id);
virtual Point2i ime_get_selection() const;
virtual String ime_get_text() const;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
+ enum VirtualKeyboardType {
+ KEYBOARD_TYPE_DEFAULT,
+ KEYBOARD_TYPE_MULTILINE,
+ KEYBOARD_TYPE_NUMBER,
+ KEYBOARD_TYPE_NUMBER_DECIMAL,
+ KEYBOARD_TYPE_PHONE,
+ KEYBOARD_TYPE_EMAIL_ADDRESS,
+ KEYBOARD_TYPE_PASSWORD,
+ KEYBOARD_TYPE_URL
+ };
+
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void virtual_keyboard_hide();
// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
@@ -467,6 +488,7 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation)
VARIANT_ENUM_CAST(DisplayServer::WindowMode)
VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
VARIANT_ENUM_CAST(DisplayServer::HandleType)
+VARIANT_ENUM_CAST(DisplayServer::VirtualKeyboardType);
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent)
diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp
index 3694dcdb9a..7d797bf611 100644
--- a/servers/extensions/physics_server_3d_extension.cpp
+++ b/servers/extensions/physics_server_3d_extension.cpp
@@ -196,6 +196,9 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask");
GDVIRTUAL_BIND(_body_get_collision_mask, "body");
+ GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority");
+ GDVIRTUAL_BIND(_body_get_collision_priority, "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");
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
index c4b4a00eaf..3200438253 100644
--- a/servers/extensions/physics_server_3d_extension.h
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -319,6 +319,9 @@ public:
EXBIND2(body_set_collision_mask, RID, uint32_t)
EXBIND1RC(uint32_t, body_get_collision_mask, RID)
+ EXBIND2(body_set_collision_priority, RID, real_t)
+ EXBIND1RC(real_t, body_get_collision_priority, RID)
+
EXBIND2(body_set_user_flags, RID, uint32_t)
EXBIND1RC(uint32_t, body_get_user_flags, RID)
diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp
index 40b2b2539e..2164dca29e 100644
--- a/servers/movie_writer/movie_writer.cpp
+++ b/servers/movie_writer/movie_writer.cpp
@@ -191,7 +191,7 @@ void MovieWriter::end() {
if (movie_path.is_relative_path()) {
// Print absolute path to make finding the file easier,
// and to make it clickable in terminal emulators that support this.
- movie_path = ProjectSettings::get_singleton()->globalize_path("res://").plus_file(movie_path);
+ movie_path = ProjectSettings::get_singleton()->globalize_path("res://").path_join(movie_path);
}
print_line(vformat("Done recording movie at path: %s", movie_path));
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 5e9f1c824a..0f73df8894 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -158,12 +158,53 @@ void NavigationServer2D::_emit_map_changed(RID p_map) {
emit_signal(SNAME("map_changed"), p_map);
}
+#ifdef DEBUG_ENABLED
+void NavigationServer2D::set_debug_enabled(bool p_enabled) {
+ NavigationServer3D::get_singleton_mut()->set_debug_enabled(p_enabled);
+}
+bool NavigationServer2D::get_debug_enabled() const {
+ return NavigationServer3D::get_singleton()->get_debug_enabled();
+}
+
+void NavigationServer2D::set_debug_navigation_edge_connection_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_edge_connection_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_edge_connection_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_edge_connection_color();
+}
+
+void NavigationServer2D::set_debug_navigation_geometry_face_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_geometry_face_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
+}
+
+void NavigationServer2D::set_debug_navigation_geometry_face_disabled_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_disabled_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_geometry_face_disabled_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color();
+}
+
+void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(p_value);
+}
+
+bool NavigationServer2D::get_debug_navigation_enable_edge_connections() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections();
+}
+#endif // DEBUG_ENABLED
+
void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_maps"), &NavigationServer2D::get_maps);
ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create);
ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active);
- ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer2D::map_is_active);
+ ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer2D::map_is_active);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size);
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);
@@ -196,7 +237,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_neighbor_distance", "agent", "distance"), &NavigationServer2D::agent_set_neighbor_distance);
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);
ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer2D::agent_set_radius);
@@ -222,11 +263,11 @@ NavigationServer2D::~NavigationServer2D() {
singleton = nullptr;
}
-Array FORWARD_0_C(get_maps);
+TypedArray<RID> FORWARD_0_C(get_maps);
-Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid);
+TypedArray<RID> 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);
+TypedArray<RID> 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);
@@ -282,7 +323,7 @@ RID NavigationServer2D::agent_create() const {
void FORWARD_2_C(agent_set_map, RID, p_agent, RID, p_map, rid_to_rid, rid_to_rid);
-void FORWARD_2_C(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real);
+void FORWARD_2_C(agent_set_neighbor_distance, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real);
void FORWARD_2_C(agent_set_max_neighbors, RID, p_agent, int, p_count, rid_to_rid, int_to_int);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 1b15c7ff37..5e96466d66 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -53,7 +53,7 @@ public:
/// MUST be used in single thread!
static NavigationServer2D *get_singleton_mut() { return singleton; }
- virtual Array get_maps() const;
+ virtual TypedArray<RID> get_maps() const;
/// Create a new map.
virtual RID map_create() const;
@@ -82,8 +82,8 @@ public:
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;
+ virtual TypedArray<RID> map_get_regions(RID p_map) const;
+ virtual TypedArray<RID> map_get_agents(RID p_map) const;
virtual void map_force_update(RID p_map);
@@ -133,7 +133,7 @@ public:
/// time of the simulation. If the number is too
/// low, the simulation will not be safe.
/// Must be non-negative.
- virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const;
+ virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const;
/// The maximum number of other agents this
/// agent takes into account in the navigation.
@@ -184,6 +184,23 @@ public:
NavigationServer2D();
virtual ~NavigationServer2D();
+
+#ifdef DEBUG_ENABLED
+ void set_debug_enabled(bool p_enabled);
+ bool get_debug_enabled() const;
+
+ void set_debug_navigation_edge_connection_color(const Color &p_color);
+ Color get_debug_navigation_edge_connection_color() const;
+
+ void set_debug_navigation_geometry_face_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_color() const;
+
+ void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_disabled_color() const;
+
+ void set_debug_navigation_enable_edge_connections(const bool p_value);
+ bool get_debug_navigation_enable_edge_connections() const;
+#endif // DEBUG_ENABLED
};
#endif // NAVIGATION_SERVER_2D_H
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 52855c5931..466b74bc64 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -41,7 +41,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer3D::map_create);
ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer3D::map_set_active);
- ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer3D::map_is_active);
+ ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer3D::map_is_active);
ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer3D::map_set_up);
ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size);
@@ -79,7 +79,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_neighbor_distance", "agent", "distance"), &NavigationServer3D::agent_set_neighbor_distance);
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);
ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer3D::agent_set_radius);
@@ -123,6 +123,12 @@ NavigationServer3D::NavigationServer3D() {
debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true);
debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true);
debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true);
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // enable NavigationServer3D when in Editor or else navmesh edge connections are invisible
+ // on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this
+ set_debug_enabled(true);
+ }
#endif // DEBUG_ENABLED
}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index f24c0117d1..3213da3d84 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -56,7 +56,7 @@ public:
/// MUST be used in single thread!
static NavigationServer3D *get_singleton_mut();
- virtual Array get_maps() const = 0;
+ virtual TypedArray<RID> get_maps() const = 0;
/// Create a new map.
virtual RID map_create() const = 0;
@@ -93,8 +93,8 @@ public:
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;
+ virtual TypedArray<RID> map_get_regions(RID p_map) const = 0;
+ virtual TypedArray<RID> map_get_agents(RID p_map) const = 0;
virtual void map_force_update(RID p_map) = 0;
@@ -147,7 +147,7 @@ public:
/// time of the simulation. If the number is too
/// low, the simulation will not be safe.
/// Must be non-negative.
- virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const = 0;
+ virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const = 0;
/// The maximum number of other agents this
/// agent takes into account in the navigation.
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp
index 96c8dfc69e..af90f96438 100644
--- a/servers/physics_2d/godot_area_2d.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -248,6 +248,10 @@ void GodotArea2D::call_queries() {
Callable::CallError ce;
Variant ret;
monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling event callback method " + Variant::get_callable_error_text(monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_bodies.clear();
@@ -286,6 +290,10 @@ void GodotArea2D::call_queries() {
Callable::CallError ce;
Variant ret;
area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling event callback method " + Variant::get_callable_error_text(area_monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_areas.clear();
diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp
index 268beb1a55..ef6a6b1ae2 100644
--- a/servers/physics_2d/godot_body_2d.cpp
+++ b/servers/physics_2d/godot_body_2d.cpp
@@ -44,7 +44,7 @@ void GodotBody2D::update_mass_properties() {
//update shapes and motions
switch (mode) {
- case PhysicsServer2D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer2D::BODY_MODE_RIGID: {
real_t total_area = 0;
for (int i = 0; i < get_shape_count(); i++) {
if (is_shape_disabled(i)) {
@@ -113,7 +113,7 @@ void GodotBody2D::update_mass_properties() {
_inv_inertia = 0;
_inv_mass = 0;
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: {
_inv_inertia = 0;
_inv_mass = 1.0 / mass;
@@ -160,7 +160,7 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian
real_t mass_value = p_value;
ERR_FAIL_COND(mass_value <= 0);
mass = mass_value;
- if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (mode >= PhysicsServer2D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} break;
@@ -168,13 +168,13 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian
real_t inertia_value = p_value;
if (inertia_value <= 0.0) {
calculate_inertia = true;
- if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer2D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} else {
calculate_inertia = false;
inertia = inertia_value;
- if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer2D::BODY_MODE_RIGID) {
_inv_inertia = 1.0 / inertia;
}
}
@@ -267,7 +267,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) {
first_time_kinematic = true;
}
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer2D::BODY_MODE_RIGID: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
if (!calculate_inertia) {
_inv_inertia = 1.0 / inertia;
@@ -277,7 +277,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) {
set_active(true);
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = 0;
angular_velocity = 0;
@@ -358,7 +358,7 @@ void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p
} break;
case PhysicsServer2D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
+ if (mode >= PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) {
set_active(true);
}
@@ -661,7 +661,7 @@ void GodotBody2D::wakeup_neighbours() {
continue;
}
GodotBody2D *b = n[i];
- if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->mode < PhysicsServer2D::BODY_MODE_RIGID) {
continue;
}
diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h
index 4b87a69d5c..409940d4f8 100644
--- a/servers/physics_2d/godot_body_2d.h
+++ b/servers/physics_2d/godot_body_2d.h
@@ -42,7 +42,7 @@ class GodotConstraint2D;
class GodotPhysicsDirectBodyState2D;
class GodotBody2D : public GodotCollisionObject2D {
- PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
+ PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_RIGID;
Vector2 biased_linear_velocity;
real_t biased_angular_velocity = 0.0;
diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h
index 1a683a7b0f..7965e8a94d 100644
--- a/servers/physics_2d/godot_collision_object_2d.h
+++ b/servers/physics_2d/godot_collision_object_2d.h
@@ -70,6 +70,7 @@ private:
Transform2D inv_transform;
uint32_t collision_mask = 1;
uint32_t collision_layer = 1;
+ real_t collision_priority = 1.0;
bool _static = true;
SelfList<GodotCollisionObject2D> pending_shape_update_list;
@@ -166,6 +167,13 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; }
+ _FORCE_INLINE_ void set_collision_priority(real_t p_priority) {
+ ERR_FAIL_COND_MSG(p_priority <= 0, "Priority must be greater than 0.");
+ collision_priority = p_priority;
+ _shape_changed();
+ }
+ _FORCE_INLINE_ real_t get_collision_priority() const { return collision_priority; }
+
void remove_shape(GodotShape2D *p_shape) override;
void remove_shape(int p_index);
diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp
index 99e68de07c..c728dccd4f 100644
--- a/servers/physics_2d/godot_physics_server_2d.cpp
+++ b/servers/physics_2d/godot_physics_server_2d.cpp
@@ -718,6 +718,20 @@ uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
}
+void GodotPhysicsServer2D::body_set_collision_priority(RID p_body, real_t p_priority) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_priority(p_priority);
+}
+
+real_t GodotPhysicsServer2D::body_get_collision_priority(RID p_body) const {
+ const GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_priority();
+}
+
void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
GodotBody2D *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h
index 2af6e5c97c..20e492d87a 100644
--- a/servers/physics_2d/godot_physics_server_2d.h
+++ b/servers/physics_2d/godot_physics_server_2d.h
@@ -199,6 +199,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override;
virtual uint32_t body_get_collision_mask(RID p_body) const override;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) override;
+ virtual real_t body_get_collision_priority(RID p_body) const override;
+
virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) override;
virtual Variant body_get_param(RID p_body, BodyParameter p_param) const override;
diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp
index 166ec3049e..afcc5af951 100644
--- a/servers/physics_2d/godot_space_2d.cpp
+++ b/servers/physics_2d/godot_space_2d.cpp
@@ -594,6 +594,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
const int max_results = 32;
int recover_attempts = 4;
Vector2 sr[max_results * 2];
+ real_t priorities[max_results];
do {
GodotPhysicsServer2D::CollCbkData cbk;
@@ -606,6 +607,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk;
GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk;
+ int priority_amount = 0;
bool collided = false;
@@ -641,7 +643,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) {
const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj);
- if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
@@ -664,6 +666,10 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
+ while (cbk.amount > priority_amount) {
+ priorities[priority_amount] = col_obj->get_collision_priority();
+ priority_amount++;
+ }
if (!did_collide && cbk.invalid_by_dir > 0) {
//this shape must be excluded
@@ -686,6 +692,12 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
break;
}
+ real_t inv_total_weight = 0.0;
+ for (int i = 0; i < cbk.amount; i++) {
+ inv_total_weight += priorities[i];
+ }
+ inv_total_weight = Math::is_zero_approx(inv_total_weight) ? 1.0 : (real_t)cbk.amount / inv_total_weight;
+
recovered = true;
Vector2 recover_motion;
@@ -701,7 +713,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
real_t depth = n.dot(a + recover_motion) - d;
if (depth > min_contact_depth + CMP_EPSILON) {
// Only recover if there is penetration.
- recover_motion -= n * (depth - min_contact_depth) * 0.4;
+ recover_motion -= n * (depth - min_contact_depth) * 0.4 * priorities[i] * inv_total_weight;
}
}
@@ -936,7 +948,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) {
const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj);
- if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
@@ -1206,7 +1218,7 @@ GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() {
GodotSpace2D::GodotSpace2D() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
- body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0));
+ body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp
index 0603458acd..46718c8819 100644
--- a/servers/physics_2d/godot_step_2d.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -42,7 +42,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D
p_body->set_island_step(_step);
if (p_body->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) {
- // Only dynamic bodies are tested for activation.
+ // Only rigid bodies are tested for activation.
p_body_island.push_back(p_body);
}
diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp
index fdb9f42b40..9765d0bf58 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -277,6 +277,10 @@ void GodotArea3D::call_queries() {
Callable::CallError ce;
Variant ret;
monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling monitor callback method " + Variant::get_callable_error_text(monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_bodies.clear();
@@ -315,6 +319,10 @@ void GodotArea3D::call_queries() {
Callable::CallError ce;
Variant ret;
area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling area monitor callback method " + Variant::get_callable_error_text(area_monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_areas.clear();
diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp
index 4c89106839..b632f7f461 100644
--- a/servers/physics_3d/godot_body_3d.cpp
+++ b/servers/physics_3d/godot_body_3d.cpp
@@ -56,7 +56,7 @@ void GodotBody3D::update_mass_properties() {
// Update shapes and motions.
switch (mode) {
- case PhysicsServer3D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer3D::BODY_MODE_RIGID: {
real_t total_area = 0;
for (int i = 0; i < get_shape_count(); i++) {
if (is_shape_disabled(i)) {
@@ -154,7 +154,7 @@ void GodotBody3D::update_mass_properties() {
_inv_inertia = Vector3();
_inv_mass = 0;
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: {
_inv_inertia_tensor.set_zero();
_inv_mass = 1.0 / mass;
@@ -201,7 +201,7 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian
real_t mass_value = p_value;
ERR_FAIL_COND(mass_value <= 0);
mass = mass_value;
- if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode >= PhysicsServer3D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} break;
@@ -209,12 +209,12 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian
inertia = p_value;
if ((inertia.x <= 0.0) || (inertia.y <= 0.0) || (inertia.z <= 0.0)) {
calculate_inertia = true;
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer3D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} else {
calculate_inertia = false;
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer3D::BODY_MODE_RIGID) {
principal_inertia_axes_local = Basis();
_inv_inertia = inertia.inverse();
_update_transform_dependent();
@@ -263,7 +263,7 @@ Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const {
return mass;
} break;
case PhysicsServer3D::BODY_PARAM_INERTIA: {
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer3D::BODY_MODE_RIGID) {
return _inv_inertia.inverse();
} else {
return Vector3();
@@ -315,7 +315,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
_update_transform_dependent();
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer3D::BODY_MODE_RIGID: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
if (!calculate_inertia) {
principal_inertia_axes_local = Basis();
@@ -327,7 +327,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
set_active(true);
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = Vector3();
angular_velocity = Vector3();
@@ -407,7 +407,7 @@ void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p
} break;
case PhysicsServer3D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
+ if (mode >= PhysicsServer3D::BODY_MODE_RIGID && !active && !can_sleep) {
set_active(true);
}
@@ -744,7 +744,7 @@ void GodotBody3D::wakeup_neighbours() {
continue;
}
GodotBody3D *b = n[i];
- if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (b->mode < PhysicsServer3D::BODY_MODE_RIGID) {
continue;
}
diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h
index 93bd5a0071..2153ca4e91 100644
--- a/servers/physics_3d/godot_body_3d.h
+++ b/servers/physics_3d/godot_body_3d.h
@@ -40,7 +40,7 @@ class GodotConstraint3D;
class GodotPhysicsDirectBodyState3D;
class GodotBody3D : public GodotCollisionObject3D {
- PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
+ PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_RIGID;
Vector3 linear_velocity;
Vector3 angular_velocity;
diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h
index 0f09f21962..2d342f65f3 100644
--- a/servers/physics_3d/godot_collision_object_3d.h
+++ b/servers/physics_3d/godot_collision_object_3d.h
@@ -59,6 +59,7 @@ private:
ObjectID instance_id;
uint32_t collision_layer = 1;
uint32_t collision_mask = 1;
+ real_t collision_priority = 1.0;
struct Shape {
Transform3D xform;
@@ -165,6 +166,13 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
+ _FORCE_INLINE_ void set_collision_priority(real_t p_priority) {
+ ERR_FAIL_COND_MSG(p_priority <= 0, "Priority must be greater than 0.");
+ collision_priority = p_priority;
+ _shape_changed();
+ }
+ _FORCE_INLINE_ real_t get_collision_priority() const { return collision_priority; }
+
_FORCE_INLINE_ bool collides_with(GodotCollisionObject3D *p_other) const {
return p_other->collision_layer & collision_mask;
}
diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp
index b2d3e4d876..094d77a582 100644
--- a/servers/physics_3d/godot_collision_solver_3d.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d.cpp
@@ -38,7 +38,7 @@
#define collision_solver sat_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) {
const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
return false;
@@ -70,6 +70,7 @@ bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_s
bool found = false;
for (int i = 0; i < support_count; i++) {
+ supports[i] += p_margin * supports[i].normalized();
supports[i] = p_transform_B.xform(supports[i]);
if (p.distance_to(supports[i]) >= 0) {
continue;
@@ -379,9 +380,9 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T
}
if (swap) {
- return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_A);
} else {
- return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_B);
}
} else if (type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
@@ -456,8 +457,17 @@ bool GodotCollisionSolver3D::solve_distance_world_boundary(const GodotShape3D *p
Vector3 supports[max_supports];
int support_count;
GodotShape3D::FeatureType support_type;
+ Vector3 support_direction = p_transform_B.basis.xform_inv(-p.normal).normalized();
- p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
+ p_shape_B->get_supports(support_direction, max_supports, supports, support_count, support_type);
+
+ if (support_count == 0) { // This is a poor man's way to detect shapes that don't implement get_supports, such as GodotMotionShape3D.
+ Vector3 support_B = p_transform_B.xform(p_shape_B->get_support(support_direction));
+ r_point_A = p.project(support_B);
+ r_point_B = support_B;
+ bool collided = p.distance_to(support_B) <= 0;
+ return collided;
+ }
if (support_type == GodotShape3D::FEATURE_CIRCLE) {
ERR_FAIL_COND_V(support_count != 3, false);
diff --git a/servers/physics_3d/godot_collision_solver_3d.h b/servers/physics_3d/godot_collision_solver_3d.h
index a6a0ebfead..e7d67903e9 100644
--- a/servers/physics_3d/godot_collision_solver_3d.h
+++ b/servers/physics_3d/godot_collision_solver_3d.h
@@ -42,7 +42,7 @@ private:
static void 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);
static bool soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex);
static bool concave_callback(void *p_userdata, GodotShape3D *p_convex);
- static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
static bool solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
static bool solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static bool solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index b735283ebe..9c1535f561 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -593,6 +593,20 @@ uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
}
+void GodotPhysicsServer3D::body_set_collision_priority(RID p_body, real_t p_priority) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_priority(p_priority);
+}
+
+real_t GodotPhysicsServer3D::body_get_collision_priority(RID p_body) const {
+ const GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_priority();
+}
+
void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
GodotBody3D *body = body_owner.get_or_null(p_body);
if (body) {
diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h
index 1d57451925..b429f23a0c 100644
--- a/servers/physics_3d/godot_physics_server_3d.h
+++ b/servers/physics_3d/godot_physics_server_3d.h
@@ -192,6 +192,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override;
virtual uint32_t body_get_collision_mask(RID p_body) const override;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) override;
+ virtual real_t body_get_collision_priority(RID p_body) const override;
+
virtual void body_set_user_flags(RID p_body, uint32_t p_flags) override;
virtual uint32_t body_get_user_flags(RID p_body) const override;
diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp
index 533d7605ce..76d59202c9 100644
--- a/servers/physics_3d/godot_space_3d.cpp
+++ b/servers/physics_3d/godot_space_3d.cpp
@@ -701,6 +701,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
const int max_results = 32;
int recover_attempts = 4;
Vector3 sr[max_results * 2];
+ real_t priorities[max_results];
do {
GodotPhysicsServer3D::CollCbkData cbk;
@@ -710,6 +711,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk;
GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk;
+ int priority_amount = 0;
bool collided = false;
@@ -737,6 +739,10 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
if (GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, margin)) {
collided = cbk.amount > 0;
}
+ while (cbk.amount > priority_amount) {
+ priorities[priority_amount] = col_obj->get_collision_priority();
+ priority_amount++;
+ }
}
}
@@ -744,6 +750,12 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
break;
}
+ real_t inv_total_weight = 0.0;
+ for (int i = 0; i < cbk.amount; i++) {
+ inv_total_weight += priorities[i];
+ }
+ inv_total_weight = Math::is_zero_approx(inv_total_weight) ? 1.0 : (real_t)cbk.amount / inv_total_weight;
+
recovered = true;
Vector3 recover_motion;
@@ -759,7 +771,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
real_t depth = n.dot(a + recover_motion) - d;
if (depth > min_contact_depth + CMP_EPSILON) {
// Only recover if there is penetration.
- recover_motion -= n * (depth - min_contact_depth) * 0.4;
+ recover_motion -= n * (depth - min_contact_depth) * 0.4 * priorities[i] * inv_total_weight;
}
}
@@ -989,6 +1001,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
r_result->collision_unsafe_fraction = unsafe;
r_result->collision_count = rcd.result_count;
+ r_result->collision_depth = rcd.best_result.len;
}
collided = true;
@@ -1002,6 +1015,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
r_result->collision_safe_fraction = 1.0;
r_result->collision_unsafe_fraction = 1.0;
+ r_result->collision_depth = 0.0;
}
return collided;
@@ -1235,7 +1249,7 @@ GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() {
GodotSpace3D::GodotSpace3D() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
- body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0));
+ body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp
index f384c829a4..bfedcd29c0 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -44,7 +44,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D
p_body->set_island_step(_step);
if (p_body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) {
- // Only dynamic bodies are tested for activation.
+ // Only rigid bodies are tested for activation.
p_body_island.push_back(p_body);
}
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 41aae36785..ca9c9c8fc4 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/string/print_string.h"
+#include "core/variant/typed_array.h"
PhysicsServer2D *PhysicsServer2D::singleton = nullptr;
@@ -147,6 +148,16 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {}
///////////////////////////////////////////////////////
+Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) {
+ Ref<PhysicsRayQueryParameters2D> params;
+ params.instantiate();
+ params->set_from(p_from);
+ params->set_to(p_to);
+ params->set_collision_mask(p_mask);
+ params->set_exclude(p_exclude);
+ return params;
+}
+
void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
@@ -165,6 +176,8 @@ Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const {
}
void PhysicsRayQueryParameters2D::_bind_methods() {
+ ClassDB::bind_static_method("PhysicsRayQueryParameters2D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters2D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>()));
+
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from);
@@ -335,7 +348,7 @@ Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Ref<PhysicsRayQueryPa
return d;
}
-Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) {
+TypedArray<Dictionary> PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) {
ERR_FAIL_COND_V(p_point_query.is_null(), Array());
Vector<ShapeResult> ret;
@@ -344,10 +357,10 @@ Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryPar
int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size());
if (rc == 0) {
- return Array();
+ return TypedArray<Dictionary>();
}
- Array r;
+ TypedArray<Dictionary> r;
r.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -360,13 +373,13 @@ Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryPar
return r;
}
-Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+TypedArray<Dictionary> PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), TypedArray<Dictionary>());
Vector<ShapeResult> sr;
sr.resize(p_max_results);
int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size());
- Array ret;
+ TypedArray<Dictionary> ret;
ret.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -380,22 +393,22 @@ Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryPar
return ret;
}
-Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+Vector<real_t> PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), Vector<real_t>());
real_t closest_safe, closest_unsafe;
bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe);
if (!res) {
- return Array();
+ return Vector<real_t>();
}
- Array ret;
+ Vector<real_t> ret;
ret.resize(2);
- ret[0] = closest_safe;
- ret[1] = closest_unsafe;
+ ret.write[0] = closest_safe;
+ ret.write[1] = closest_unsafe;
return ret;
}
-Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
+TypedArray<PackedVector2Array> PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<Vector2> ret;
@@ -403,9 +416,9 @@ Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParam
int rc = 0;
bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc);
if (!res) {
- return Array();
+ return TypedArray<PackedVector2Array>();
}
- Array r;
+ TypedArray<PackedVector2Array> r;
r.resize(rc * 2);
for (int i = 0; i < rc * 2; i++) {
r[i] = ret[i];
@@ -694,6 +707,9 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer2D::body_set_collision_mask);
ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer2D::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_priority", "body", "priority"), &PhysicsServer2D::body_set_collision_priority);
+ ClassDB::bind_method(D_METHOD("body_get_collision_priority", "body"), &PhysicsServer2D::body_get_collision_priority);
+
ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer2D::body_set_param);
ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer2D::body_get_param);
@@ -801,8 +817,8 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 7a821c64e6..071ff5ffe9 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -36,6 +36,8 @@
#include "core/object/ref_counted.h"
class PhysicsDirectSpaceState2D;
+template <typename T>
+class TypedArray;
class PhysicsDirectBodyState2D : public Object {
GDCLASS(PhysicsDirectBodyState2D, Object);
@@ -114,10 +116,10 @@ class PhysicsDirectSpaceState2D : public Object {
GDCLASS(PhysicsDirectSpaceState2D, Object);
Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query);
- Array _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32);
- Array _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
- Array _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
- Array _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
+ Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
+ TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
protected:
@@ -346,8 +348,8 @@ public:
enum BodyMode {
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
- BODY_MODE_DYNAMIC,
- BODY_MODE_DYNAMIC_LINEAR,
+ BODY_MODE_RIGID,
+ BODY_MODE_RIGID_LINEAR,
};
virtual RID body_create() = 0;
@@ -393,6 +395,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0;
virtual uint32_t body_get_collision_mask(RID p_body) const = 0;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) = 0;
+ virtual real_t body_get_collision_priority(RID p_body) const = 0;
+
// common body variables
enum BodyParameter {
BODY_PARAM_BOUNCE,
@@ -605,6 +610,7 @@ protected:
static void _bind_methods();
public:
+ static Ref<PhysicsRayQueryParameters2D> create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude);
const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector2 &p_from) { parameters.from = p_from; }
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index ddb071f603..d080aac438 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -205,6 +205,9 @@ public:
FUNC2(body_set_collision_mask, RID, uint32_t);
FUNC1RC(uint32_t, body_get_collision_mask, RID);
+ FUNC2(body_set_collision_priority, RID, real_t);
+ FUNC1RC(real_t, body_get_collision_priority, RID);
+
FUNC3(body_set_param, RID, BodyParameter, const Variant &);
FUNC2RC(Variant, body_get_param, RID, BodyParameter);
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index a606d055f7..fc32e1f665 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/string/print_string.h"
+#include "core/variant/typed_array.h"
void PhysicsServer3DRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) {
GDVIRTUAL_REQUIRED_CALL(_set_vertex, p_vertex_id, p_vector3);
@@ -184,6 +185,8 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const {
}
void PhysicsRayQueryParameters3D::_bind_methods() {
+ ClassDB::bind_static_method("PhysicsRayQueryParameters3D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters3D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>()));
+
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from);
@@ -220,6 +223,16 @@ void PhysicsRayQueryParameters3D::_bind_methods() {
///////////////////////////////////////////////////////
+Ref<PhysicsRayQueryParameters3D> PhysicsRayQueryParameters3D::create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) {
+ Ref<PhysicsRayQueryParameters3D> params;
+ params.instantiate();
+ params->set_from(p_from);
+ params->set_to(p_to);
+ params->set_collision_mask(p_mask);
+ params->set_exclude(p_exclude);
+ return params;
+}
+
void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
@@ -354,8 +367,8 @@ Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryPa
return d;
}
-Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) {
- ERR_FAIL_COND_V(p_point_query.is_null(), Array());
+TypedArray<Dictionary> PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) {
+ ERR_FAIL_COND_V(p_point_query.is_null(), TypedArray<Dictionary>());
Vector<ShapeResult> ret;
ret.resize(p_max_results);
@@ -363,10 +376,10 @@ Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryPar
int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size());
if (rc == 0) {
- return Array();
+ return TypedArray<Dictionary>();
}
- Array r;
+ TypedArray<Dictionary> r;
r.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -379,13 +392,13 @@ Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryPar
return r;
}
-Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+TypedArray<Dictionary> PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), TypedArray<Dictionary>());
Vector<ShapeResult> sr;
sr.resize(p_max_results);
int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size());
- Array ret;
+ TypedArray<Dictionary> ret;
ret.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -399,22 +412,22 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar
return ret;
}
-Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+Vector<real_t> PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), Vector<real_t>());
real_t closest_safe = 1.0f, closest_unsafe = 1.0f;
bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe);
if (!res) {
- return Array();
+ return Vector<real_t>();
}
- Array ret;
+ Vector<real_t> ret;
ret.resize(2);
- ret[0] = closest_safe;
- ret[1] = closest_unsafe;
+ ret.write[0] = closest_safe;
+ ret.write[1] = closest_unsafe;
return ret;
}
-Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
+TypedArray<PackedVector2Array> PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<Vector3> ret;
@@ -422,9 +435,9 @@ Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParam
int rc = 0;
bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc);
if (!res) {
- return Array();
+ return TypedArray<PackedVector2Array>();
}
- Array r;
+ TypedArray<PackedVector2Array> r;
r.resize(rc * 2);
for (int i = 0; i < rc * 2; i++) {
r[i] = ret[i];
@@ -738,6 +751,9 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer3D::body_set_collision_mask);
ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer3D::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_priority", "body", "priority"), &PhysicsServer3D::body_set_collision_priority);
+ ClassDB::bind_method(D_METHOD("body_get_collision_priority", "body"), &PhysicsServer3D::body_get_collision_priority);
+
ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer3D::body_add_shape, DEFVAL(Transform3D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer3D::body_set_shape);
ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer3D::body_set_shape_transform);
@@ -972,8 +988,8 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 86a41d96ef..6237ed67aa 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -38,6 +38,8 @@
#include "core/variant/native_ptr.h"
class PhysicsDirectSpaceState3D;
+template <typename T>
+class TypedArray;
class PhysicsDirectBodyState3D : public Object {
GDCLASS(PhysicsDirectBodyState3D, Object);
@@ -120,10 +122,10 @@ class PhysicsDirectSpaceState3D : public Object {
private:
Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query);
- Array _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32);
- Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
- Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
- Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
+ Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
+ TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
protected:
@@ -379,8 +381,8 @@ public:
enum BodyMode {
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
- BODY_MODE_DYNAMIC,
- BODY_MODE_DYNAMIC_LINEAR,
+ BODY_MODE_RIGID,
+ BODY_MODE_RIGID_LINEAR,
};
enum BodyDampMode {
@@ -421,6 +423,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0;
virtual uint32_t body_get_collision_mask(RID p_body) const = 0;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) = 0;
+ virtual real_t body_get_collision_priority(RID p_body) const = 0;
+
virtual void body_set_user_flags(RID p_body, uint32_t p_flags) = 0;
virtual uint32_t body_get_user_flags(RID p_body) const = 0;
@@ -550,6 +555,7 @@ public:
struct MotionResult {
Vector3 travel;
Vector3 remainder;
+ real_t collision_depth = 0.0;
real_t collision_safe_fraction = 0.0;
real_t collision_unsafe_fraction = 0.0;
@@ -816,6 +822,7 @@ protected:
static void _bind_methods();
public:
+ static Ref<PhysicsRayQueryParameters3D> create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude);
const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector3 &p_from) { parameters.from = p_from; }
diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index d4a4ad3132..ed4546b240 100644
--- a/servers/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -202,6 +202,9 @@ public:
FUNC2(body_set_collision_mask, RID, uint32_t);
FUNC1RC(uint32_t, body_get_collision_mask, RID);
+ FUNC2(body_set_collision_priority, RID, real_t);
+ FUNC1RC(real_t, body_get_collision_priority, RID);
+
FUNC2(body_set_user_flags, RID, uint32_t);
FUNC1RC(uint32_t, body_get_user_flags, RID);
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
index be98770b90..8d3a45d696 100644
--- a/servers/rendering/dummy/rasterizer_scene_dummy.h
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -31,12 +31,65 @@
#ifndef RASTERIZER_SCENE_DUMMY_H
#define RASTERIZER_SCENE_DUMMY_H
+#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_scene_render.h"
+#include "storage/utilities.h"
class RasterizerSceneDummy : public RendererSceneRender {
public:
- RenderGeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
- void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override {}
+ class GeometryInstanceDummy : public RenderGeometryInstance {
+ public:
+ GeometryInstanceDummy() {}
+
+ virtual void _mark_dirty() override {}
+
+ virtual void set_skeleton(RID p_skeleton) override {}
+ virtual void set_material_override(RID p_override) override {}
+ virtual void set_material_overlay(RID p_overlay) override {}
+ virtual void set_surface_materials(const Vector<RID> &p_materials) override {}
+ virtual void set_mesh_instance(RID p_mesh_instance) override {}
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override {}
+ virtual void set_lod_bias(float p_lod_bias) override {}
+ virtual void set_layer_mask(uint32_t p_layer_mask) override {}
+ virtual void set_fade_range(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 {}
+ virtual void set_parent_fade_alpha(float p_alpha) override {}
+ virtual void set_transparency(float p_transparency) override {}
+ virtual void set_use_baked_light(bool p_enable) override {}
+ virtual void set_use_dynamic_gi(bool p_enable) override {}
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
+ virtual void set_lightmap_capture(const Color *p_sh9) override {}
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override {}
+ virtual void set_cast_double_sided_shadows(bool p_enable) override {}
+
+ virtual Transform3D get_transform() override { return Transform3D(); }
+ virtual AABB get_aabb() override { return AABB(); }
+
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
+
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override {}
+ };
+
+ PagedAllocator<GeometryInstanceDummy> geometry_instance_alloc;
+
+public:
+ RenderGeometryInstance *geometry_instance_create(RID p_base) override {
+ RS::InstanceType type = RendererDummy::Utilities::get_singleton()->get_base_type(p_base);
+ ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
+
+ GeometryInstanceDummy *ginstance = geometry_instance_alloc.alloc();
+
+ return ginstance;
+ }
+
+ void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override {
+ GeometryInstanceDummy *ginstance = static_cast<GeometryInstanceDummy *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+
+ geometry_instance_alloc.free(ginstance);
+ }
uint32_t geometry_instance_get_pair_mask() override { return 0; }
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index 55c42330cf..e25a2ac3a9 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -66,7 +66,7 @@ public:
virtual void shader_set_path_hint(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_get_shader_uniform_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(); }
@@ -89,7 +89,7 @@ public:
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_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
};
diff --git a/servers/rendering/dummy/storage/mesh_storage.cpp b/servers/rendering/dummy/storage/mesh_storage.cpp
new file mode 100644
index 0000000000..adf736eee3
--- /dev/null
+++ b/servers/rendering/dummy/storage/mesh_storage.cpp
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* 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 RendererDummy;
+
+MeshStorage *MeshStorage::singleton = nullptr;
+
+MeshStorage::MeshStorage() {
+ singleton = this;
+}
+
+MeshStorage::~MeshStorage() {
+ singleton = nullptr;
+}
+
+RID MeshStorage::mesh_allocate() {
+ return mesh_owner.allocate_rid();
+}
+
+void MeshStorage::mesh_initialize(RID p_rid) {
+ mesh_owner.initialize_rid(p_rid, DummyMesh());
+}
+
+void MeshStorage::mesh_free(RID p_rid) {
+ DummyMesh *mesh = mesh_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!mesh);
+
+ mesh_owner.free(p_rid);
+}
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index 8dfcd978ac..1eb4fd854f 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -31,23 +31,57 @@
#ifndef MESH_STORAGE_DUMMY_H
#define MESH_STORAGE_DUMMY_H
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
#include "servers/rendering/storage/mesh_storage.h"
-#include "servers/rendering/storage/utilities.h"
namespace RendererDummy {
class MeshStorage : public RendererMeshStorage {
+private:
+ static MeshStorage *singleton;
+
+ struct DummyMesh {
+ Vector<RS::SurfaceData> surfaces;
+ int blend_shape_count;
+ RS::BlendShapeMode blend_shape_mode;
+ PackedFloat32Array blend_shape_values;
+ };
+
+ mutable RID_Owner<DummyMesh> mesh_owner;
+
public:
+ static MeshStorage *get_singleton() {
+ return singleton;
+ };
+
+ MeshStorage();
+ ~MeshStorage();
+
/* 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 {}
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+
+ virtual RID mesh_allocate() override;
+ 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 void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!m);
+ m->surfaces.push_back(RS::SurfaceData());
+ RS::SurfaceData *s = &m->surfaces.write[m->surfaces.size() - 1];
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+ s->vertex_data = p_surface.vertex_data;
+ s->attribute_data = p_surface.attribute_data;
+ s->vertex_count = p_surface.vertex_count;
+ s->index_data = p_surface.index_data;
+ s->index_count = p_surface.index_count;
+ }
virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
@@ -61,8 +95,18 @@ public:
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 RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!m, RS::SurfaceData());
+ RS::SurfaceData s = m->surfaces[p_surface];
+ return s;
+ }
+
+ virtual int mesh_get_surface_count(RID p_mesh) const override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+ return m->surfaces.size();
+ }
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(); }
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 73b1284558..c15b656d06 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -69,7 +69,6 @@ public:
/* 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 {
@@ -159,6 +158,7 @@ public:
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_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) 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; }
diff --git a/servers/rendering/dummy/storage/utilities.cpp b/servers/rendering/dummy/storage/utilities.cpp
new file mode 100644
index 0000000000..125ed81917
--- /dev/null
+++ b/servers/rendering/dummy/storage/utilities.cpp
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* utilities.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 "utilities.h"
+
+using namespace RendererDummy;
+
+Utilities *Utilities::singleton = nullptr;
+
+Utilities::Utilities() {
+ singleton = this;
+}
+
+Utilities::~Utilities() {
+ singleton = nullptr;
+}
diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h
index b94f678c75..cb7b2a2b63 100644
--- a/servers/rendering/dummy/storage/utilities.h
+++ b/servers/rendering/dummy/storage/utilities.h
@@ -31,20 +31,38 @@
#ifndef UTILITIES_DUMMY_H
#define UTILITIES_DUMMY_H
+#include "mesh_storage.h"
#include "servers/rendering/storage/utilities.h"
#include "texture_storage.h"
namespace RendererDummy {
class Utilities : public RendererUtilities {
+private:
+ static Utilities *singleton;
+
public:
+ static Utilities *get_singleton() { return singleton; }
+
+ Utilities();
+ ~Utilities();
+
/* INSTANCES */
- virtual RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
+ virtual RS::InstanceType get_base_type(RID p_rid) const override {
+ if (RendererDummy::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ return RS::INSTANCE_MESH;
+ }
+ return RS::INSTANCE_NONE;
+ }
+
virtual 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;
+ } else if (RendererDummy::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ RendererDummy::MeshStorage::get_singleton()->mesh_free(p_rid);
+ return true;
}
return false;
}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 6da48fde9c..aa9772a483 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -605,9 +605,13 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
if (p_antialiased) {
- float border_size = 2.0;
- if (p_width < border_size) {
- border_size = p_width;
+ // Use the same antialiasing feather size as StyleBoxFlat's default
+ // (but doubled, as it's specified for both sides here).
+ // This value is empirically determined to provide good antialiasing quality
+ // while not making lines appear too soft.
+ float border_size = 1.25f;
+ if (p_width < 1.0f) {
+ border_size *= p_width;
}
Vector2 dir2 = diff.normalized();
@@ -774,9 +778,13 @@ 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;
+ // Use the same antialiasing feather size as StyleBoxFlat's default
+ // (but doubled, as it's specified for both sides here).
+ // This value is empirically determined to provide good antialiasing quality
+ // while not making lines appear too soft.
+ float border_size = 1.25f;
+ if (p_width < 1.0f) {
+ border_size *= p_width;
}
Color color2 = Color(1, 1, 1, 0);
@@ -1175,6 +1183,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
rect->px_range = p_px_range;
}
+void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
+ ERR_FAIL_COND(!rect);
+ rect->modulate = p_modulate;
+ rect->rect = p_rect;
+
+ rect->texture = p_texture;
+
+ rect->source = p_src_rect;
+ rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD;
+
+ if (p_rect.size.x < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->rect.size.x = -rect->rect.size.x;
+ }
+ if (p_src_rect.size.x < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->source.size.x = -rect->source.size.x;
+ }
+ if (p_rect.size.y < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->rect.size.y = -rect->rect.size.y;
+ }
+ if (p_src_rect.size.y < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->source.size.y = -rect->source.size.y;
+ }
+}
+
void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index e8c54310c9..0d6a4006f8 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -225,6 +225,7 @@ public:
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0);
+ void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID());
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 11a7d34291..6791ed9626 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -46,6 +46,7 @@ public:
CANVAS_RECT_CLIP_UV = 32,
CANVAS_RECT_IS_GROUP = 64,
CANVAS_RECT_MSDF = 128,
+ CANVAS_RECT_LCD = 256,
};
struct Light {
@@ -193,7 +194,7 @@ public:
Rect2 rect;
Color modulate;
Rect2 source;
- uint8_t flags;
+ uint16_t flags;
float outline;
float px_range;
diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp
index 3a9bab022c..675659f4c8 100644
--- a/servers/rendering/renderer_geometry_instance.cpp
+++ b/servers/rendering/renderer_geometry_instance.cpp
@@ -117,8 +117,8 @@ void RenderGeometryInstanceBase::set_use_dynamic_gi(bool p_enable) {
_mark_dirty();
}
-void RenderGeometryInstanceBase::set_instance_shader_parameters_offset(int32_t p_offset) {
- shader_parameters_offset = p_offset;
+void RenderGeometryInstanceBase::set_instance_shader_uniforms_offset(int32_t p_offset) {
+ shader_uniforms_offset = p_offset;
_mark_dirty();
}
diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h
index 279566d5c9..fecb9878c2 100644
--- a/servers/rendering/renderer_geometry_instance.h
+++ b/servers/rendering/renderer_geometry_instance.h
@@ -59,7 +59,7 @@ public:
virtual void set_use_dynamic_gi(bool p_enable) = 0;
virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
virtual void set_lightmap_capture(const Color *p_sh9) = 0;
- virtual void set_instance_shader_parameters_offset(int32_t p_offset) = 0;
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) = 0;
virtual void set_cast_double_sided_shadows(bool p_enable) = 0;
virtual Transform3D get_transform() = 0;
@@ -104,7 +104,7 @@ public:
float parent_fade_alpha = 1.0;
float force_alpha = 1.0;
- int32_t shader_parameters_offset = -1;
+ int32_t shader_uniforms_offset = -1;
struct Data {
//data used less often goes into regular heap
@@ -140,7 +140,7 @@ public:
virtual void set_transparency(float p_transparency) override;
virtual void set_use_baked_light(bool p_enable) override;
virtual void set_use_dynamic_gi(bool p_enable) override;
- virtual void set_instance_shader_parameters_offset(int32_t p_offset) override;
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override;
virtual void set_cast_double_sided_shadows(bool p_enable) override;
virtual Transform3D get_transform() override;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 17ca1986c6..ef17ceb98c 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -269,7 +269,7 @@ public:
//spot
radius *= shared->cone_overfit; // overfit icosphere
- real_t len = Math::tan(Math::deg2rad(p_spot_aperture)) * radius;
+ real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius;
//approximate, probably better to use a cone support function
float max_d = -1e20;
float min_d = 1e20;
@@ -293,7 +293,7 @@ public:
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_column(Vector3::AXIS_Z))));
+ float angle = Math::rad_to_deg(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;
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 0f896a8aa7..874409b885 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -1604,7 +1604,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
ScreenSpaceReflectionFilterPushConstant push_constant;
push_constant.view_index = v;
push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
+ push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]);
push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index a61d1c4d02..257b67cf04 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -378,7 +378,7 @@ void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID
}
}
-void Fog::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void Fog::FogShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
RBMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -500,7 +500,7 @@ Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) {
fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(fog_map, "Fog map");
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
Vector<uint8_t> dm;
dm.resize(fog_size.x * fog_size.y * fog_size.z * 4);
dm.fill(0);
@@ -643,7 +643,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
{
RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
@@ -663,7 +663,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
{
RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
@@ -675,7 +675,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
{
RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
@@ -949,7 +949,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
}
{
RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
@@ -960,7 +960,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
}
{
RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
@@ -972,7 +972,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
{
RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
index 7002d6c872..171f9f3b88 100644
--- a/servers/rendering/renderer_rd/environment/fog.h
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -200,7 +200,7 @@ private:
virtual void set_path_hint(const String &p_hint);
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_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 7cda0337b8..66e984174c 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -1140,6 +1140,7 @@ void GI::SDFGI::erase() {
RD::get_singleton()->free(lightprobe_data);
RD::get_singleton()->free(lightprobe_history_scroll);
+ RD::get_singleton()->free(lightprobe_average_scroll);
RD::get_singleton()->free(occlusion_data);
RD::get_singleton()->free(ambient_texture);
@@ -1591,34 +1592,24 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection
push_constant.max_cascades = cascades.size();
push_constant.screen_size[0] = p_width;
push_constant.screen_size[1] = p_height;
- push_constant.probe_axis_size = probe_axis_count;
- push_constant.use_occlusion = uses_occlusion;
push_constant.y_mult = y_mult;
push_constant.z_near = -p_projections[v].get_z_near();
- 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.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.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;
- push_constant.cam_transform[14] = p_transform.origin.z;
- push_constant.cam_transform[15] = 1;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ push_constant.cam_basis[i][j] = p_transform.basis.rows[j][i];
+ }
+ }
+ push_constant.cam_origin[0] = p_transform.origin[0];
+ push_constant.cam_origin[1] = p_transform.origin[1];
+ push_constant.cam_origin[2] = p_transform.origin[2];
// need to properly unproject for asymmetric projection matrices in stereo..
Projection inv_projection = p_projections[v].inverse();
for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j];
+ for (int j = 0; j < 3; j++) {
+ push_constant.inv_projection[j][i] = inv_projection.matrix[i][j];
}
}
@@ -1933,7 +1924,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
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].cos_spot_angle = Math::cos(Math::deg_to_rad(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++;
@@ -2371,7 +2362,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
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].cos_spot_angle = Math::cos(Math::deg_to_rad(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++;
@@ -2437,18 +2428,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
if (last_probe_data_version != data_version) {
//need to re-create everything
- if (texture.is_valid()) {
- RD::get_singleton()->free(texture);
- RD::get_singleton()->free(write_buffer);
- mipmaps.clear();
- }
-
- for (int i = 0; i < dynamic_maps.size(); i++) {
- RD::get_singleton()->free(dynamic_maps[i].texture);
- RD::get_singleton()->free(dynamic_maps[i].depth);
- }
-
- dynamic_maps.clear();
+ free_resources();
Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
@@ -2820,7 +2800,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
l.color[1] = color.g;
l.color[2] = color.b;
- l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ l.cos_spot_angle = Math::cos(Math::deg_to_rad(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);
@@ -3140,6 +3120,37 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
last_probe_version = gi->voxel_gi_get_version(probe);
}
+void GI::VoxelGIInstance::free_resources() {
+ if (texture.is_valid()) {
+ RD::get_singleton()->free(texture);
+ RD::get_singleton()->free(write_buffer);
+
+ texture = RID();
+ write_buffer = RID();
+ mipmaps.clear();
+ }
+
+ for (int i = 0; i < dynamic_maps.size(); i++) {
+ RD::get_singleton()->free(dynamic_maps[i].texture);
+ RD::get_singleton()->free(dynamic_maps[i].depth);
+
+ // these only exist on the first level...
+ if (dynamic_maps[i].fb_depth.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].fb_depth);
+ }
+ if (dynamic_maps[i].albedo.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].albedo);
+ }
+ if (dynamic_maps[i].normal.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].normal);
+ }
+ if (dynamic_maps[i].orm.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].orm);
+ }
+ }
+ dynamic_maps.clear();
+}
+
void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -3946,6 +3957,12 @@ RID GI::voxel_gi_instance_create(RID p_base) {
return rid;
}
+void GI::voxel_gi_instance_free(RID p_rid) {
+ GI::VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_rid);
+ voxel_gi->free_resources();
+ voxel_gi_instance_owner.free(p_rid);
+}
+
void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
ERR_FAIL_COND(!voxel_gi);
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index d4d4182950..8860445c3b 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -232,16 +232,13 @@ private:
uint32_t max_cascades;
int32_t screen_size[2];
- uint32_t use_occlusion;
float y_mult;
- uint32_t probe_axis_size;
float z_near;
- float reserved1;
- float reserved2;
- float cam_transform[16];
- float inv_projection[16];
+ float inv_projection[3][4];
+ float cam_basis[3][3];
+ float cam_origin[3];
};
SdfgiDebugShaderRD debug;
@@ -472,6 +469,7 @@ public:
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ void free_resources();
};
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
@@ -486,6 +484,12 @@ public:
return voxel_gi->texture;
};
+ bool voxel_gi_instance_owns(RID p_rid) const {
+ return voxel_gi_instance_owner.owns(p_rid);
+ }
+
+ void voxel_gi_instance_free(RID p_rid);
+
RS::VoxelGIQuality voxel_gi_quality = RS::VOXEL_GI_QUALITY_LOW;
/* SDFGI */
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 147658bea9..1d6b158d65 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -114,12 +114,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- // print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
@@ -164,7 +168,7 @@ void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, R
}
}
-void SkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SkyRD::SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -1228,7 +1232,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh
// 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));
+ angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
} else {
angular_diameter = 0.0;
}
diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h
index c5a2e2c298..080165c112 100644
--- a/servers/rendering/renderer_rd/environment/sky.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -131,7 +131,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
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 7eddc1fb5b..8754e90647 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1076,7 +1076,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
instance_data.flags = inst->flags_cache;
instance_data.gi_offset = inst->gi_offset_cache;
instance_data.layer_mask = inst->layer_mask;
- instance_data.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ instance_data.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset);
instance_data.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x;
instance_data.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y;
instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x;
@@ -2265,15 +2265,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
case RS::DECAL_FILTER_NEAREST: {
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 = 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 = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ 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_MIPMAPS: {
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_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -2292,15 +2295,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
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 = 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 = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ 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_MIPMAPS: {
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_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -2662,7 +2668,11 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 1;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
+ RID instance_buffer = scene_state.instance_buffer[RENDER_LIST_SECONDARY];
+ if (instance_buffer == RID()) {
+ instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used
+ }
+ u.append_id(instance_buffer);
uniforms.push_back(u);
}
{
@@ -3271,12 +3281,18 @@ void RenderForwardClustered::_update_shader_quality_settings() {
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
- sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
- sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
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 0faf2e2463..0911ee595f 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
@@ -150,6 +150,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);
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
#if 0
print_line("**compiling shader:");
@@ -158,11 +159,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element *el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -392,11 +392,15 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St
}
}
-void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_shader_uniform_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) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
@@ -693,6 +697,11 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
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 d4fc70cada..d6b526fa4a 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
@@ -174,6 +174,7 @@ public:
bool uses_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
+ bool uses_screen_texture_mipmaps = false;
Cull cull_mode = CULL_DISABLED;
uint64_t last_pass = 0;
@@ -182,7 +183,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_path_hint(const String &p_path);
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_shader_uniform_list(List<PropertyInfo> *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;
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 15f810fb3b..ffd47cc163 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -1214,15 +1214,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
case RS::DECAL_FILTER_NEAREST: {
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 = 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 = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ 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_MIPMAPS: {
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_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -1241,15 +1244,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
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 = 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 = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ 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_MIPMAPS: {
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_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -1897,7 +1903,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
push_constant.flags = inst->flags_cache;
push_constant.gi_offset = inst->gi_offset_cache;
push_constant.layer_mask = inst->layer_mask;
- push_constant.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ push_constant.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset);
if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
// abuse lightmap_uv_scale[0] here, should not be needed here
@@ -2558,12 +2564,18 @@ void RenderForwardMobile::_update_shader_quality_settings() {
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
sc.constant_id = SPEC_CONSTANT_DECAL_USE_MIPMAPS;
- sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
sc.constant_id = SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS;
- sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
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 0593178829..85c9e1db2a 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
@@ -158,11 +158,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element * el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -349,11 +348,14 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin
}
}
-void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_shader_uniform_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) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
continue;
}
@@ -595,6 +597,11 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
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 1bb8a08ccf..e208334547 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
@@ -142,7 +142,7 @@ public:
virtual void set_path_hint(const String &p_path);
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_shader_uniform_list(List<PropertyInfo> *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;
diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp
new file mode 100644
index 0000000000..9baa86a32d
--- /dev/null
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* framebuffer_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 "framebuffer_cache_rd.h"
+
+FramebufferCacheRD *FramebufferCacheRD::singleton = nullptr;
+
+void FramebufferCacheRD::_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 FramebufferCacheRD::_framebuffer_invalidation_callback(void *p_userdata) {
+ singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata));
+}
+
+FramebufferCacheRD::FramebufferCacheRD() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+}
+
+FramebufferCacheRD::~FramebufferCacheRD() {
+ if (cache_instances_used > 0) {
+ ERR_PRINT("At exit: " + itos(cache_instances_used) + " framebuffer cache instance(s) still in use.");
+ }
+}
diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
new file mode 100644
index 0000000000..f360e0fc6b
--- /dev/null
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
@@ -0,0 +1,310 @@
+/*************************************************************************/
+/* framebuffer_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 FRAMEBUFFER_CACHE_RD_H
+#define FRAMEBUFFER_CACHE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "servers/rendering/rendering_device.h"
+
+class FramebufferCacheRD : public Object {
+ GDCLASS(FramebufferCacheRD, Object)
+
+ struct Cache {
+ Cache *prev = nullptr;
+ Cache *next = nullptr;
+ uint32_t hash = 0;
+ RID cache;
+ LocalVector<RID> textures;
+ LocalVector<RD::FramebufferPass> passes;
+ uint32_t views = 0;
+ };
+
+ PagedAllocator<Cache> cache_allocator;
+
+ enum {
+ HASH_TABLE_SIZE = 16381 // Prime
+ };
+
+ Cache *hash_table[HASH_TABLE_SIZE] = {};
+
+ static _FORCE_INLINE_ uint32_t _hash_pass(const RD::FramebufferPass &p, uint32_t h) {
+ h = hash_murmur3_one_32(p.depth_attachment, h);
+ h = hash_murmur3_one_32(p.vrs_attachment, h);
+
+ h = hash_murmur3_one_32(p.color_attachments.size(), h);
+ for (int i = 0; i < p.color_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.color_attachments[i], h);
+ }
+
+ h = hash_murmur3_one_32(p.resolve_attachments.size(), h);
+ for (int i = 0; i < p.resolve_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.resolve_attachments[i], h);
+ }
+
+ h = hash_murmur3_one_32(p.preserve_attachments.size(), h);
+ for (int i = 0; i < p.preserve_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.preserve_attachments[i], h);
+ }
+
+ return h;
+ }
+
+ static _FORCE_INLINE_ bool _compare_pass(const RD::FramebufferPass &a, const RD::FramebufferPass &b) {
+ if (a.depth_attachment != b.depth_attachment) {
+ return false;
+ }
+
+ if (a.vrs_attachment != b.vrs_attachment) {
+ return false;
+ }
+
+ if (a.color_attachments.size() != b.color_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.color_attachments.size(); i++) {
+ if (a.color_attachments[i] != b.color_attachments[i]) {
+ return false;
+ }
+ }
+
+ if (a.resolve_attachments.size() != b.resolve_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.resolve_attachments.size(); i++) {
+ if (a.resolve_attachments[i] != b.resolve_attachments[i]) {
+ return false;
+ }
+ }
+
+ if (a.preserve_attachments.size() != b.preserve_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.preserve_attachments.size(); i++) {
+ if (a.preserve_attachments[i] != b.preserve_attachments[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ _FORCE_INLINE_ uint32_t _hash_rids(uint32_t h, const RID &arg) {
+ return hash_murmur3_one_64(arg.get_id(), h);
+ }
+
+ template <typename... Args>
+ uint32_t _hash_rids(uint32_t h, const RID &arg, Args... args) {
+ h = hash_murmur3_one_64(arg.get_id(), h);
+ return _hash_rids(h, args...);
+ }
+
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg) {
+ return textures[idx] == arg;
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg, Args... args) {
+ if (textures[idx] != arg) {
+ return false;
+ }
+ return _compare_args(idx + 1, textures, args...);
+ }
+
+ _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg) {
+ textures.push_back(arg);
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg, Args... args) {
+ textures.push_back(arg);
+ _create_args(textures, args...);
+ }
+
+ static FramebufferCacheRD *singleton;
+
+ uint32_t cache_instances_used = 0;
+
+ void _invalidate(Cache *p_cache);
+ static void _framebuffer_invalidation_callback(void *p_userdata);
+
+ RID _allocate_from_data(uint32_t p_views, uint32_t p_hash, uint32_t p_table_idx, const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes) {
+ RID rid;
+ if (p_passes.size()) {
+ rid = RD::get_singleton()->framebuffer_create_multipass(p_textures, p_passes, RD::INVALID_ID, p_views);
+ } else {
+ rid = RD::get_singleton()->framebuffer_create(p_textures, RD::INVALID_ID, p_views);
+ }
+
+ ERR_FAIL_COND_V(rid.is_null(), rid);
+
+ Cache *c = cache_allocator.alloc();
+ c->views = p_views;
+ c->cache = rid;
+ c->hash = p_hash;
+ c->textures.resize(p_textures.size());
+ for (uint32_t i = 0; i < c->textures.size(); i++) {
+ c->textures[i] = p_textures[i];
+ }
+ c->passes.resize(p_passes.size());
+ for (uint32_t i = 0; i < c->passes.size(); i++) {
+ c->passes[i] = p_passes[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()->framebuffer_set_invalidation_callback(rid, _framebuffer_invalidation_callback, c);
+
+ cache_instances_used++;
+
+ return rid;
+ }
+
+public:
+ template <typename... Args>
+ RID get_cache(Args... args) {
+ uint32_t h = hash_murmur3_one_32(1); //1 view
+ h = hash_murmur3_one_32(sizeof...(Args), h);
+ h = _hash_args(h, args...);
+ h = hash_murmur3_one_32(0, h); // 0 passes
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == 1 && _compare_args(0, c->textures, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RID> textures;
+ _create_args(textures, args...);
+
+ return _allocate_from_data(1, h, table_idx, textures, Vector<RD::FramebufferPass>());
+ }
+
+ template <typename... Args>
+ RID get_cache_multiview(uint32_t p_views, Args... args) {
+ uint32_t h = hash_murmur3_one_32(p_views);
+ h = hash_murmur3_one_32(sizeof...(Args), h);
+ h = _hash_args(h, args...);
+ h = hash_murmur3_one_32(0, h); // 0 passes
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == p_views && _compare_args(0, c->textures, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RID> textures;
+ _create_args(textures, args...);
+
+ return _allocate_from_data(p_views, h, table_idx, textures, Vector<RD::FramebufferPass>());
+ }
+
+ RID get_cache_multipass(const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes, uint32_t p_views = 1) {
+ uint32_t h = hash_murmur3_one_32(p_views);
+ h = hash_murmur3_one_32(p_textures.size());
+ for (int i = 0; i < p_textures.size(); i++) {
+ h = hash_murmur3_one_64(p_textures[i].get_id(), h);
+ }
+ h = hash_murmur3_one_32(p_passes.size());
+ for (int i = 0; i < p_passes.size(); i++) {
+ h = _hash_pass(p_passes[i], h);
+ }
+
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->views == p_views && c->textures.size() == (uint32_t)p_textures.size() && c->passes.size() == (uint32_t)p_passes.size()) {
+ bool all_ok = true;
+
+ for (int i = 0; i < p_textures.size(); i++) {
+ if (p_textures[i] != c->textures[i]) {
+ all_ok = false;
+ break;
+ }
+ }
+
+ if (all_ok) {
+ for (int i = 0; i < p_passes.size(); i++) {
+ if (!_compare_pass(p_passes[i], c->passes[i])) {
+ all_ok = false;
+ break;
+ }
+ }
+ }
+
+ if (all_ok) {
+ return c->cache;
+ }
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+ return _allocate_from_data(p_views, h, table_idx, p_textures, p_passes);
+ }
+
+ static FramebufferCacheRD *get_singleton() { return singleton; }
+
+ FramebufferCacheRD();
+ ~FramebufferCacheRD();
+};
+
+#endif // FRAMEBUFFER_CACHE_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 27399298b3..7102f1f0ff 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
//bind pipeline
- {
+ if (rect->flags & CANVAS_RECT_LCD) {
+ RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
+ RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate);
+ } else {
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
}
@@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.msdf[1] = rect->outline; // Outline size.
push_constant.msdf[2] = 0.f; // Reserved.
push_constant.msdf[3] = 0.f; // Reserved.
+ } else if (rect->flags & CANVAS_RECT_LCD) {
+ push_constant.flags |= FLAGS_USE_LCD;
}
push_constant.modulation[0] = rect->modulate.r * base_color.r;
@@ -1361,6 +1367,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Item *ci = p_item_list;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ bool backbuffer_gen_mipmaps = false;
Item *canvas_group_owner = nullptr;
@@ -1389,6 +1396,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -1474,9 +1482,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- texture_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, backbuffer_gen_mipmaps);
backbuffer_copy = false;
+ backbuffer_gen_mipmaps = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
}
@@ -1591,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
real_t farp = p_far;
real_t aspect = 1.0;
- real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5));
+ real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
real_t ymin = -ymax;
real_t xmin = ymin * aspect;
real_t xmax = ymax * aspect;
@@ -1956,8 +1965,8 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve
} else {
//update existing
- RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr());
- RD::get_singleton()->buffer_update(oc->index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr());
+ RD::get_singleton()->buffer_update(oc->sdf_vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr());
+ RD::get_singleton()->buffer_update(oc->sdf_index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr());
}
}
}
@@ -1980,6 +1989,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
+ uses_screen_texture_mipmaps = false;
uses_sdf = false;
uses_time = false;
@@ -1990,7 +2000,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
- uses_screen_texture = false;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
@@ -2015,6 +2024,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
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.");
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
}
@@ -2025,12 +2036,16 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
@@ -2104,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::PipelineColorBlendState blend_state;
blend_state.attachments.push_back(attachment);
+ RD::PipelineColorBlendState::Attachment attachment_lcd;
+ attachment_lcd.enable_blend = true;
+ attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ RD::PipelineColorBlendState blend_state_lcd;
+ blend_state_lcd.attachments.push_back(attachment_lcd);
+
//update pipelines
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
@@ -2119,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- { //non lit
+ {
+ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
@@ -2132,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS },
- { //lit
+ SHADER_VARIANT_ATTRIBUTES_POINTS,
+ SHADER_VARIANT_QUAD,
+ },
+ {
+ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
@@ -2143,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
+ SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
+ SHADER_VARIANT_QUAD_LIGHT,
+ },
};
RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]);
- pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
+ pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
+ } else {
+ pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
}
}
@@ -2171,11 +2209,15 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S
}
}
-void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_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) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
if (E.value.texture_order >= 0) {
@@ -2350,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
blend_state.attachments.push_back(blend_attachment);
+ RD::PipelineColorBlendState::Attachment attachment_lcd;
+ attachment_lcd.enable_blend = true;
+ attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ RD::PipelineColorBlendState blend_state_lcd;
+ blend_state_lcd.attachments.push_back(attachment_lcd);
+
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
@@ -2363,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- { //non lit
+ {
+ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
@@ -2376,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS },
- { //lit
+ SHADER_VARIANT_ATTRIBUTES_POINTS,
+ SHADER_VARIANT_QUAD,
+ },
+ {
+ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
@@ -2387,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
+ SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
+ SHADER_VARIANT_QUAD_LIGHT,
+ },
};
RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
+ } else {
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
}
}
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index f96d4686ff..54077a5b9a 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
FLAGS_USE_MSDF = (1 << 28),
+ FLAGS_USE_LCD = (1 << 29),
};
enum {
@@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
PIPELINE_VARIANT_ATTRIBUTE_LINES,
PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
PIPELINE_VARIANT_ATTRIBUTE_POINTS,
+ PIPELINE_VARIANT_QUAD_LCD_BLEND,
PIPELINE_VARIANT_MAX
};
enum PipelineLightMode {
@@ -174,13 +176,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
+ bool uses_screen_texture_mipmaps = false;
bool uses_sdf = false;
bool uses_time = false;
virtual void set_code(const String &p_Code);
virtual void set_path_hint(const String &p_path);
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_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index a61172c8f5..e7abcf5674 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -249,6 +249,7 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
uniform_set_cache = memnew(UniformSetCacheRD);
+ framebuffer_cache = memnew(FramebufferCacheRD);
{
String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
@@ -266,7 +267,7 @@ RendererCompositorRD::RendererCompositorRD() {
if (err != OK) {
ERR_PRINT("Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir);
} else {
- shader_cache_dir = shader_cache_dir.plus_file("shader_cache");
+ shader_cache_dir = shader_cache_dir.path_join("shader_cache");
bool shader_cache_enabled = GLOBAL_GET("rendering/shader_compiler/shader_cache/enabled");
if (!Engine::get_singleton()->is_editor_hint() && !shader_cache_enabled) {
@@ -316,5 +317,6 @@ RendererCompositorRD::RendererCompositorRD() {
RendererCompositorRD::~RendererCompositorRD() {
memdelete(uniform_set_cache);
+ memdelete(framebuffer_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 564c26bfe4..a28335f800 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -37,6 +37,7 @@
#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h"
#include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
@@ -50,6 +51,7 @@
class RendererCompositorRD : public RendererCompositor {
protected:
UniformSetCacheRD *uniform_set_cache = nullptr;
+ FramebufferCacheRD *framebuffer_cache = nullptr;
RendererCanvasRenderRD *canvas = nullptr;
RendererRD::Utilities *utilities = nullptr;
RendererRD::LightStorage *light_storage = nullptr;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index c6f38012a6..fa83428367 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2459,8 +2459,20 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
p_internal_width = p_width;
}
- const float texture_mipmap_bias = -log2f(p_width / p_internal_width) + p_texture_mipmap_bias;
- material_storage->sampler_rd_configure_custom(texture_mipmap_bias);
+ if (p_use_taa) {
+ // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
+ // This restores sharpness in still images to be roughly at the same level as without TAA,
+ // but moving scenes will still be blurrier.
+ p_texture_mipmap_bias -= 0.5;
+ }
+
+ if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
+ // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
+ // If both TAA and FXAA are enabled, combine their negative LOD biases together.
+ p_texture_mipmap_bias -= 0.25;
+ }
+
+ material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
update_uniform_sets();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -2472,7 +2484,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->height = p_height;
rb->fsr_sharpness = p_fsr_sharpness;
rb->render_target = p_render_target;
- rb->msaa = p_msaa;
+ rb->msaa_3d = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
rb->use_taa = p_use_taa;
rb->use_debanding = p_use_debanding;
@@ -2497,7 +2509,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.height = rb->internal_height; // If set to rb->width, msaa won't crash
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) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb->msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
}
tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
@@ -2520,7 +2532,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (rb->view_count > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
- if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb->msaa_3d == RS::VIEWPORT_MSAA_DISABLED) {
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
} else {
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
@@ -2531,7 +2543,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.array_layers = rb->view_count; // create a layer for every view
- if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb->msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
} else {
tf.usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
@@ -2859,24 +2871,27 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.color[2] = linear_col.b;
light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
+ light_data.volumetric_fog_energy = light_storage->light_get_param(base, RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY);
light_data.mask = light_storage->light_get_cull_mask(base);
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
+ light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
}
- light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
+ light_data.shadow_opacity = (p_using_shadows && light_storage->light_has_shadow(base))
+ ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY)
+ : 0.0;
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));
+ angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
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.
@@ -2886,7 +2901,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
angular_diameter = 0.0;
}
- if (light_data.shadow_enabled) {
+ if (light_data.shadow_opacity > 0.001) {
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);
@@ -2938,7 +2953,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
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 / light_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.softshadow_angle = angular_diameter;
@@ -3040,19 +3054,26 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// Reuse fade begin, fade length and distance for shadow LOD determination later.
float fade_begin = 0.0;
+ float fade_shadow = 0.0;
float fade_length = 0.0;
real_t distance = 0.0;
float fade = 1.0;
+ float shadow_opacity_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_shadow = light_storage->light_get_distance_fade_shadow(li->light);
fade_length = light_storage->light_get_distance_fade_length(li->light);
distance = camera_plane.distance_to(li->transform.origin);
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
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);
}
+
+ if (distance > fade_shadow) {
+ shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length);
+ }
}
float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
@@ -3061,6 +3082,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.color[1] = linear_col.g * energy;
light_data.color[2] = linear_col.b * energy;
light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
+ light_data.volumetric_fog_energy = light_storage->light_get_param(base, RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY);
light_data.bake_mode = light_storage->light_get_bake_mode(base);
float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
@@ -3084,7 +3106,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
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.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle));
light_data.mask = light_storage->light_get_cull_mask(base);
@@ -3116,11 +3138,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.projector_rect[3] = 0;
}
- const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
+ const bool needs_shadow =
+ shadow_atlas &&
+ shadow_atlas->shadow_owners.has(li->self) &&
+ p_using_shadows &&
+ light_storage->light_has_shadow(base);
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)) {
+ if (distance > light_storage->light_get_distance_fade_shadow(li->light) + light_storage->light_get_distance_fade_length(li->light)) {
// Out of range, don't draw shadows to improve performance.
in_shadow_range = false;
}
@@ -3129,7 +3155,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
if (needs_shadow && in_shadow_range) {
// fill in the shadow information
- light_data.shadow_enabled = true;
+ light_data.shadow_opacity = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) * shadow_opacity_fade;
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
@@ -3151,7 +3177,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.atlas_rect[3] = rect.size.height;
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();
@@ -3181,7 +3206,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// Only enable PCSS-like soft shadows if blurring is enabled.
// Otherwise, performance would decrease with no visual difference.
Projection cm = li->shadow_transform[0].camera;
- float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
+ float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle));
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
} else {
light_data.soft_shadow_size = 0.0;
@@ -3189,7 +3214,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
} else {
- light_data.shadow_enabled = false;
+ light_data.shadow_opacity = 0.0;
}
li->cull_mask = light_storage->light_get_cull_mask(base);
@@ -3637,7 +3662,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
if (p_render_data->render_buffers.is_valid()) {
bool directional_shadows = false;
for (uint32_t i = 0; i < directional_light_count; i++) {
- if (cluster.directional_lights[i].shadow_enabled) {
+ if (cluster.directional_lights[i].shadow_opacity > 0.001) {
directional_shadows = true;
break;
}
@@ -4079,19 +4104,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
decal_instance_owner.free(p_rid);
} else if (lightmap_instance_owner.owns(p_rid)) {
lightmap_instance_owner.free(p_rid);
- } else if (gi.voxel_gi_instance_owner.owns(p_rid)) {
- RendererRD::GI::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.get_or_null(p_rid);
- if (voxel_gi->texture.is_valid()) {
- RD::get_singleton()->free(voxel_gi->texture);
- RD::get_singleton()->free(voxel_gi->write_buffer);
- }
-
- for (int i = 0; i < voxel_gi->dynamic_maps.size(); i++) {
- RD::get_singleton()->free(voxel_gi->dynamic_maps[i].texture);
- RD::get_singleton()->free(voxel_gi->dynamic_maps[i].depth);
- }
-
- gi.voxel_gi_instance_owner.free(p_rid);
+ } else if (gi.voxel_gi_instance_owns(p_rid)) {
+ gi.voxel_gi_instance_free(p_rid);
} else if (sky.sky_owner.owns(p_rid)) {
sky.update_dirty_skys();
sky.free_sky(p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 09ec2a9efd..3867fd8605 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -456,7 +456,7 @@ private:
int width = 0;
int height = 0;
float fsr_sharpness = 0.2f;
- RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_taa = false;
bool use_debanding = false;
@@ -608,7 +608,7 @@ private:
float inv_spot_attenuation;
float cos_spot_angle;
float specular_amount;
- uint32_t shadow_enabled;
+ float shadow_opacity;
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
float shadow_matrix[16];
@@ -618,7 +618,7 @@ private:
float soft_shadow_size;
float soft_shadow_scale;
uint32_t mask;
- float shadow_volumetric_fog_fade;
+ float volumetric_fog_energy;
uint32_t bake_mode;
float projector_rect[4];
};
@@ -633,12 +633,12 @@ private:
float softshadow_angle;
float soft_shadow_scale;
uint32_t blend_splits;
- uint32_t shadow_enabled;
+ float shadow_opacity;
float fade_from;
float fade_to;
uint32_t pad[2];
uint32_t bake_mode;
- float shadow_volumetric_fog_fade;
+ float volumetric_fog_energy;
float shadow_bias[4];
float shadow_normal_bias[4];
float shadow_transmittance_bias[4];
@@ -1167,23 +1167,51 @@ public:
virtual void decals_set_filter(RS::DecalFilter p_filter) override;
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
- _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
- _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
- _FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
- _FORCE_INLINE_ float directional_shadow_quality_radius_get() const { return directional_shadow_quality_radius; }
+ _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const {
+ return shadows_quality;
+ }
+ _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const {
+ return directional_shadow_quality;
+ }
+ _FORCE_INLINE_ float shadows_quality_radius_get() const {
+ return shadows_quality_radius;
+ }
+ _FORCE_INLINE_ float directional_shadow_quality_radius_get() const {
+ return directional_shadow_quality_radius;
+ }
- _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() { return directional_penumbra_shadow_kernel; }
- _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() { return directional_soft_shadow_kernel; }
- _FORCE_INLINE_ float *penumbra_shadow_kernel_get() { return penumbra_shadow_kernel; }
- _FORCE_INLINE_ float *soft_shadow_kernel_get() { return soft_shadow_kernel; }
+ _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() {
+ return directional_penumbra_shadow_kernel;
+ }
+ _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() {
+ return directional_soft_shadow_kernel;
+ }
+ _FORCE_INLINE_ float *penumbra_shadow_kernel_get() {
+ return penumbra_shadow_kernel;
+ }
+ _FORCE_INLINE_ float *soft_shadow_kernel_get() {
+ return soft_shadow_kernel;
+ }
- _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const { return directional_penumbra_shadow_samples; }
- _FORCE_INLINE_ int directional_soft_shadow_samples_get() const { return directional_soft_shadow_samples; }
- _FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; }
- _FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; }
+ _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const {
+ return directional_penumbra_shadow_samples;
+ }
+ _FORCE_INLINE_ int directional_soft_shadow_samples_get() const {
+ return directional_soft_shadow_samples;
+ }
+ _FORCE_INLINE_ int penumbra_shadow_samples_get() const {
+ return penumbra_shadow_samples;
+ }
+ _FORCE_INLINE_ int soft_shadow_samples_get() const {
+ return soft_shadow_samples;
+ }
- _FORCE_INLINE_ RS::LightProjectorFilter light_projectors_get_filter() const { return light_projectors_filter; }
- _FORCE_INLINE_ RS::DecalFilter decals_get_filter() const { return decals_filter; }
+ _FORCE_INLINE_ RS::LightProjectorFilter light_projectors_get_filter() const {
+ return light_projectors_filter;
+ }
+ _FORCE_INLINE_ RS::DecalFilter decals_get_filter() const {
+ return decals_filter;
+ }
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index c9b6d09d4c..0f2dea6fe9 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -380,7 +380,7 @@ static const uint32_t cache_file_version = 2;
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";
+ String path = shader_cache_dir.path_join(name).path_join(base_sha256).path_join(sha1) + ".cache";
Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
if (f.is_null()) {
@@ -443,7 +443,7 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
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";
+ String path = shader_cache_dir.path_join(name).path_join(base_sha256).path_join(sha1) + ".cache";
Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
ERR_FAIL_COND(f.is_null());
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index f8e9020f9f..459d798a80 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -509,7 +509,13 @@ void main() {
float a = clamp(d * px_size + 0.5, 0.0, 1.0);
color.a = a * color.a;
}
-
+ } else if (bool(draw_data.flags & FLAGS_USE_LCD)) {
+ vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv);
+ if (lcd_sample.a == 1.0) {
+ color.rgb = lcd_sample.rgb * color.a;
+ } else {
+ color = vec4(0.0, 0.0, 0.0, 0.0);
+ }
} else {
#else
{
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 2ea6965c09..1b627a3e81 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -25,6 +25,7 @@
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
#define FLAGS_USE_MSDF (1 << 28)
+#define FLAGS_USE_LCD (1 << 29)
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0438671dd2..0b43af7738 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
@@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a3b3938ee9..a06cacfabe 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
index d85ab3af2e..246ef81cb2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
@@ -182,17 +182,18 @@ void main() {
if (found) {
float margin_blend = 1.0;
- vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin
- if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, params.screen_size + margin)))) {
- // clip outside screen + margin
+ vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.05); // make a uniform margin
+ if (any(bvec4(lessThan(pos, vec2(0.0, 0.0)), greaterThan(pos, params.screen_size)))) {
+ // clip at the screen edges
imageStore(ssr_image, ssC, vec4(0.0));
return;
}
{
- //blend fading out towards external margin
- vec2 margin_grad = mix(pos - params.screen_size, -pos, lessThan(pos, vec2(0.0)));
- margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y));
+ //blend fading out towards inner margin
+ // 0.5 = midpoint of reflection
+ vec2 margin_grad = mix(params.screen_size - pos, pos, lessThan(pos, params.screen_size * 0.5));
+ margin_blend = smoothstep(0.0, margin.x * margin.y, margin_grad.x * margin_grad.y);
//margin_blend = 1.0;
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
index af5f7d0a58..9640d30e78 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
@@ -37,16 +37,14 @@ layout(push_constant, std430) uniform Params {
uint max_cascades;
ivec2 screen_size;
- bool use_occlusion;
float y_mult;
- int probe_axis_size;
float z_near;
- float reserved1;
- float reserved2;
- mat4 cam_transform;
- mat4 inv_projection;
+ mat3x4 inv_projection;
+ // We pack these more tightly than mat3 and vec3, which will require some reconstruction trickery.
+ float cam_basis[3][3];
+ float cam_origin[3];
}
params;
@@ -82,13 +80,21 @@ void main() {
vec3 ray_pos;
vec3 ray_dir;
{
- ray_pos = params.cam_transform[3].xyz;
+ ray_pos = vec3(params.cam_origin[0], params.cam_origin[1], params.cam_origin[2]);
ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0);
ray_dir.z = params.z_near;
- ray_dir = (params.inv_projection * vec4(ray_dir, 1.0)).xyz;
- ray_dir = normalize(mat3(params.cam_transform) * ray_dir);
+ ray_dir = (vec4(ray_dir, 1.0) * mat4(params.inv_projection)).xyz;
+
+ mat3 cam_basis;
+ {
+ vec3 c0 = vec3(params.cam_basis[0][0], params.cam_basis[0][1], params.cam_basis[0][2]);
+ vec3 c1 = vec3(params.cam_basis[1][0], params.cam_basis[1][1], params.cam_basis[1][2]);
+ vec3 c2 = vec3(params.cam_basis[2][0], params.cam_basis[2][1], params.cam_basis[2][2]);
+ cam_basis = mat3(c0, c1, c2);
+ }
+ ray_dir = normalize(cam_basis * ray_dir);
}
ray_pos.y *= params.y_mult;
diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index e74cfad65c..07d5223472 100644
--- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -270,6 +270,9 @@ const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
vec3(0.9375, 0.25925926, 0.12),
vec3(0.03125, 0.59259259, 0.32));
+// Higher values will make light in volumetric fog fade out sooner when it's occluded by shadow.
+const float INV_FOG_FADE = 10.0;
+
void main() {
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
@@ -375,46 +378,48 @@ void main() {
if (total_density > 0.001) {
for (uint i = 0; i < params.directional_light_count; i++) {
- vec3 shadow_attenuation = vec3(1.0);
-
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -view_pos.z;
-
- vec4 pssm_coord;
- vec3 light_dir = directional_lights.data[i].direction;
- vec4 v = vec4(view_pos, 1.0);
- float z_range;
-
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.x;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.y;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.z;
-
- } else {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.w;
- }
+ if (directional_lights.data[i].volumetric_fog_energy > 0.001) {
+ vec3 shadow_attenuation = vec3(1.0);
+
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
+ float depth_z = -view_pos.z;
+
+ vec4 pssm_coord;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec4 v = vec4(view_pos, 1.0);
+ float z_range;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.x;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.y;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.z;
+
+ } else {
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.w;
+ }
- float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
- float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade);
+ float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
+ float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * INV_FOG_FADE);
- 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 = 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(vec3(0.0), vec3(1.0), shadow);
- }
+ shadow_attenuation = mix(vec3(1.0 - directional_lights.data[i].shadow_opacity), 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);
+ 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) * directional_lights.data[i].volumetric_fog_energy;
+ }
}
// Compute light from sky
@@ -481,12 +486,12 @@ void main() {
float d = distance(omni_lights.data[light_index].position, view_pos);
float shadow_attenuation = 1.0;
- if (d * omni_lights.data[light_index].inv_radius < 1.0) {
+ if (omni_lights.data[light_index].volumetric_fog_energy > 0.001 && d * omni_lights.data[light_index].inv_radius < 1.0) {
float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
vec3 light = omni_lights.data[light_index].color;
- if (omni_lights.data[light_index].shadow_enabled) {
+ if (omni_lights.data[light_index].shadow_opacity > 0.001) {
//has shadow
vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
vec2 flip_offset = omni_lights.data[light_index].direction.xy;
@@ -509,9 +514,9 @@ void main() {
float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
- shadow_attenuation = exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ shadow_attenuation = mix(1.0 - omni_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
- total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g);
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g) * omni_lights.data[light_index].volumetric_fog_energy;
}
}
}
@@ -562,7 +567,7 @@ void main() {
float d = length(light_rel_vec);
float shadow_attenuation = 1.0;
- if (d * spot_lights.data[light_index].inv_radius < 1.0) {
+ if (spot_lights.data[light_index].volumetric_fog_energy > 0.001 && d * spot_lights.data[light_index].inv_radius < 1.0) {
float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
vec3 spot_dir = spot_lights.data[light_index].direction;
@@ -572,7 +577,7 @@ void main() {
vec3 light = spot_lights.data[light_index].color;
- if (spot_lights.data[light_index].shadow_enabled) {
+ if (spot_lights.data[light_index].shadow_opacity > 0.001) {
//has shadow
vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
vec2 flip_offset = spot_lights.data[light_index].direction.xy;
@@ -595,9 +600,9 @@ void main() {
float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
- shadow_attenuation = exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
+ shadow_attenuation = mix(1.0 - spot_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
- total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g);
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g) * spot_lights.data[light_index].volumetric_fog_energy;
}
}
}
diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
index 61c8488a05..a7fca25a6b 100644
--- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
@@ -15,7 +15,7 @@ struct LightData { //this structure needs to be as packed as possible
mediump float cone_attenuation;
mediump float cone_angle;
mediump float specular_amount;
- bool shadow_enabled;
+ mediump float shadow_opacity;
highp vec4 atlas_rect; // rect in the shadow atlas
highp mat4 shadow_matrix;
@@ -25,7 +25,7 @@ struct LightData { //this structure needs to be as packed as possible
highp float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
highp float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
uint mask;
- mediump float shadow_volumetric_fog_fade;
+ mediump float volumetric_fog_energy;
uint bake_mode;
highp vec4 projector_rect; //projector rect in srgb decal atlas
};
@@ -60,12 +60,12 @@ struct DirectionalLightData {
highp float softshadow_angle;
highp float soft_shadow_scale;
bool blend_splits;
- bool shadow_enabled;
+ mediump float shadow_opacity;
highp float fade_from;
highp float fade_to;
uvec2 pad;
uint bake_mode;
- mediump float shadow_volumetric_fog_fade;
+ mediump float volumetric_fog_energy;
highp vec4 shadow_bias;
highp vec4 shadow_normal_bias;
highp vec4 shadow_transmittance_bias;
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 4369bddc83..fb5759bc17 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -458,11 +458,11 @@ void main() {
} break;
case ATTRACTOR_TYPE_VECTOR_FIELD: {
- vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents) * 2.0 - 1.0;
+ vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents + 1.0) * 0.5;
if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) {
continue;
}
- vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz;
+ vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * 2.0 - 1.0;
dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction
amount = length(s);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 22058b3a06..6b4e4a5a16 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) out vec3 vertex_interp;
@@ -231,12 +238,13 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
@@ -988,8 +996,10 @@ void fragment_shader(in SceneData scene_data) {
vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
vec3 ref_vec = reflect(-view, bent_normal);
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
#else
vec3 ref_vec = reflect(-view, normal);
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
#endif
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
@@ -1046,6 +1056,7 @@ void fragment_shader(in SceneData scene_data) {
ambient_light *= attenuation;
specular_light *= attenuation;
+ ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD;
@@ -1203,6 +1214,7 @@ void fragment_shader(in SceneData scene_data) {
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(-view, normal));
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal));
@@ -1302,6 +1314,18 @@ void fragment_shader(in SceneData scene_data) {
item_to = subgroupBroadcastFirst(subgroupMax(item_to));
#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
+ vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
+ vec3 anisotropic_tangent = cross(anisotropic_direction, view);
+ vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
+ vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
+#else
+ vec3 bent_normal = normal;
+#endif
+ vec3 ref_vec = normalize(reflect(-view, bent_normal));
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
+
for (uint i = item_from; i < item_to; i++) {
uint mask = cluster_buffer.data[cluster_reflection_offset + i];
mask &= cluster_get_range_clip_mask(i, item_min, item_max);
@@ -1324,16 +1348,8 @@ void fragment_shader(in SceneData scene_data) {
if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
-#ifdef LIGHT_ANISOTROPY_USED
- // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
- vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
- vec3 anisotropic_tangent = cross(anisotropic_direction, view);
- vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
- vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
-#else
- vec3 bent_normal = normal;
-#endif
- reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+
+ reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
}
@@ -1417,7 +1433,7 @@ void fragment_shader(in SceneData scene_data) {
float shadow = 1.0;
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
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))));
@@ -1626,7 +1642,7 @@ void fragment_shader(in SceneData scene_data) {
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth;
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
@@ -1681,6 +1697,8 @@ void fragment_shader(in SceneData scene_data) {
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+
+ shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;
#endif
blur_shadow(shadow);
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 e27c81eaea..7299bb0576 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -395,7 +395,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
- if (omni_lights.data[idx].shadow_enabled) {
+ if (omni_lights.data[idx].shadow_opacity > 0.001) {
// there is a shadowmap
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
@@ -498,6 +498,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
}
shadow /= float(sc_penumbra_shadow_samples);
+ shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);
} else {
//no blockers found, so no shadow
@@ -516,7 +517,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
vec2 pos = shadow_sample.xy / shadow_sample.z;
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
depth *= omni_lights.data[idx].inv_radius;
- shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth);
+ shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity);
}
return shadow;
@@ -674,7 +675,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
- if (spot_lights.data[idx].shadow_enabled) {
+ if (spot_lights.data[idx].shadow_opacity > 0.001) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
vec3 spot_dir = spot_lights.data[idx].direction;
@@ -735,6 +736,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
}
shadow /= float(sc_penumbra_shadow_samples);
+ shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);
} else {
//no blockers found, so no shadow
@@ -743,7 +745,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_block.data.shadow_atlas_pixel_size, shadow_uv);
+ shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity);
}
return shadow;
@@ -872,7 +874,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
diffuse_light, specular_light);
}
-void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
+void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
vec3 box_extents = reflections.data[ref_index].box_extents;
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
@@ -880,8 +882,6 @@ void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, flo
return;
}
- vec3 ref_vec = normalize(reflect(-view, normal));
-
vec3 inner_pos = abs(local_pos / box_extents);
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
//make blend more rounded
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 26d0de46c2..0ffc72f78f 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) highp out vec3 vertex_interp;
@@ -229,12 +236,13 @@ void main() {
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
@@ -889,8 +897,10 @@ void main() {
vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
vec3 ref_vec = reflect(-view, bent_normal);
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
#else
vec3 ref_vec = reflect(-view, normal);
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
#endif
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
@@ -940,6 +950,7 @@ void main() {
vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map
float NoV = max(dot(n, view), 0.0001);
vec3 ref_vec = reflect(-view, n);
+ ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);
// The clear coat layer assumes an IOR of 1.5 (4% reflectance)
float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV));
float attenuation = 1.0 - Fc;
@@ -1036,6 +1047,19 @@ void main() {
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
uint reflection_indices = draw_call.reflection_probes.x;
+
+#ifdef LIGHT_ANISOTROPY_USED
+ // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
+ vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
+ vec3 anisotropic_tangent = cross(anisotropic_direction, view);
+ vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
+ vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
+#else
+ vec3 bent_normal = normal;
+#endif
+ vec3 ref_vec = normalize(reflect(-view, bent_normal));
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
+
for (uint i = 0; i < 8; i++) {
uint reflection_index = reflection_indices & 0xFF;
if (i == 4) {
@@ -1047,16 +1071,8 @@ void main() {
if (reflection_index == 0xFF) {
break;
}
-#ifdef LIGHT_ANISOTROPY_USED
- // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
- vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
- vec3 anisotropic_tangent = cross(anisotropic_direction, view);
- vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
- vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
-#else
- vec3 bent_normal = normal;
-#endif
- reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+
+ reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
if (reflection_accum.a > 0.0) {
@@ -1134,7 +1150,7 @@ void main() {
#ifdef USE_SOFT_SHADOWS
//version with soft shadows, more expensive
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec4 pssm_coord;
@@ -1286,7 +1302,7 @@ void main() {
#else
// Soft shadow disabled version
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec4 pssm_coord;
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index a893a66c94..75bea9300b 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -54,14 +54,54 @@ layout(push_constant, std430) uniform Params {
}
params;
-vec4 decode_abgr_2_10_10_10(uint base) {
- uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3);
- return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0;
+vec2 uint_to_vec2(uint base) {
+ uvec2 decode = (uvec2(base) >> uvec2(0, 16)) & uvec2(0xFFFF, 0xFFFF);
+ return vec2(decode) / vec2(65535.0, 65535.0) * 2.0 - 1.0;
}
-uint encode_abgr_2_10_10_10(vec4 base) {
- uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30);
- return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w;
+vec3 oct_to_vec3(vec2 oct) {
+ vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
+vec3 decode_uint_oct_to_norm(uint base) {
+ return oct_to_vec3(uint_to_vec2(base));
+}
+
+vec4 decode_uint_oct_to_tang(uint base) {
+ vec2 oct_sign_encoded = uint_to_vec2(base);
+ // Binormal sign encoded in y component
+ vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0);
+ return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y));
+}
+
+vec2 signNotZero(vec2 v) {
+ return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0)));
+}
+
+uint vec2_to_uint(vec2 base) {
+ uvec2 enc = uvec2(clamp(ivec2(base * vec2(65535, 65535)), ivec2(0), ivec2(0xFFFF, 0xFFFF))) << uvec2(0, 16);
+ return enc.x | enc.y;
+}
+
+vec2 vec3_to_oct(vec3 e) {
+ e /= abs(e.x) + abs(e.y) + abs(e.z);
+ vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy);
+ return oct * 0.5f + 0.5f;
+}
+
+uint encode_norm_to_uint_oct(vec3 base) {
+ return vec2_to_uint(vec3_to_oct(base));
+}
+
+uint encode_tang_to_uint_oct(vec4 base) {
+ vec2 oct = vec3_to_oct(base.xyz);
+ // Encode binormal sign in y component
+ oct.y = oct.y * 0.5f + 0.5f;
+ oct.y = base.w >= 0.0f ? oct.y : 1 - oct.y;
+ return vec2_to_uint(oct);
}
void main() {
@@ -131,12 +171,12 @@ void main() {
src_offset += 3;
if (params.has_normal) {
- normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb;
+ normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]);
src_offset++;
}
if (params.has_tangent) {
- tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]);
+ tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]);
}
if (params.has_blend_shape) {
@@ -155,12 +195,12 @@ void main() {
base_offset += 3;
if (params.has_normal) {
- blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w;
base_offset++;
}
if (params.has_tangent) {
- blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w;
}
blend_total += w;
@@ -234,12 +274,12 @@ void main() {
dst_offset += 3;
if (params.has_normal) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0));
+ dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal);
dst_offset++;
}
if (params.has_tangent) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent);
+ dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent);
}
#endif
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index d3831b4618..b845c1155e 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -75,6 +75,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ light.param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_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;
@@ -88,9 +89,9 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
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_OPACITY] = 1.0;
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);
@@ -351,7 +352,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
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;
+ float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
};
case RS::LIGHT_OMNI: {
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 3e3246e8e9..7e98a3cb8e 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -250,13 +250,6 @@ public:
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;
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 8297e72260..fa8406e7a1 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -941,6 +941,12 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa
continue; //instance uniforms don't appear in the buffer
}
+ if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
@@ -1052,6 +1058,12 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
Vector<RID> textures;
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
@@ -1125,6 +1137,9 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
} break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_TRANSPARENT);
+ } break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_ANISO);
} break;
@@ -1304,7 +1319,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
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) {
+ 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;
}
@@ -2403,11 +2418,11 @@ String MaterialStorage::shader_get_code(RID p_shader) const {
return shader->code;
}
-void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+void MaterialStorage::shader_get_shader_uniform_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);
+ return shader->data->get_shader_uniform_list(p_param_list);
}
}
@@ -2669,14 +2684,14 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}
-void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+void MaterialStorage::material_get_instance_shader_uniforms(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);
+ material_get_instance_shader_uniforms(material->next_pass, r_parameters);
}
}
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index cb98a78bf8..dbf7a92e23 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -57,7 +57,7 @@ public:
virtual void set_code(const String &p_Code) = 0;
virtual void set_path_hint(const String &p_hint) = 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_shader_uniform_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;
@@ -362,7 +362,7 @@ public:
virtual void shader_set_code(RID p_shader, const String &p_code) override;
virtual void shader_set_path_hint(RID p_shader, const String &p_path) 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_get_shader_uniform_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;
@@ -394,7 +394,7 @@ public:
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_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override;
virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index dc3f35f942..49d7198ec2 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -327,8 +327,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
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.vertex_data.size()) {
+ 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);
@@ -345,7 +347,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
+ bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
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;
@@ -364,6 +366,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
}
+ ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
@@ -377,7 +381,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s->vertex_buffer);
+ if (s->vertex_buffer.is_valid()) {
+ u.append_id(s->vertex_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
uniforms.push_back(u);
}
{
@@ -416,7 +424,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
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]);
+ const AABB &bone = p_surface.bone_aabbs[i];
+ if (!bone.has_no_volume()) {
+ mesh->bone_aabbs.write[i].merge_with(bone);
+ }
}
mesh->aabb.merge_with(p_surface.aabb);
}
@@ -467,6 +478,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i
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]->vertex_buffer.is_null());
uint64_t data_size = p_data.size();
const uint8_t *r = p_data.ptr();
@@ -524,7 +536,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.vertex_buffer.is_valid()) {
+ 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);
}
@@ -702,7 +716,9 @@ void MeshStorage::mesh_clear(RID 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.vertex_buffer.is_valid()) {
+ 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);
}
@@ -848,7 +864,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
}
MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
+ if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
//surface warrants transform
s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
@@ -1057,10 +1073,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_NORMAL: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
@@ -1069,9 +1084,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_TANGENT: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 3ca648b0d0..022b027644 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -134,7 +134,7 @@ void process() {
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, MaterialStorage::SHADER_TYPE_PARTICLES));
+ ParticleProcessMaterialData *md = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -1072,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
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, MaterialStorage::SHADER_TYPE_PARTICLES));
+ ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES));
if (!m) {
- m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
+ m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
}
ERR_FAIL_COND(!m);
@@ -1603,7 +1603,7 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri
}
}
-void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void ParticlesStorage::ParticlesShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -1696,16 +1696,16 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() {
return shader_data;
}
-bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool ParticlesStorage::ParticleProcessMaterialData::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() {
+ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() {
free_parameters_uniform_set(uniform_set);
}
MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
- ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
+ ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 04ecfcfdce..299fdc6ec8 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -159,7 +159,7 @@ private:
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 use_local_coords = false;
bool has_collision_cache = false;
bool has_sdf_collision = false;
@@ -337,7 +337,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -354,14 +354,14 @@ private:
return ParticlesStorage::get_singleton()->_create_particles_shader_func();
}
- struct ParticlesMaterialData : public MaterialStorage::MaterialData {
+ struct ParticleProcessMaterialData : public MaterialStorage::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();
+ virtual ~ParticleProcessMaterialData();
};
MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 17a6ad57f9..ce19187071 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -96,6 +96,7 @@ TextureStorage::TextureStorage() {
Vector<uint8_t> pv;
pv.resize(16 * 4);
for (int i = 0; i < 16; i++) {
+ // Opaque white.
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 255);
pv.set(i * 4 + 2, 255);
@@ -109,6 +110,7 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Opaque black.
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
pv.set(i * 4 + 2, 0);
@@ -122,6 +124,21 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Transparent black.
+ 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_TRANSPARENT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ // Opaque normal map "flat" color.
pv.set(i * 4 + 0, 128);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
@@ -135,6 +152,7 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Opaque flowmap "flat" color.
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
@@ -398,7 +416,10 @@ TextureStorage::TextureStorage() {
tformat.format = RD::DATA_FORMAT_R8_UINT;
tformat.width = 4;
tformat.height = 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ if (RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
+ tformat.usage_bits |= RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
+ }
tformat.texture_type = RD::TEXTURE_TYPE_2D;
Vector<uint8_t> pv;
@@ -2100,6 +2121,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
RD::get_singleton()->free(rt->color);
}
+ if (rt->color_multisample.is_valid()) {
+ RD::get_singleton()->free(rt->color_multisample);
+ }
+
if (rt->backbuffer.is_valid()) {
RD::get_singleton()->free(rt->backbuffer);
rt->backbuffer = RID();
@@ -2111,6 +2136,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
rt->framebuffer = RID();
rt->color = RID();
+ rt->color_multisample = RID();
}
void TextureStorage::_update_render_target(RenderTarget *rt) {
@@ -2132,30 +2158,50 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
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::TextureFormat rd_color_attachment_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;
+ rd_color_attachment_format.format = rt->color_format;
+ rd_color_attachment_format.width = rt->size.width;
+ rd_color_attachment_format.height = rt->size.height;
+ rd_color_attachment_format.depth = 1;
+ rd_color_attachment_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_color_attachment_format.mipmaps = 1;
+ if (rd_color_attachment_format.array_layers > 1) { // why are we not using rt->texture_type ??
+ rd_color_attachment_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
} else {
- rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ rd_color_attachment_format.texture_type = RD::TEXTURE_TYPE_2D;
+ }
+ rd_color_attachment_format.samples = RD::TEXTURE_SAMPLES_1;
+ rd_color_attachment_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ rd_color_attachment_format.shareable_formats.push_back(rt->color_format);
+ rd_color_attachment_format.shareable_formats.push_back(rt->color_format_srgb);
+ if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ rd_color_attachment_format.is_resolve_buffer = true;
}
- 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);
+ rt->color = RD::get_singleton()->texture_create(rd_color_attachment_format, rd_view);
ERR_FAIL_COND(rt->color.is_null());
Vector<RID> fb_textures;
+
+ if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ // Use the texture format of the color attachment for the multisample color attachment.
+ RD::TextureFormat rd_color_multisample_format = rd_color_attachment_format;
+ const RD::TextureSamples texture_samples[RS::VIEWPORT_MSAA_MAX] = {
+ RD::TEXTURE_SAMPLES_1,
+ RD::TEXTURE_SAMPLES_2,
+ RD::TEXTURE_SAMPLES_4,
+ RD::TEXTURE_SAMPLES_8,
+ };
+ rd_color_multisample_format.samples = texture_samples[rt->msaa];
+ RD::TextureView rd_view_multisample;
+ rd_color_multisample_format.is_resolve_buffer = false;
+ rt->color_multisample = RD::get_singleton()->texture_create(rd_color_multisample_format, rd_view_multisample);
+ fb_textures.push_back(rt->color_multisample);
+ ERR_FAIL_COND(rt->color_multisample.is_null());
+ }
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()) {
@@ -2314,6 +2360,17 @@ void TextureStorage::render_target_set_as_unused(RID p_render_target) {
rt->was_used = false;
}
+void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (p_msaa == rt->msaa) {
+ return;
+ }
+
+ rt->msaa = p_msaa;
+ _update_render_target(rt);
+}
+
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());
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index f07f764761..25d355d878 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -46,6 +46,7 @@ public:
enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_WHITE,
DEFAULT_RD_TEXTURE_BLACK,
+ DEFAULT_RD_TEXTURE_TRANSPARENT,
DEFAULT_RD_TEXTURE_NORMAL,
DEFAULT_RD_TEXTURE_ANISO,
DEFAULT_RD_TEXTURE_DEPTH,
@@ -253,6 +254,9 @@ private:
uint32_t view_count;
RID framebuffer;
RID color;
+ RID color_multisample; // Needed when MSAA is enabled.
+
+ RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
//used for retrieving from CPU
RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
@@ -555,6 +559,7 @@ public:
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;
+ virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) 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);
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
index 5a91046628..fcef2f24bf 100644
--- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
@@ -290,9 +290,14 @@ bool Utilities::has_os_feature(const String &p_feature) const {
return true;
}
+#if !defined(ANDROID_ENABLED) && !defined(IOS_ENABLED)
+ // Some Android devices report support for S3TC but we don't expect that and don't export the textures.
+ // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
+ // For good measure we do the same hack for iOS, just in case.
if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
+#endif
if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
index abf110730b..bca8b02178 100644
--- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
@@ -163,7 +163,7 @@ public:
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...)) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && sizeof...(Args) == c->uniforms.size() && _compare_args(0, c->uniforms, args...)) {
return c->cache;
}
c = c->next;
@@ -193,7 +193,7 @@ public:
const Cache *c = hash_table[table_idx];
while (c) {
- if (c->hash == h && c->set == p_set && c->shader == p_shader) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && (uint32_t)p_uniforms.size() == c->uniforms.size()) {
bool all_ok = true;
for (int i = 0; i < p_uniforms.size(); i++) {
if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) {
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 852fe89cd0..ba6fb71e67 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -100,10 +100,10 @@ public:
virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
- virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
- virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
- virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
- virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0;
+ virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
+ virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
+ virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const = 0;
+ virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const = 0;
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 368bbb63f5..6846916f3f 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -506,7 +506,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
if (instance->mesh_instance.is_valid()) {
- RSG::mesh_storage->mesh_free(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(instance->mesh_instance);
instance->mesh_instance = RID();
// no need to set instance data flag here, as it was freed above
}
@@ -637,6 +637,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = geom;
geom->geometry_instance = scene_render->geometry_instance_create(p_base);
+ ERR_FAIL_NULL(geom->geometry_instance);
+
geom->geometry_instance->set_skeleton(instance->skeleton);
geom->geometry_instance->set_material_override(instance->material_override);
geom->geometry_instance->set_material_overlay(instance->material_overlay);
@@ -836,6 +838,7 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_layer_mask(p_mask);
}
}
@@ -848,6 +851,7 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_transparency(p_transparency);
}
}
@@ -1009,6 +1013,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
_instance_update_mesh_instance(instance);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_skeleton(p_skeleton);
}
}
@@ -1129,6 +1134,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_use_baked_light(p_enabled);
}
@@ -1149,6 +1155,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_use_dynamic_gi(p_enabled);
}
@@ -1207,6 +1214,8 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
+
geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
}
@@ -1222,6 +1231,7 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_material_override(p_material);
}
}
@@ -1235,6 +1245,7 @@ void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, R
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_material_overlay(p_material);
}
}
@@ -1407,6 +1418,7 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
}
}
@@ -1419,66 +1431,67 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_lod_bias(p_lod_bias);
}
}
-void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
+void RendererSceneCull::instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter);
+ HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_uniforms.find(p_parameter);
if (!E) {
Instance::InstanceShaderParameter isp;
isp.index = -1;
isp.info = PropertyInfo();
isp.value = p_value;
- instance->instance_shader_parameters[p_parameter] = isp;
+ instance->instance_shader_uniforms[p_parameter] = isp;
} else {
E->value.value = p_value;
- if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) {
+ if (E->value.index >= 0 && instance->instance_allocated_shader_uniforms) {
//update directly
RSG::material_storage->global_shader_uniforms_instance_update(p_instance, E->value.index, p_value);
}
}
}
-Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
+Variant RendererSceneCull::instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const {
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
- if (instance->instance_shader_parameters.has(p_parameter)) {
- return instance->instance_shader_parameters[p_parameter].value;
+ if (instance->instance_shader_uniforms.has(p_parameter)) {
+ return instance->instance_shader_uniforms[p_parameter].value;
}
return Variant();
}
-Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
+Variant RendererSceneCull::instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const {
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
- if (instance->instance_shader_parameters.has(p_parameter)) {
- return instance->instance_shader_parameters[p_parameter].default_value;
+ if (instance->instance_shader_uniforms.has(p_parameter)) {
+ return instance->instance_shader_uniforms[p_parameter].default_value;
}
return Variant();
}
-void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
+void RendererSceneCull::instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
const_cast<RendererSceneCull *>(this)->update_dirty_instances();
Vector<StringName> names;
- for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_parameters) {
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_uniforms) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
for (int i = 0; i < names.size(); i++) {
- PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
+ PropertyInfo pinfo = instance->instance_shader_uniforms[names[i]].info;
p_parameters->push_back(pinfo);
}
}
@@ -1587,10 +1600,12 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (!p_instance->lightmap_sh.is_empty()) {
p_instance->lightmap_sh.clear(); //don't need SH
p_instance->lightmap_target_sh.clear(); //don't need SH
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_lightmap_capture(nullptr);
}
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_transform(p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
}
@@ -1817,6 +1832,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
// Clear these now because the InstanceData containing the dirty flags is gone
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->pair_light_instances(nullptr, 0);
geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0);
@@ -1990,6 +2006,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
}
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr());
}
@@ -2146,7 +2163,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
if (soft_shadow_angle > 0.0) {
float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
- soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range;
+ soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range;
x_max += soft_shadow_expand;
y_max += soft_shadow_expand;
@@ -2757,6 +2774,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->pair_light_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
}
@@ -2764,6 +2782,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY);
}
@@ -2781,6 +2800,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
}
@@ -2797,7 +2817,10 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
break;
}
}
+
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx);
+
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
}
@@ -2813,7 +2836,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
+
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
@@ -2824,6 +2849,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
for (uint32_t j = 0; j < 9; j++) {
sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_lightmap_capture(sh);
idata.instance->last_frame_pass = frame_number;
}
@@ -3125,8 +3151,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
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));
+ float w = radius * Math::sin(Math::deg_to_rad(angle));
+ float d = radius * Math::cos(Math::deg_to_rad(angle));
Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;
@@ -3588,11 +3614,13 @@ void RendererSceneCull::render_probes() {
}
}
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
+ ERR_FAIL_NULL(geom->geometry_instance);
scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
@@ -3633,6 +3661,7 @@ void RendererSceneCull::render_particle_colliders() {
continue;
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
@@ -3642,9 +3671,9 @@ void RendererSceneCull::render_particle_colliders() {
}
}
-void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
+void RendererSceneCull::_update_instance_shader_uniforms_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);
+ RSG::material_storage->material_get_instance_shader_uniforms(p_material, &plist);
for (const RendererMaterialStorage::InstanceShaderParam &E : plist) {
StringName name = E.info.name;
if (isparams.has(name)) {
@@ -3724,7 +3753,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false;
}
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);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_override);
} else {
if (p_instance->base_type == RS::INSTANCE_MESH) {
RID mesh = p_instance->base;
@@ -3746,7 +3775,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3777,7 +3806,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3815,7 +3844,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3831,7 +3860,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->material_overlay.is_valid()) {
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);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_overlay);
}
if (can_cast_shadows != geom->can_cast_shadows) {
@@ -3845,23 +3874,25 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
geom->material_is_animated = is_animated;
- p_instance->instance_shader_parameters = isparams;
+ p_instance->instance_shader_uniforms = isparams;
- if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
- p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
- if (p_instance->instance_allocated_shader_parameters) {
- p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_shader_uniforms_instance_allocate(p_instance->self);
- geom->geometry_instance->set_instance_shader_parameters_offset(p_instance->instance_allocated_shader_parameters_offset);
+ if (p_instance->instance_allocated_shader_uniforms != (p_instance->instance_shader_uniforms.size() > 0)) {
+ p_instance->instance_allocated_shader_uniforms = (p_instance->instance_shader_uniforms.size() > 0);
+ if (p_instance->instance_allocated_shader_uniforms) {
+ p_instance->instance_allocated_shader_uniforms_offset = RSG::material_storage->global_shader_uniforms_instance_allocate(p_instance->self);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_allocated_shader_uniforms_offset);
- for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_uniforms) {
if (E.value.value.get_type() != Variant::NIL) {
RSG::material_storage->global_shader_uniforms_instance_update(p_instance->self, E.value.index, E.value.value);
}
}
} else {
RSG::material_storage->global_shader_uniforms_instance_free(p_instance->self);
- p_instance->instance_allocated_shader_parameters_offset = -1;
- geom->geometry_instance->set_instance_shader_parameters_offset(-1);
+ p_instance->instance_allocated_shader_uniforms_offset = -1;
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_instance_shader_uniforms_offset(-1);
}
}
}
@@ -3874,6 +3905,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_surface_materials(p_instance->materials);
}
}
@@ -3953,7 +3985,7 @@ bool RendererSceneCull::free(RID p_rid) {
instance_geometry_set_material_overlay(p_rid, RID());
instance_attach_skeleton(p_rid, RID());
- if (instance->instance_allocated_shader_parameters) {
+ if (instance->instance_allocated_shader_uniforms) {
//free the used shader parameters
RSG::material_storage->global_shader_uniforms_instance_free(instance->self);
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 3a2b0a0fdf..540fb0e27a 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -426,9 +426,9 @@ public:
PropertyInfo info;
};
- HashMap<StringName, InstanceShaderParameter> instance_shader_parameters;
- bool instance_allocated_shader_parameters = false;
- int32_t instance_allocated_shader_parameters_offset = -1;
+ HashMap<StringName, InstanceShaderParameter> instance_shader_uniforms;
+ bool instance_allocated_shader_uniforms = false;
+ int32_t instance_allocated_shader_uniforms_offset = -1;
//
@@ -967,12 +967,12 @@ 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(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
+ void _update_instance_shader_uniforms_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;
- virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const;
- virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const;
+ virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value);
+ virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
+ virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const;
+ virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const;
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 118bf532b3..b6f515b223 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -72,6 +72,41 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
+Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() {
+ // We need to sort the viewports in a "topological order",
+ // children first and parents last, we use the Kahn's algorithm to achieve that.
+
+ Vector<Viewport *> result;
+ List<Viewport *> nodes;
+
+ for (Viewport *viewport : active_viewports) {
+ if (viewport->parent.is_valid()) {
+ continue;
+ }
+
+ nodes.push_back(viewport);
+ }
+
+ while (!nodes.is_empty()) {
+ Viewport *node = nodes[0];
+ nodes.pop_front();
+
+ result.insert(0, node);
+
+ for (Viewport *child : active_viewports) {
+ if (child->parent != node->self) {
+ continue;
+ }
+
+ if (!nodes.find(child)) {
+ nodes.push_back(child);
+ }
+ }
+ }
+
+ return result;
+}
+
void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->render_buffers.is_valid()) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
@@ -138,7 +173,11 @@ 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->texture_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
+ // At resolution scales lower than 1.0, use negative texture mipmap bias
+ // to compensate for the loss of sharpness.
+ const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
+
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@@ -544,8 +583,10 @@ void RendererViewport::draw_viewports() {
set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
}
- //sort viewports
- active_viewports.sort_custom<ViewportSort>();
+ if (sorted_active_viewports_dirty) {
+ sorted_active_viewports = _sort_active_viewports();
+ sorted_active_viewports_dirty = false;
+ }
HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
@@ -554,9 +595,9 @@ void RendererViewport::draw_viewports() {
//determine what is visible
draw_viewports_pass++;
- for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
+ for (int i = sorted_active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
- Viewport *vp = active_viewports[i];
+ Viewport *vp = sorted_active_viewports[i];
if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) {
continue;
@@ -617,8 +658,8 @@ void RendererViewport::draw_viewports() {
int objects_drawn = 0;
int draw_calls_used = 0;
- for (int i = 0; i < active_viewports.size(); i++) {
- Viewport *vp = active_viewports[i];
+ for (int i = 0; i < sorted_active_viewports.size(); i++) {
+ Viewport *vp = sorted_active_viewports[i];
if (vp->last_pass != draw_viewports_pass) {
continue; //should not draw
@@ -810,6 +851,8 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
} else {
active_viewports.erase(viewport);
}
+
+ sorted_active_viewports_dirty = true;
}
void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
@@ -1033,14 +1076,25 @@ void RendererViewport::viewport_set_positional_shadow_atlas_quadrant_subdivision
RSG::scene->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
}
-void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
+void RendererViewport::viewport_set_msaa_2d(RID p_viewport, RS::ViewportMSAA p_msaa) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ if (viewport->msaa_2d == p_msaa) {
+ return;
+ }
+ viewport->msaa_2d = p_msaa;
+ RSG::texture_storage->render_target_set_msaa(viewport->render_target, p_msaa);
+}
+
+void RendererViewport::viewport_set_msaa_3d(RID p_viewport, RS::ViewportMSAA p_msaa) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- if (viewport->msaa == p_msaa) {
+ if (viewport->msaa_3d == p_msaa) {
return;
}
- viewport->msaa = p_msaa;
+ viewport->msaa_3d = p_msaa;
_configure_3d_render_buffers(viewport);
}
@@ -1239,6 +1293,7 @@ bool RendererViewport::free(RID p_rid) {
viewport_set_scenario(p_rid, RID());
active_viewports.erase(viewport);
+ sorted_active_viewports_dirty = true;
if (viewport->use_occlusion_culling) {
RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid);
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 5e37c96336..f64b2a986f 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -66,7 +66,8 @@ public:
RID render_target_texture;
RID render_buffers;
- RS::ViewportMSAA msaa = RenderingServer::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportMSAA msaa_2d = RenderingServer::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportMSAA msaa_3d = RenderingServer::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_taa = false;
bool use_debanding = false;
@@ -157,7 +158,6 @@ public:
measure_render_time = false;
debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
- msaa = RS::VIEWPORT_MSAA_DISABLED;
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
use_debanding = false;
use_occlusion_culling = false;
@@ -185,25 +185,16 @@ public:
mutable RID_Owner<Viewport, true> viewport_owner;
- struct ViewportSort {
- _FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
- bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2();
- bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2();
-
- if (left_to_screen == right_to_screen) {
- return p_right->parent == p_left->self;
- }
- return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1);
- }
- };
-
Vector<Viewport *> active_viewports;
+ Vector<Viewport *> sorted_active_viewports;
+ bool sorted_active_viewports_dirty = false;
int total_objects_drawn = 0;
int total_vertices_drawn = 0;
int total_draw_calls_used = 0;
private:
+ Vector<Viewport *> _sort_active_viewports();
void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
void _draw_viewport(Viewport *p_viewport);
@@ -259,7 +250,8 @@ public:
void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true);
void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
- void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
+ void viewport_set_msaa_2d(RID p_viewport, RS::ViewportMSAA p_msaa);
+ void viewport_set_msaa_3d(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);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 0b76bb3051..2fefdbff52 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -387,6 +387,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
+ ClassDB::bind_method(D_METHOD("framebuffer_is_valid", "framebuffer"), &RenderingDevice::framebuffer_is_valid);
ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
@@ -428,6 +429,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants);
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 03aa6f7644..276ba8f247 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -129,6 +129,8 @@ public:
typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device);
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
+ typedef void (*InvalidationCallback)(void *);
+
private:
static ShaderCompileToSPIRVFunction compile_to_spirv_function;
static ShaderCacheFunction cache_function;
@@ -460,6 +462,7 @@ public:
TextureSamples samples;
uint32_t usage_bits;
Vector<DataFormat> shareable_formats;
+ bool is_resolve_buffer = false;
TextureFormat() {
format = DATA_FORMAT_R8_UNORM;
@@ -547,13 +550,15 @@ public:
int32_t vrs_attachment = ATTACHMENT_UNUSED; // density map for VRS, only used if supported
};
- virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
+ virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0) = 0;
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
- virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
+ virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
+ virtual bool framebuffer_is_valid(RID p_framebuffer) const = 0;
+ virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) = 0;
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
@@ -793,8 +798,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
- typedef void (*UniformSetInvalidatedCallback)(void *);
- virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0;
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
@@ -1126,6 +1130,7 @@ public:
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
+ virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0;
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0;
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0;
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index 8bdd3deea1..a56b7eb241 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -443,8 +443,8 @@ public:
void add_id(const RID &p_id) { base.append_id(p_id); }
void clear_ids() { base.clear_ids(); }
- Array get_ids() const {
- Array ids;
+ TypedArray<RID> get_ids() const {
+ TypedArray<RID> ids;
for (uint32_t i = 0; i < base.get_id_count(); i++) {
ids.push_back(base.get_id(i));
}
@@ -452,7 +452,7 @@ public:
}
protected:
- void _set_ids(const Array &p_ids) {
+ void _set_ids(const TypedArray<RID> &p_ids) {
base.clear_ids();
for (int i = 0; i < p_ids.size(); i++) {
RID id = p_ids[i];
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 21a94b88f2..ba70f02ca5 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -227,7 +227,7 @@ public:
FUNC2(shader_set_path_hint, RID, const String &)
FUNC1RC(String, shader_get_code, RID)
- FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
+ FUNC2SC(shader_get_shader_uniform_list, RID, List<PropertyInfo> *)
FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int)
FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int)
@@ -619,7 +619,8 @@ public:
FUNC3(viewport_set_positional_shadow_atlas_size, RID, int, bool)
FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
FUNC3(viewport_set_positional_shadow_atlas_quadrant_subdivision, RID, int, int)
- FUNC2(viewport_set_msaa, RID, ViewportMSAA)
+ FUNC2(viewport_set_msaa_2d, RID, ViewportMSAA)
+ FUNC2(viewport_set_msaa_3d, RID, ViewportMSAA)
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
FUNC2(viewport_set_use_taa, RID, bool)
FUNC2(viewport_set_use_debanding, RID, bool)
@@ -773,10 +774,10 @@ public:
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
FUNC2(instance_geometry_set_lod_bias, RID, float)
FUNC2(instance_geometry_set_transparency, RID, float)
- FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
- FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
- FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
- FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
+ FUNC3(instance_geometry_set_shader_uniform, RID, const StringName &, const Variant &)
+ FUNC2RC(Variant, instance_geometry_get_shader_uniform, RID, const StringName &)
+ FUNC2RC(Variant, instance_geometry_get_shader_uniform_default_value, RID, const StringName &)
+ FUNC2C(instance_geometry_get_shader_uniform_list, RID, List<PropertyInfo> *)
FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
@@ -831,6 +832,7 @@ public:
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
+ FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 7637eae4a6..f14350305a 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -498,6 +498,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
if (SL::is_sampler_type(E.value.type)) {
+ if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
max_texture_uniforms++;
} else {
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
@@ -537,6 +542,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
p_actions.uniforms->insert(uniform_name, uniform);
continue; // Instances are indexed directly, don't need index uniforms.
}
+
+ if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
+
if (SL::is_sampler_type(uniform.type)) {
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
if (!RS::get_singleton()->is_low_end()) {
@@ -892,12 +904,39 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
+ if (vnode->name == "SCREEN_TEXTURE") {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
} else {
if (shader->uniforms.has(vnode->name)) {
//its a uniform!
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
if (u.texture_order >= 0) {
- code = _mkid(vnode->name); //texture, use as is
+ StringName name = vnode->name;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ name = "SCREEN_TEXTURE";
+ if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ name = "NORMAL_ROUGHNESS_TEXTURE";
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ name = "DEPTH_TEXTURE";
+ } else {
+ name = _mkid(vnode->name); //texture, use as is
+ }
+
+ if (p_default_actions.renames.has(name)) {
+ code = p_default_actions.renames[name];
+ } else {
+ code = name;
+ }
+
+ if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) {
+ *p_actions.usage_flag_pointers[name] = true;
+ used_flag_pointers.insert(name);
+ }
+
} else {
//a scalar or vector
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
@@ -1155,6 +1194,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
if (correct_texture_uniform) {
+ //TODO Needs to detect screen_texture hint as well
is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@@ -1404,6 +1444,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
r_gen_code.uses_fragment_time = false;
r_gen_code.uses_vertex_time = false;
r_gen_code.uses_global_textures = false;
+ r_gen_code.uses_screen_texture_mipmaps = false;
used_name_defines.clear();
used_rmode_defines.clear();
@@ -1434,8 +1475,11 @@ void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) {
texture_functions.insert("textureLod");
texture_functions.insert("textureProjLod");
texture_functions.insert("textureGrad");
+ texture_functions.insert("textureProjGrad");
texture_functions.insert("textureGather");
texture_functions.insert("textureSize");
+ texture_functions.insert("textureQueryLod");
+ texture_functions.insert("textureQueryLevels");
texture_functions.insert("texelFetch");
}
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index 06f42e9f0f..1ad43daf5f 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -80,6 +80,7 @@ public:
bool uses_global_textures;
bool uses_fragment_time;
bool uses_vertex_time;
+ bool uses_screen_texture_mipmaps;
};
struct DefaultIdentifierActions {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 2dd0f7006b..2bbc5e4dfb 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -195,10 +195,14 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"SOURCE_COLOR",
"HINT_DEFAULT_WHITE_TEXTURE",
"HINT_DEFAULT_BLACK_TEXTURE",
+ "HINT_DEFAULT_TRANSPARENT_TEXTURE",
"HINT_NORMAL_TEXTURE",
"HINT_ANISOTROPY_TEXTURE",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
+ "HINT_SCREEN_TEXTURE",
+ "HINT_NORMAL_ROUGHNESS_TEXTURE",
+ "HINT_DEPTH_TEXTURE",
"FILTER_NEAREST",
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
@@ -354,6 +358,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ 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_DEFAULT_TRANSPARENT_TEXTURE, "hint_default_transparent", 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, {}, {} },
@@ -361,6 +366,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ 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_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", 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, {}, {} },
@@ -1088,9 +1097,21 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
case ShaderNode::Uniform::HINT_DEFAULT_WHITE: {
result = "hint_default_white";
} break;
+ case ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ result = "hint_default_transparent";
+ } break;
case ShaderNode::Uniform::HINT_ANISOTROPY: {
result = "hint_anisotropy";
} break;
+ case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: {
+ result = "hint_screen_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ result = "hint_normal_roughness_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: {
+ result = "hint_depth_texture";
+ } break;
default:
break;
}
@@ -2458,11 +2479,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// reflect
+ { "reflect", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
{ "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
+ { "reflect", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
// refract
+ { "refract", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
{ "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
+ { "refract", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
// faceforward
@@ -2723,6 +2748,18 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "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 },
+ // textureProjGrad
+
+ { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, 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, false },
@@ -2740,6 +2777,32 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "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 },
+ // textureQueryLod
+
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLERCUBE, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+
+ // textureQueryLevels
+
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER2D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER2D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER2D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER3D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER3D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER3D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLERCUBE }, { "sampler" }, TAG_GLOBAL, true },
+
// dFdx
{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
@@ -5314,6 +5377,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
_set_tkpos(prev_pos);
+ ShaderNode::Varying &var = shader->varyings[identifier];
String error;
if (is_token_operator_assign(next_token.type)) {
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
@@ -5321,8 +5385,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
} else {
- ShaderNode::Varying &var = shader->varyings[identifier];
-
switch (var.stage) {
case ShaderNode::Varying::STAGE_VERTEX:
if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
@@ -5338,6 +5400,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
}
+
+ if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) {
+ _set_tkpos(var.tkpos);
+ _set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier."));
+ return nullptr;
+ }
}
if (ident_type == IDENTIFIER_FUNCTION) {
@@ -7153,9 +7221,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!n) {
return ERR_PARSE_ERROR;
}
- if (n->get_datatype() != TYPE_INT) {
- _set_error(RTR("Expected an integer expression."));
- return ERR_PARSE_ERROR;
+ {
+ const ShaderLanguage::DataType switch_type = n->get_datatype();
+ if (switch_type != TYPE_INT && switch_type != TYPE_UINT) {
+ _set_error(RTR("Expected an integer expression."));
+ return ERR_PARSE_ERROR;
+ }
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
@@ -8233,8 +8304,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
- 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."));
+ if (!is_uniform && type > TYPE_MAT4) {
+ _set_error(RTR("Invalid data type for varying."));
return ERR_PARSE_ERROR;
}
@@ -8410,6 +8481,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_HINT_DEFAULT_WHITE_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE;
} break;
+ case TK_HINT_DEFAULT_TRANSPARENT_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT;
+ } break;
case TK_HINT_NORMAL_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_NORMAL;
} break;
@@ -8552,6 +8626,15 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
} break;
+ case TK_HINT_SCREEN_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE;
+ } break;
+ case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE;
+ } break;
+ case TK_HINT_DEPTH_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE;
+ } break;
case TK_FILTER_NEAREST: {
new_filter = FILTER_NEAREST;
} break;
@@ -8576,6 +8659,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_REPEAT_ENABLE: {
new_repeat = REPEAT_ENABLE;
} break;
+
default:
break;
}
@@ -8600,9 +8684,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
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)));
+ _set_error(vformat(RTR("Duplicated filter mode: '%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)));
+ _set_error(vformat(RTR("Redefinition of filter mode: '%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 {
@@ -8613,9 +8697,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
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)));
+ _set_error(vformat(RTR("Duplicated repeat mode: '%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)));
+ _set_error(vformat(RTR("Redefinition of repeat mode: '%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 {
@@ -10248,6 +10332,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_anisotropy");
options.push_back("hint_default_black");
options.push_back("hint_default_white");
+ options.push_back("hint_default_transparent");
options.push_back("hint_normal");
options.push_back("hint_roughness_a");
options.push_back("hint_roughness_b");
@@ -10255,6 +10340,9 @@ 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_screen_texture");
+ options.push_back("hint_normal_roughness_texture");
+ options.push_back("hint_depth_texture");
options.push_back("source_color");
options.push_back("repeat_enable");
options.push_back("repeat_disable");
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 09160e2949..75b713d167 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -164,6 +164,7 @@ public:
TK_RENDER_MODE,
TK_HINT_DEFAULT_WHITE_TEXTURE,
TK_HINT_DEFAULT_BLACK_TEXTURE,
+ TK_HINT_DEFAULT_TRANSPARENT_TEXTURE,
TK_HINT_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_R,
@@ -175,6 +176,9 @@ public:
TK_HINT_SOURCE_COLOR,
TK_HINT_RANGE,
TK_HINT_INSTANCE_INDEX,
+ TK_HINT_SCREEN_TEXTURE,
+ TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
+ TK_HINT_DEPTH_TEXTURE,
TK_FILTER_NEAREST,
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
@@ -664,7 +668,11 @@ public:
HINT_ROUGHNESS_GRAY,
HINT_DEFAULT_BLACK,
HINT_DEFAULT_WHITE,
+ HINT_DEFAULT_TRANSPARENT,
HINT_ANISOTROPY,
+ HINT_SCREEN_TEXTURE,
+ HINT_NORMAL_ROUGHNESS_TEXTURE,
+ HINT_DEPTH_TEXTURE,
HINT_MAX
};
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
index a7b274b3e2..3766477070 100644
--- a/servers/rendering/shader_preprocessor.cpp
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -349,6 +349,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) {
process_ifdef(p_tokenizer);
} else if (directive == "ifndef") {
process_ifndef(p_tokenizer);
+ } else if (directive == "elif") {
+ process_elif(p_tokenizer);
} else if (directive == "else") {
process_else(p_tokenizer);
} else if (directive == "endif") {
@@ -415,24 +417,88 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) {
}
}
+void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ if (state->current_branch == nullptr || state->current_branch->else_defined) {
+ set_error(RTR("Unmatched elif."), line);
+ return;
+ }
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = line - 1;
+ }
+
+ String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ if (body.is_empty()) {
+ set_error(RTR("Missing condition."), line);
+ return;
+ }
+
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ Expression expression;
+ Vector<String> names;
+ error = expression.parse(body, names);
+ if (error != OK) {
+ set_error(expression.get_error_text(), line);
+ return;
+ }
+
+ Variant v = expression.execute(Array(), nullptr, false);
+ if (v.get_type() == Variant::NIL) {
+ set_error(RTR("Condition evaluation error."), line);
+ return;
+ }
+
+ bool skip = false;
+ for (int i = 0; i < state->current_branch->conditions.size(); i++) {
+ if (state->current_branch->conditions[i]) {
+ skip = true;
+ break;
+ }
+ }
+
+ bool success = !skip && v.booleanize();
+ start_branch_condition(p_tokenizer, success, true);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region->parent);
+ }
+}
+
void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
- if (state->skip_stack_else.is_empty()) {
- set_error(RTR("Unmatched else."), p_tokenizer->get_line());
+ const int line = p_tokenizer->get_line();
+
+ if (state->current_branch == nullptr || state->current_branch->else_defined) {
+ set_error(RTR("Unmatched else."), line);
return;
}
- p_tokenizer->advance('\n');
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = line - 1;
+ }
- bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1];
- state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1);
+ p_tokenizer->advance('\n');
- Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include];
- int index = vec.size() - 1;
- if (index >= 0) {
- SkippedCondition *cond = vec[index];
- if (cond->end_line == -1) {
- cond->end_line = p_tokenizer->get_line();
+ bool skip = false;
+ for (int i = 0; i < state->current_branch->conditions.size(); i++) {
+ if (state->current_branch->conditions[i]) {
+ skip = true;
+ break;
}
}
+ state->current_branch->else_defined = true;
+
+ if (state->save_regions) {
+ add_region(line + 1, !skip, state->previous_region->parent);
+ }
if (skip) {
Vector<String> ends;
@@ -447,21 +513,19 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
set_error(RTR("Unmatched endif."), p_tokenizer->get_line());
return;
}
-
- Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include];
- int index = vec.size() - 1;
- if (index >= 0) {
- SkippedCondition *cond = vec[index];
- if (cond->end_line == -1) {
- cond->end_line = p_tokenizer->get_line();
- }
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = p_tokenizer->get_line() - 1;
+ state->previous_region = state->previous_region->parent;
}
p_tokenizer->advance('\n');
+
+ state->current_branch = state->current_branch->parent;
+ state->branches.pop_back();
}
void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
- int line = p_tokenizer->get_line();
+ const int line = p_tokenizer->get_line();
String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
if (body.is_empty()) {
@@ -469,7 +533,12 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
return;
}
- Error error = expand_macros(body, line, body);
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
if (error != OK) {
return;
}
@@ -490,6 +559,10 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
bool success = v.booleanize();
start_branch_condition(p_tokenizer, success);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region);
+ }
}
void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
@@ -510,6 +583,10 @@ void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
bool success = state->defines.has(label);
start_branch_condition(p_tokenizer, success);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region);
+ }
}
void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
@@ -530,6 +607,10 @@ void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
bool success = !state->defines.has(label);
start_branch_condition(p_tokenizer, success);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region);
+ }
}
void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
@@ -594,15 +675,15 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
return;
}
- String old_include = state->current_include;
- state->current_include = real_path;
+ String old_filename = state->current_filename;
+ state->current_filename = real_path;
ShaderPreprocessor processor;
int prev_condition_depth = state->condition_depth;
state->condition_depth = 0;
FilePosition fp;
- fp.file = state->current_include;
+ fp.file = state->current_filename;
fp.line = line;
state->include_positions.push_back(fp);
@@ -614,7 +695,7 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
// Reset to last include if there are no errors. We want to use this as context.
if (state->error.is_empty()) {
- state->current_include = old_include;
+ state->current_filename = old_filename;
state->include_positions.pop_back();
} else {
return;
@@ -668,24 +749,28 @@ void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
state->defines.erase(label);
}
-void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) {
- state->condition_depth++;
+void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent_region) {
+ Region region;
+ region.file = state->current_filename;
+ region.enabled = p_enabled;
+ region.from_line = p_line;
+ region.parent = p_parent_region;
+ state->previous_region = &state->regions[region.file].push_back(region)->get();
+}
- if (p_success) {
- state->skip_stack_else.push_back(true);
+void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue) {
+ if (!p_continue) {
+ state->condition_depth++;
+ state->current_branch = &state->branches.push_back(Branch(p_success, state->current_branch))->get();
} else {
- SkippedCondition *cond = memnew(SkippedCondition());
- cond->start_line = p_tokenizer->get_line();
- state->skipped_conditions[state->current_include].push_back(cond);
-
+ state->current_branch->conditions.push_back(p_success);
+ }
+ if (!p_success) {
Vector<String> ends;
+ ends.push_back("elif");
ends.push_back("else");
ends.push_back("endif");
- if (next_directive(p_tokenizer, ends) == "else") {
- state->skip_stack_else.push_back(false);
- } else {
- state->skip_stack_else.push_back(true);
- }
+ next_directive(p_tokenizer, ends);
}
}
@@ -702,47 +787,173 @@ void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) {
add_to_output(line);
}
-Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
- Vector<Pair<String, Define *>> active_defines;
- active_defines.resize(state->defines.size());
- int index = 0;
- for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
- active_defines.set(index++, Pair<String, Define *>(E->key(), E->get()));
+Error ShaderPreprocessor::expand_condition(const String &p_string, int p_line, String &r_expanded) {
+ // Checks bracket count to be even + check the cursor position.
+ {
+ int bracket_start_count = 0;
+ int bracket_end_count = 0;
+
+ for (int i = 0; i < p_string.size(); i++) {
+ switch (p_string[i]) {
+ case CURSOR:
+ state->completion_type = COMPLETION_TYPE_CONDITION;
+ break;
+ case '(':
+ bracket_start_count++;
+ break;
+ case ')':
+ bracket_end_count++;
+ break;
+ }
+ }
+ if (bracket_start_count > bracket_end_count) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (bracket_end_count > bracket_start_count) {
+ _set_expected_error("(", p_line);
+ return FAILED;
+ }
}
- return expand_macros(p_string, p_line, active_defines, r_expanded);
+ String result = p_string;
+
+ int index = 0;
+ int index_start = 0;
+ int index_end = 0;
+
+ while (find_match(result, "defined", index, index_start)) {
+ bool open_bracket = false;
+ bool found_word = false;
+ bool word_completed = false;
+
+ LocalVector<char32_t> text;
+ int post_bracket_index = -1;
+ int size = result.size();
+
+ for (int i = (index_start - 1); i < size; i++) {
+ char32_t c = result[i];
+ if (c == 0) {
+ if (found_word) {
+ word_completed = true;
+ }
+ break;
+ }
+ char32_t cs[] = { c, '\0' };
+ String s = String(cs);
+ bool is_space = is_char_space(c);
+
+ if (word_completed) {
+ if (c == ')') {
+ continue;
+ }
+ if (c == '|' || c == '&') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ break;
+ } else if (!is_space) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ } else if (is_space) {
+ if (found_word && !open_bracket) {
+ index_end = i;
+ word_completed = true;
+ }
+ } else if (c == '(') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = true;
+ } else if (c == ')') {
+ if (open_bracket) {
+ if (!found_word) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = false;
+ post_bracket_index = i + 1;
+ } else {
+ index_end = i;
+ }
+ word_completed = true;
+ } else if (is_char_word(c)) {
+ text.push_back(c);
+ found_word = true;
+ } else {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ }
+
+ if (word_completed) {
+ if (open_bracket) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (post_bracket_index != -1) {
+ index_end = post_bracket_index;
+ }
+
+ String body = state->defines.has(vector_to_string(text)) ? "true" : "false";
+ String temp = result;
+
+ result = result.substr(0, index) + body;
+ index_start = result.length();
+ if (index_end > 0) {
+ result += temp.substr(index_end);
+ }
+ } else {
+ set_error(RTR("Invalid macro name."), p_line);
+ return FAILED;
+ }
+ }
+ r_expanded = result;
+ return OK;
}
-Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) {
- r_expanded = p_string;
- // When expanding macros we must only evaluate them once.
- // Later we continue expanding but with the already
- // evaluated macros removed.
- for (int i = 0; i < p_defines.size(); i++) {
- Pair<String, Define *> define_pair = p_defines[i];
-
- Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded);
- if (error != OK) {
- return error;
+Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
+ String iterative = p_string;
+ int pass_count = 0;
+ bool expanded = true;
+
+ while (expanded) {
+ expanded = false;
+
+ // As long as we find something to expand, keep going.
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ if (expand_macros_once(iterative, p_line, E, iterative)) {
+ expanded = true;
+ }
}
- // Remove expanded macro and recursively replace remaining.
- p_defines.remove_at(i);
- return expand_macros(r_expanded, p_line, p_defines, r_expanded);
+ pass_count++;
+ if (pass_count > 50) {
+ set_error(RTR("Macro expansion limit exceeded."), p_line);
+ break;
+ }
}
+ r_expanded = iterative;
+
+ if (!state->error.is_empty()) {
+ return FAILED;
+ }
return OK;
}
-Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) {
+bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded) {
String result = p_line;
- const String &key = p_define_pair.first;
- const Define *define = p_define_pair.second;
+ const String &key = p_define_pair->key();
+ const Define *define = p_define_pair->value();
int index_start = 0;
int index = 0;
- while (find_match(result, key, index, index_start)) {
+ if (find_match(result, key, index, index_start)) {
String body = define->body;
if (define->arguments.size() > 0) {
// Complex macro with arguments.
@@ -750,14 +961,14 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu
int args_end = p_line.find(")", args_start);
if (args_start == -1 || args_end == -1) {
set_error(RTR("Missing macro argument parenthesis."), p_line_number);
- return FAILED;
+ return false;
}
String values = result.substr(args_start + 1, args_end - (args_start + 1));
Vector<String> args = values.split(",");
if (args.size() != define->arguments.size()) {
set_error(RTR("Invalid macro argument count."), p_line_number);
- return FAILED;
+ return false;
}
// Insert macro arguments into the body.
@@ -779,11 +990,13 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu
// Manually reset index_start to where the body value of the define finishes.
// This ensures we don't skip another instance of this macro in the string.
index_start = index + body.length() + 1;
- break;
}
+
+ r_expanded = result;
+ return true;
}
- r_expanded = result;
- return OK;
+
+ return false;
}
bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) {
@@ -874,12 +1087,6 @@ void ShaderPreprocessor::clear() {
memdelete(E->get());
}
- for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) {
- for (SkippedCondition *condition : E->get()) {
- memdelete(condition);
- }
- }
-
memdelete(state);
}
state_owner = false;
@@ -969,8 +1176,12 @@ Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, Strin
return OK;
}
-Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, IncludeCompletionFunction p_include_completion_func) {
+Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, List<Region> *r_regions, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, IncludeCompletionFunction p_include_completion_func) {
State pp_state;
+ if (!p_filename.is_empty()) {
+ pp_state.current_filename = p_filename;
+ pp_state.save_regions = r_regions != nullptr;
+ }
Error err = preprocess(&pp_state, p_code, r_result);
if (err != OK) {
if (r_error_text) {
@@ -980,6 +1191,9 @@ Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, Str
*r_error_position = pp_state.include_positions;
}
}
+ if (r_regions) {
+ *r_regions = pp_state.regions[p_filename];
+ }
if (r_includes) {
*r_includes = pp_state.shader_includes;
}
@@ -988,7 +1202,7 @@ Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, Str
switch (pp_state.completion_type) {
case COMPLETION_TYPE_DIRECTIVE: {
List<String> options;
- get_keyword_list(&options, true);
+ get_keyword_list(&options, true, true);
for (const String &E : options) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
@@ -1007,6 +1221,11 @@ Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, Str
}
} break;
+ case COMPLETION_TYPE_CONDITION: {
+ ScriptLanguage::CodeCompletionOption option("defined", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+
+ } break;
case COMPLETION_TYPE_INCLUDE_PATH: {
if (p_include_completion_func && r_completion_options) {
p_include_completion_func(r_completion_options);
@@ -1020,8 +1239,12 @@ Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, Str
return err;
}
-void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) {
+void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords) {
r_keywords->push_back("define");
+ if (!p_ignore_context_keywords) {
+ r_keywords->push_back("defined");
+ }
+ r_keywords->push_back("elif");
if (p_include_shader_keywords) {
r_keywords->push_back("else");
}
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
index a93fb680dd..b4e7c7199f 100644
--- a/servers/rendering/shader_preprocessor.h
+++ b/servers/rendering/shader_preprocessor.h
@@ -50,6 +50,7 @@ public:
COMPLETION_TYPE_DIRECTIVE,
COMPLETION_TYPE_PRAGMA_DIRECTIVE,
COMPLETION_TYPE_PRAGMA,
+ COMPLETION_TYPE_CONDITION,
COMPLETION_TYPE_INCLUDE_PATH,
};
@@ -58,6 +59,14 @@ public:
int line = 0;
};
+ struct Region {
+ String file;
+ int from_line = -1;
+ int to_line = -1;
+ bool enabled = false;
+ Region *parent = nullptr;
+ };
+
private:
struct Token {
char32_t text;
@@ -122,23 +131,34 @@ private:
String body;
};
- struct SkippedCondition {
- int start_line = -1;
- int end_line = -1;
+ struct Branch {
+ Vector<bool> conditions;
+ Branch *parent = nullptr;
+ bool else_defined = false;
+
+ Branch() {}
+
+ Branch(bool p_condition, Branch *p_parent) :
+ parent(p_parent) {
+ conditions.push_back(p_condition);
+ }
};
struct State {
RBMap<String, Define *> defines;
- Vector<bool> skip_stack_else;
+ List<Branch> branches;
+ Branch *current_branch = nullptr;
int condition_depth = 0;
RBSet<String> includes;
List<uint64_t> cyclic_include_hashes; // Holds code hash of includes.
int include_depth = 0;
- String current_include;
+ String current_filename;
String current_shader_type;
String error;
List<FilePosition> include_positions;
- RBMap<String, Vector<SkippedCondition *>> skipped_conditions;
+ bool save_regions = false;
+ RBMap<String, List<Region>> regions;
+ Region *previous_region = nullptr;
bool disabled = false;
CompletionType completion_type = COMPLETION_TYPE_NONE;
HashSet<Ref<ShaderInclude>> shader_includes;
@@ -156,8 +176,17 @@ private:
static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1);
static String tokens_to_string(const LocalVector<Token> &p_tokens);
+ void _set_expected_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Expected a '%s'."), p_what), p_line);
+ }
+
+ void _set_unexpected_token_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line);
+ }
+
void process_directive(Tokenizer *p_tokenizer);
void process_define(Tokenizer *p_tokenizer);
+ void process_elif(Tokenizer *p_tokenizer);
void process_else(Tokenizer *p_tokenizer);
void process_endif(Tokenizer *p_tokenizer);
void process_if(Tokenizer *p_tokenizer);
@@ -167,12 +196,13 @@ private:
void process_pragma(Tokenizer *p_tokenizer);
void process_undef(Tokenizer *p_tokenizer);
- void start_branch_condition(Tokenizer *p_tokenizer, bool p_success);
+ void add_region(int p_line, bool p_enabled, Region *p_parent_region);
+ void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false);
+ Error expand_condition(const String &p_string, int p_line, String &r_result);
void expand_output_macros(int p_start, int p_line);
Error expand_macros(const String &p_string, int p_line, String &r_result);
- Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result);
- Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded);
+ bool expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded);
bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start);
String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives);
@@ -188,9 +218,9 @@ private:
public:
typedef void (*IncludeCompletionFunction)(List<ScriptLanguage::CodeCompletionOption> *);
- Error preprocess(const String &p_code, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr);
+ Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr);
- static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords);
+ static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords = false);
static void get_pragma_list(List<String> *r_pragmas);
ShaderPreprocessor();
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 5772179d68..43c483a00d 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -97,6 +97,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3;
+
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
@@ -139,6 +144,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3;
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
index 6347b22240..ad8e3e79bf 100644
--- a/servers/rendering/storage/material_storage.h
+++ b/servers/rendering/storage/material_storage.h
@@ -63,7 +63,7 @@ public:
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 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_get_shader_uniform_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;
@@ -94,7 +94,7 @@ public:
Variant default_value;
};
- virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
+ virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
};
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index 982ab4a958..08ff88d4a5 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -133,6 +133,7 @@ public:
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_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) = 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;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index bb76281782..88c20914e1 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -31,6 +31,7 @@
#include "rendering_server.h"
#include "core/config/project_settings.h"
+#include "core/variant/typed_array.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
@@ -69,44 +70,44 @@ Array RenderingServer::_texture_debug_usage_bind() {
return arr;
}
-static Array to_array(const Vector<ObjectID> &ids) {
- Array a;
+static PackedInt64Array to_int_array(const Vector<ObjectID> &ids) {
+ PackedInt64Array a;
a.resize(ids.size());
for (int i = 0; i < ids.size(); ++i) {
- a[i] = ids[i];
+ a.write[i] = ids[i];
}
return a;
}
-Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
+PackedInt64Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
if (RSG::threaded) {
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
}
Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario);
- return to_array(ids);
+ return to_int_array(ids);
}
-Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
+PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
if (RSG::threaded) {
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
}
Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario);
- return to_array(ids);
+ return to_int_array(ids);
}
-Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const {
+PackedInt64Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const {
if (RSG::threaded) {
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
}
Vector<Plane> planes;
for (int i = 0; i < p_convex.size(); ++i) {
Variant v = p_convex[i];
- ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, Array());
+ ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, PackedInt64Array());
planes.push_back(v);
}
Vector<ObjectID> ids = instances_cull_convex(planes, p_scenario);
- return to_array(ids);
+ return to_int_array(ids);
}
RID RenderingServer::get_test_texture() {
@@ -398,16 +399,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const Vector3 *src = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- Vector3 n = src[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
-
- uint32_t value = 0;
- value |= CLAMP(int(n.x * 1023.0), 0, 1023);
- value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+ Vector2 res = src[i].octahedron_encode();
+ int16_t vector[2] = {
+ (int16_t)CLAMP(res.x * 65535, 0, 65535),
+ (int16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4);
}
-
} break;
case RS::ARRAY_TANGENT: {
@@ -416,33 +415,32 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
if (type == Variant::PACKED_FLOAT32_ARRAY) {
Vector<float> array = p_arrays[ai];
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
- const float *src = array.ptr();
+ const float *src_ptr = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- uint32_t value = 0;
- value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
- 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 |= 3UL << 30;
- }
-
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]);
+ Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]);
+ int16_t vector[2] = {
+ (int16_t)CLAMP(res.x * 65535, 0, 65535),
+ (int16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4);
}
} else { // PACKED_FLOAT64_ARRAY
Vector<double> array = p_arrays[ai];
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
- const double *src = array.ptr();
+ const double *src_ptr = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- uint32_t value = 0;
- value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
- 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 |= 3UL << 30;
- }
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]);
+ Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]);
+ int16_t vector[2] = {
+ (int16_t)CLAMP(res.x * 65535, 0, 65535),
+ (int16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4);
}
}
} break;
@@ -627,7 +625,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const int *src = indices.ptr();
for (int i = 0; i < p_index_array_len; i++) {
- if (p_vertex_array_len < (1 << 16)) {
+ if (p_vertex_array_len < (1 << 16) && p_vertex_array_len > 0) {
uint16_t v = src[i];
memcpy(&iw[i * 2], &v, 2);
@@ -836,9 +834,8 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
break;
}
/* determine whether using 16 or 32 bits indices */
- if (p_vertex_len >= (1 << 16)) {
+ if (p_vertex_len >= (1 << 16) || p_vertex_len == 0) {
elem_size = 4;
-
} else {
elem_size = 2;
}
@@ -909,8 +906,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
}
}
- ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory
-
if (p_blend_shapes.size()) {
// Validate format for morphs.
for (int i = 0; i < p_blend_shapes.size(); i++) {
@@ -944,6 +939,12 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
uint32_t mask = (1 << ARRAY_MAX) - 1;
format |= (~mask) & p_compress_format; // Make the full format.
+ if ((format & RS::ARRAY_FORMAT_VERTEX) == 0 && !(format & RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) {
+ ERR_PRINT("Mesh created without vertex array. This mesh will not be visible with the default shader. If using an empty vertex array is intentional, create the mesh with the ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY flag to silence this error.");
+ // Set the flag here after warning to suppress errors down the pipeline.
+ format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY;
+ }
+
int vertex_array_size = vertex_element_size * array_len;
int attrib_array_size = attrib_element_size * array_len;
int skin_array_size = skin_element_size * array_len;
@@ -1337,7 +1338,7 @@ Dictionary RenderingServer::mesh_surface_get_lods(RID p_mesh, int p_surface) con
return ret;
}
-Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const {
+TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const {
SurfaceData sd = mesh_get_surface(p_mesh, p_surface);
ERR_FAIL_COND_V(sd.vertex_count == 0, Array());
@@ -1359,7 +1360,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur
ERR_FAIL_COND_V(blend_shape_count != (uint32_t)mesh_get_blend_shape_count(p_mesh), Array());
- Array blend_shape_array;
+ TypedArray<Array> blend_shape_array;
blend_shape_array.resize(mesh_get_blend_shape_count(p_mesh));
for (uint32_t i = 0; i < blend_shape_count; i++) {
Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor);
@@ -1369,7 +1370,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur
return blend_shape_array;
} else {
- return Array();
+ return TypedArray<Array>();
}
}
@@ -1378,7 +1379,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p
Vector<uint8_t> attrib_data = p_data.attribute_data;
Vector<uint8_t> skin_data = p_data.skin_data;
- ERR_FAIL_COND_V(vertex_data.size() == 0, Array());
+ ERR_FAIL_COND_V(vertex_data.size() == 0 && (p_data.format & RS::ARRAY_FORMAT_VERTEX), Array());
int vertex_len = p_data.vertex_count;
Vector<uint8_t> index_data = p_data.index_data;
@@ -1500,9 +1501,9 @@ TypedArray<Image> RenderingServer::_texture_3d_get(RID p_texture) const {
return ret;
}
-TypedArray<Dictionary> RenderingServer::_shader_get_param_list(RID p_shader) const {
+TypedArray<Dictionary> RenderingServer::_shader_get_shader_uniform_list(RID p_shader) const {
List<PropertyInfo> l;
- shader_get_param_list(p_shader, &l);
+ shader_get_shader_uniform_list(p_shader, &l);
return convert_property_list(&l);
}
@@ -1625,9 +1626,9 @@ Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) {
return d;
}
-Array RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const {
+TypedArray<Dictionary> RenderingServer::_instance_geometry_get_shader_uniform_list(RID p_instance) const {
List<PropertyInfo> params;
- instance_geometry_get_shader_parameter_list(p_instance, &params);
+ instance_geometry_get_shader_uniform_list(p_instance, &params);
return convert_property_list(&params);
}
@@ -1701,7 +1702,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code);
ClassDB::bind_method(D_METHOD("shader_set_path_hint", "shader", "path"), &RenderingServer::shader_set_path_hint);
ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code);
- ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list);
+ ClassDB::bind_method(D_METHOD("shader_get_shader_uniform_list", "shader"), &RenderingServer::_shader_get_shader_uniform_list);
ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default);
ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0));
@@ -1885,9 +1886,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
- BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
@@ -1896,6 +1898,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
@@ -1910,8 +1913,8 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
@@ -1989,9 +1992,10 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX);
BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST);
- BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
/* GI API (affects VoxelGI and SDFGI) */
@@ -2200,7 +2204,8 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_positional_shadow_atlas_size, DEFVAL(false));
ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_positional_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_msaa_3d", "viewport", "msaa"), &RenderingServer::viewport_set_msaa_3d);
+ ClassDB::bind_method(D_METHOD("viewport_set_msaa_2d", "viewport", "msaa"), &RenderingServer::viewport_set_msaa_2d);
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);
@@ -2482,10 +2487,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap);
ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_parameter", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_parameter);
- ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter);
- ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter_default_value);
- ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_list", "instance"), &RenderingServer::_instance_geometry_get_shader_parameter_list);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_uniform", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_uniform);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform_default_value);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_list", "instance"), &RenderingServer::_instance_geometry_get_shader_uniform_list);
ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID()));
@@ -2576,6 +2581,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0));
@@ -2956,9 +2962,9 @@ void RenderingServer::init() {
PROPERTY_HINT_RANGE, "-2,2,0.001"));
GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"));
GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"));
GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512);
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 1f2012ac8d..3feec448e4 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -42,6 +42,9 @@
#include "servers/display_server.h"
#include "servers/rendering/rendering_device.h"
+template <typename T>
+class TypedArray;
+
class RenderingServer : public Object {
GDCLASS(RenderingServer, Object);
@@ -170,7 +173,7 @@ public:
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 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_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0;
@@ -244,7 +247,7 @@ public:
enum ArrayFormat {
/* ARRAY FORMAT FLAGS */
- ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory
+ ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX,
ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL,
ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT,
ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
@@ -262,17 +265,19 @@ public:
ARRAY_FORMAT_CUSTOM_BASE = (ARRAY_INDEX + 1),
ARRAY_FORMAT_CUSTOM_BITS = 3,
+ ARRAY_FORMAT_CUSTOM_MASK = 0x7,
ARRAY_FORMAT_CUSTOM0_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + 0),
ARRAY_FORMAT_CUSTOM1_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS),
ARRAY_FORMAT_CUSTOM2_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 2),
ARRAY_FORMAT_CUSTOM3_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 3),
- ARRAY_FORMAT_CUSTOM_MASK = 0x7,
ARRAY_COMPRESS_FLAGS_BASE = (ARRAY_INDEX + 1 + 12),
ARRAY_FLAG_USE_2D_VERTICES = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 0),
ARRAY_FLAG_USE_DYNAMIC_UPDATE = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 1),
ARRAY_FLAG_USE_8_BONE_WEIGHTS = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 2),
+
+ ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = 1 << (ARRAY_INDEX + 1 + 15),
};
enum PrimitiveType {
@@ -323,7 +328,7 @@ public:
virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0);
Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const;
Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const;
- Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
+ TypedArray<Array> mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const;
virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0);
@@ -411,6 +416,7 @@ public:
enum LightParam {
LIGHT_PARAM_ENERGY,
LIGHT_PARAM_INDIRECT_ENERGY,
+ LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY,
LIGHT_PARAM_SPECULAR,
LIGHT_PARAM_RANGE,
LIGHT_PARAM_SIZE,
@@ -425,8 +431,8 @@ public:
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+ LIGHT_PARAM_SHADOW_OPACITY,
LIGHT_PARAM_SHADOW_BLUR,
- LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
LIGHT_PARAM_TRANSMITTANCE_BIAS,
LIGHT_PARAM_MAX
};
@@ -495,9 +501,10 @@ public:
enum LightProjectorFilter {
LIGHT_PROJECTOR_FILTER_NEAREST,
- LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
LIGHT_PROJECTOR_FILTER_LINEAR,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC,
LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
};
@@ -557,9 +564,10 @@ public:
enum DecalFilter {
DECAL_FILTER_NEAREST,
- DECAL_FILTER_NEAREST_MIPMAPS,
DECAL_FILTER_LINEAR,
+ DECAL_FILTER_NEAREST_MIPMAPS,
DECAL_FILTER_LINEAR_MIPMAPS,
+ DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC,
DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
};
@@ -866,7 +874,8 @@ public:
VIEWPORT_MSAA_MAX,
};
- virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;
+ virtual void viewport_set_msaa_3d(RID p_viewport, ViewportMSAA p_msaa) = 0;
+ virtual void viewport_set_msaa_2d(RID p_viewport, ViewportMSAA p_msaa) = 0;
enum ViewportScreenSpaceAA {
VIEWPORT_SCREEN_SPACE_AA_DISABLED,
@@ -1208,9 +1217,9 @@ public:
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0;
- Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const;
- Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
- Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const;
+ PackedInt64Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const;
+ PackedInt64Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
+ PackedInt64Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const;
enum InstanceFlags {
INSTANCE_FLAG_USE_BAKED_LIGHT,
@@ -1242,10 +1251,10 @@ public:
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0;
- virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0;
- virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0;
- virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &) const = 0;
- virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
+ virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &, const Variant &p_value) = 0;
+ virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &) const = 0;
+ virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &) const = 0;
+ virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
/* Bake 3D objects */
@@ -1318,6 +1327,7 @@ public:
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0;
+ virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0;
@@ -1569,11 +1579,11 @@ private:
RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data);
void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data);
TypedArray<Image> _texture_3d_get(RID p_texture) const;
- TypedArray<Dictionary> _shader_get_param_list(RID p_shader) const;
+ TypedArray<Dictionary> _shader_get_shader_uniform_list(RID p_shader) const;
RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count);
void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface);
Dictionary _mesh_get_surface(RID p_mesh, int p_idx);
- Array _instance_geometry_get_shader_parameter_list(RID p_instance) const;
+ TypedArray<Dictionary> _instance_geometry_get_shader_uniform_list(RID p_instance) const;
TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size);
void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses);
};
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 47598abce7..74ae2bfff0 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -69,8 +69,8 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style");
GDVIRTUAL_BIND(font_get_style_name, "font_rid");
- GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased");
- GDVIRTUAL_BIND(font_is_antialiased, "font_rid");
+ GDVIRTUAL_BIND(font_set_antialiasing, "font_rid", "antialiasing");
+ GDVIRTUAL_BIND(font_get_antialiasing, "font_rid");
GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid");
@@ -297,9 +297,13 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(percent_sign, "language");
GDVIRTUAL_BIND(strip_diacritics, "string");
+ GDVIRTUAL_BIND(is_valid_identifier, "string");
GDVIRTUAL_BIND(string_get_word_breaks, "string", "language");
+ GDVIRTUAL_BIND(is_confusable, "string", "dict");
+ GDVIRTUAL_BIND(spoof_check, "string");
+
GDVIRTUAL_BIND(string_to_upper, "string", "language");
GDVIRTUAL_BIND(string_to_lower, "string", "language");
@@ -474,16 +478,16 @@ String TextServerExtension::font_get_name(const RID &p_font_rid) const {
return String();
}
-void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) {
- GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased);
+void TextServerExtension::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) {
+ GDVIRTUAL_CALL(font_set_antialiasing, p_font_rid, p_antialiasing);
}
-bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) {
+TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(RID p_font_rid) const {
+ TextServer::FontAntialiasing ret;
+ if (GDVIRTUAL_CALL(font_get_antialiasing, p_font_rid, ret)) {
return ret;
}
- return false;
+ return TextServer::FONT_ANTIALIASING_NONE;
}
void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
@@ -630,12 +634,12 @@ double TextServerExtension::font_get_oversampling(const RID &p_font_rid) const {
return 0.0;
}
-Array TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const {
- Array ret;
+TypedArray<Vector2i> TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const {
+ TypedArray<Vector2i> ret;
if (GDVIRTUAL_CALL(font_get_size_cache_list, p_font_rid, ret)) {
return ret;
}
- return Array();
+ return TypedArray<Vector2i>();
}
void TextServerExtension::font_clear_size_cache(const RID &p_font_rid) {
@@ -746,12 +750,12 @@ PackedInt32Array TextServerExtension::font_get_texture_offsets(const RID &p_font
return PackedInt32Array();
}
-Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
- Array ret;
+PackedInt32Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
+ PackedInt32Array ret;
if (GDVIRTUAL_CALL(font_get_glyph_list, p_font_rid, p_size, ret)) {
return ret;
}
- return Array();
+ return PackedInt32Array();
}
void TextServerExtension::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) {
@@ -846,12 +850,12 @@ Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, i
return Dictionary();
}
-Array TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
- Array ret;
+TypedArray<Vector2i> TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
+ TypedArray<Vector2i> ret;
if (GDVIRTUAL_CALL(font_get_kerning_list, p_font_rid, p_size, ret)) {
return ret;
}
- return Array();
+ return TypedArray<Vector2i>();
}
void TextServerExtension::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) {
@@ -1498,6 +1502,14 @@ String TextServerExtension::percent_sign(const String &p_language) const {
return "%";
}
+bool TextServerExtension::is_valid_identifier(const String &p_string) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(is_valid_identifier, p_string, ret)) {
+ return ret;
+ }
+ return TextServer::is_valid_identifier(p_string);
+}
+
String TextServerExtension::strip_diacritics(const String &p_string) const {
String ret;
if (GDVIRTUAL_CALL(strip_diacritics, p_string, ret)) {
@@ -1522,12 +1534,12 @@ String TextServerExtension::string_to_lower(const String &p_string, const String
return p_string;
}
-Array TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- Array ret;
+TypedArray<Vector2i> TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector2i> ret;
if (GDVIRTUAL_CALL(parse_structured_text, p_parser_type, p_args, p_text, ret)) {
return ret;
}
- return Array();
+ return TypedArray<Vector2i>();
}
PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language) const {
@@ -1538,6 +1550,22 @@ PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_str
return PackedInt32Array();
}
+int TextServerExtension::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
+ int ret;
+ if (GDVIRTUAL_CALL(is_confusable, p_string, p_dict, ret)) {
+ return ret;
+ }
+ return TextServer::is_confusable(p_string, p_dict);
+}
+
+bool TextServerExtension::spoof_check(const String &p_string) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(spoof_check, p_string, ret)) {
+ return ret;
+ }
+ return TextServer::spoof_check(p_string);
+}
+
TextServerExtension::TextServerExtension() {
//NOP
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 571753ea67..6a2c199898 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -35,6 +35,7 @@
#include "core/object/script_language.h"
#include "core/os/thread_safe.h"
#include "core/variant/native_ptr.h"
+#include "core/variant/typed_array.h"
#include "servers/text_server.h"
class TextServerExtension : public TextServer {
@@ -107,10 +108,10 @@ public:
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_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override;
+ virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override;
+ GDVIRTUAL2(font_set_antialiasing, RID, TextServer::FontAntialiasing);
+ GDVIRTUAL1RC(TextServer::FontAntialiasing, font_get_antialiasing, 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;
@@ -172,10 +173,10 @@ public:
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 TypedArray<Vector2i> 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);
+ GDVIRTUAL1RC(TypedArray<Vector2i>, font_get_size_cache_list, RID);
GDVIRTUAL1(font_clear_size_cache, RID);
GDVIRTUAL2(font_remove_size_cache, RID, const Vector2i &);
@@ -221,10 +222,10 @@ public:
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 PackedInt32Array 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 &);
+ GDVIRTUAL2RC(PackedInt32Array, font_get_glyph_list, RID, const Vector2i &);
GDVIRTUAL2(font_clear_glyphs, RID, const Vector2i &);
GDVIRTUAL3(font_remove_glyph, RID, const Vector2i &, int64_t);
@@ -262,10 +263,10 @@ public:
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 TypedArray<Vector2i> 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);
+ GDVIRTUAL2RC(TypedArray<Vector2i>, font_get_kerning_list, RID, int64_t);
GDVIRTUAL2(font_clear_kerning_map, RID, int64_t);
GDVIRTUAL3(font_remove_kerning, RID, int64_t, const Vector2i &);
@@ -496,13 +497,21 @@ public:
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 bool is_valid_identifier(const String &p_string) const override;
+ GDVIRTUAL1RC(bool, is_valid_identifier, 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 &);
- 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 &);
+ TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ GDVIRTUAL3RC(TypedArray<Vector2i>, parse_structured_text, StructuredTextParser, const Array &, const String &);
+
+ virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
+ virtual bool spoof_check(const String &p_string) const override;
+ GDVIRTUAL2RC(int, is_confusable, const String &, const PackedStringArray &);
+ GDVIRTUAL1RC(bool, spoof_check, const String &);
TextServerExtension();
~TextServerExtension();
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 4a6b03d943..393160fe9e 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "servers/text_server.h"
+#include "core/variant/typed_array.h"
#include "servers/rendering_server.h"
TextServerManager *TextServerManager::singleton = nullptr;
@@ -103,8 +104,8 @@ Ref<TextServer> TextServerManager::find_interface(const String &p_name) const {
return interfaces[idx];
}
-Array TextServerManager::get_interfaces() const {
- Array ret;
+TypedArray<Dictionary> TextServerManager::get_interfaces() const {
+ TypedArray<Dictionary> ret;
for (int i = 0; i < interfaces.size(); i++) {
Dictionary iface_info;
@@ -222,8 +223,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name);
ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name);
- 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_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing);
+ ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing);
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);
@@ -446,13 +447,28 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("is_confusable", "string", "dict"), &TextServer::is_confusable);
+ ClassDB::bind_method(D_METHOD("spoof_check", "string"), &TextServer::spoof_check);
+
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
+ ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier);
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);
+ /* Font AA */
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE);
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY);
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD);
+
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR);
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
@@ -517,6 +533,7 @@ void TextServer::_bind_methods() {
BIND_BITFIELD_FLAG(GRAPHEME_IS_PUNCTUATION);
BIND_BITFIELD_FLAG(GRAPHEME_IS_UNDERSCORE);
BIND_BITFIELD_FLAG(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL);
/* Hinting */
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -545,6 +562,8 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION);
BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_IDENTIFIERS);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_SECURITY);
/* FT Contour Point Types */
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
@@ -1578,8 +1597,8 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
-Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- Array ret;
+TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector2i> ret;
switch (p_parser_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
@@ -1620,7 +1639,7 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
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.
+ } else if (!local && (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
if (prev != i) {
ret.push_back(Vector2i(prev, i));
}
@@ -1655,8 +1674,8 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
return ret;
}
-Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
- Array ret;
+TypedArray<Dictionary> TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
+ TypedArray<Dictionary> ret;
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
int gl_size = shaped_text_get_glyph_count(p_shaped);
@@ -1680,7 +1699,7 @@ Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
return ret;
}
-Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
+TypedArray<Dictionary> TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
Array ret;
const Glyph *glyphs = shaped_text_sort_logical(p_shaped);
@@ -1705,8 +1724,8 @@ Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
return ret;
}
-Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
- Array ret;
+TypedArray<Dictionary> TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
+ TypedArray<Dictionary> ret;
const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
int gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
@@ -1730,6 +1749,26 @@ Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped)
return ret;
}
+bool TextServer::is_valid_identifier(const String &p_string) const {
+ const char32_t *str = p_string.ptr();
+ int len = p_string.length();
+
+ if (len == 0) {
+ return false; // Empty string.
+ }
+
+ if (!is_unicode_identifier_start(str[0])) {
+ return false;
+ }
+
+ for (int i = 1; i < len; i++) {
+ if (!is_unicode_identifier_continue(str[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
TextServer::TextServer() {
_init_diacritics_map();
}
diff --git a/servers/text_server.h b/servers/text_server.h
index f6ab165bfc..9304771d1b 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -37,6 +37,9 @@
#include "core/variant/native_ptr.h"
#include "core/variant/variant.h"
+template <typename T>
+class TypedArray;
+
struct Glyph;
struct CaretInfo;
@@ -44,6 +47,21 @@ class TextServer : public RefCounted {
GDCLASS(TextServer, RefCounted);
public:
+ enum FontAntialiasing {
+ FONT_ANTIALIASING_NONE,
+ FONT_ANTIALIASING_GRAY,
+ FONT_ANTIALIASING_LCD,
+ };
+
+ enum FontLCDSubpixelLayout {
+ FONT_LCD_SUBPIXEL_LAYOUT_NONE,
+ FONT_LCD_SUBPIXEL_LAYOUT_HRGB,
+ FONT_LCD_SUBPIXEL_LAYOUT_HBGR,
+ FONT_LCD_SUBPIXEL_LAYOUT_VRGB,
+ FONT_LCD_SUBPIXEL_LAYOUT_VBGR,
+ FONT_LCD_SUBPIXEL_LAYOUT_MAX,
+ };
+
enum Direction {
DIRECTION_AUTO,
DIRECTION_LTR,
@@ -116,6 +134,7 @@ public:
GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction).
GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break).
GRAPHEME_IS_CONNECTED = 1 << 10, // Connected to previous grapheme.
+ GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL = 1 << 11, // It is safe to insert a U+0640 before this grapheme for elongation.
};
enum Hinting {
@@ -148,6 +167,8 @@ public:
FEATURE_FONT_VARIABLE = 1 << 10,
FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 11,
FEATURE_USE_SUPPORT_DATA = 1 << 12,
+ FEATURE_UNICODE_IDENTIFIERS = 1 << 13,
+ FEATURE_UNICODE_SECURITY = 1 << 14,
};
enum ContourPointTag {
@@ -227,8 +248,8 @@ public:
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_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_antialiasing(RID p_font_rid, FontAntialiasing p_antialiasing) = 0;
+ virtual FontAntialiasing font_get_antialiasing(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;
@@ -266,7 +287,7 @@ public:
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 Array font_get_size_cache_list(const RID &p_font_rid) const = 0;
+ virtual TypedArray<Vector2i> 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;
@@ -295,7 +316,7 @@ public:
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 Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0;
+ virtual PackedInt32Array 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;
@@ -318,7 +339,7 @@ public:
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0;
- virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0;
+ virtual TypedArray<Vector2i> 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;
@@ -408,9 +429,9 @@ public:
virtual bool shaped_text_is_ready(const 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;
+ TypedArray<Dictionary> _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);
+ TypedArray<Dictionary> _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(const RID &p_shaped) const = 0;
@@ -422,7 +443,7 @@ public:
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;
+ TypedArray<Dictionary> _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(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) = 0;
@@ -463,13 +484,17 @@ public:
// String functions.
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0;
+ virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; };
+ virtual bool spoof_check(const String &p_string) const { return false; };
+
virtual String strip_diacritics(const String &p_string) const;
+ virtual bool is_valid_identifier(const String &p_string) const;
// Other string operations.
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;
+ TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
TextServer();
~TextServer();
@@ -531,7 +556,7 @@ public:
int get_interface_count() const;
Ref<TextServer> get_interface(int p_index) const;
Ref<TextServer> find_interface(const String &p_name) const;
- Array get_interfaces() const;
+ TypedArray<Dictionary> get_interfaces() const;
_FORCE_INLINE_ Ref<TextServer> get_primary_interface() const {
return primary_interface;
@@ -562,6 +587,8 @@ VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
VARIANT_BITFIELD_CAST(TextServer::FontStyle);
VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
+VARIANT_ENUM_CAST(TextServer::FontAntialiasing);
+VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(CaretInfo);
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 990281d96d..e26212ada1 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -226,7 +226,7 @@ Ref<XRInterface> XRServer::find_interface(const String &p_name) const {
return interfaces[idx];
};
-Array XRServer::get_interfaces() const {
+TypedArray<Dictionary> XRServer::get_interfaces() const {
Array ret;
for (int i = 0; i < interfaces.size(); i++) {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 74128bfb54..57e42deccb 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -157,7 +157,7 @@ public:
int get_interface_count() const;
Ref<XRInterface> get_interface(int p_index) const;
Ref<XRInterface> find_interface(const String &p_name) const;
- Array get_interfaces() const;
+ TypedArray<Dictionary> get_interfaces() const;
/*
note, more then one interface can technically be active, especially on mobile, but only one interface is used for