summaryrefslogtreecommitdiffstats
path: root/servers
diff options
context:
space:
mode:
authorSpartan322 <Megacake1234@gmail.com>2024-10-24 18:01:23 -0400
committerSpartan322 <Megacake1234@gmail.com>2024-10-24 18:01:23 -0400
commit3679f5971aa431d37cc2acd5d459ed4b38aad26f (patch)
treecee32a21c68b1d737fc0cbe52b2a0ff649016123 /servers
parenta22fcac9dc8ecca406a3267849954a5a5373dd11 (diff)
parent1015a481ff43edb1126ab39a147fefda290131e5 (diff)
downloadredot-engine-3679f5971aa431d37cc2acd5d459ed4b38aad26f.tar.gz
Merge commit godotengine/godot@1015a481ff43edb1126ab39a147fefda290131e5
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_stream.cpp43
-rw-r--r--servers/audio/audio_stream.h6
-rw-r--r--servers/display_server.cpp4
-rw-r--r--servers/rendering/dummy/storage/light_storage.h2
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp80
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp17
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h3
-rw-r--r--servers/rendering/renderer_scene_cull.cpp13
-rw-r--r--servers/rendering/renderer_scene_cull.h1
-rw-r--r--servers/rendering/rendering_device.cpp4
-rw-r--r--servers/rendering/rendering_device.h2
-rw-r--r--servers/rendering/rendering_device_binds.cpp5
-rw-r--r--servers/rendering/rendering_server_default.cpp2
-rw-r--r--servers/rendering/rendering_server_default.h1
-rw-r--r--servers/rendering/shader_language.cpp129
-rw-r--r--servers/rendering/shader_language.h4
-rw-r--r--servers/rendering/shader_types.cpp2
-rw-r--r--servers/rendering/storage/light_storage.h2
-rw-r--r--servers/rendering_server.cpp1
-rw-r--r--servers/rendering_server.h1
20 files changed, 245 insertions, 77 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 229f6d5b4e..1ddbd01a52 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -78,6 +78,42 @@ int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_fra
return ret;
}
+PackedVector2Array AudioStreamPlayback::_mix_audio_bind(float p_rate_scale, int p_frames) {
+ Vector<AudioFrame> frames = mix_audio(p_rate_scale, p_frames);
+
+ PackedVector2Array res;
+ res.resize(frames.size());
+
+ Vector2 *res_ptrw = res.ptrw();
+ for (int i = 0; i < frames.size(); i++) {
+ res_ptrw[i] = Vector2(frames[i].left, frames[i].right);
+ }
+
+ return res;
+}
+
+Vector<AudioFrame> AudioStreamPlayback::mix_audio(float p_rate_scale, int p_frames) {
+ Vector<AudioFrame> res;
+ res.resize(p_frames);
+
+ int frames = mix(res.ptrw(), p_rate_scale, p_frames);
+ res.resize(frames);
+
+ return res;
+}
+
+void AudioStreamPlayback::start_playback(double p_from_pos) {
+ start(p_from_pos);
+}
+
+void AudioStreamPlayback::stop_playback() {
+ stop();
+}
+
+void AudioStreamPlayback::seek_playback(double p_time) {
+ seek(p_time);
+}
+
void AudioStreamPlayback::tag_used_streams() {
GDVIRTUAL_CALL(_tag_used_streams);
}
@@ -110,6 +146,13 @@ void AudioStreamPlayback::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sample_playback", "playback_sample"), &AudioStreamPlayback::set_sample_playback);
ClassDB::bind_method(D_METHOD("get_sample_playback"), &AudioStreamPlayback::get_sample_playback);
+ ClassDB::bind_method(D_METHOD("mix_audio", "rate_scale", "frames"), &AudioStreamPlayback::_mix_audio_bind);
+ ClassDB::bind_method(D_METHOD("start", "from_pos"), &AudioStreamPlayback::start_playback, DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("seek", "time"), &AudioStreamPlayback::seek_playback, DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayback::stop_playback);
+ ClassDB::bind_method(D_METHOD("get_loop_count"), &AudioStreamPlayback::get_loop_count);
+ ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayback::get_playback_position);
+ ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayback::is_playing);
}
AudioStreamPlayback::AudioStreamPlayback() {}
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 40a566734f..151daf9e8b 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -85,6 +85,7 @@ class AudioStreamPlayback : public RefCounted {
protected:
static void _bind_methods();
+ PackedVector2Array _mix_audio_bind(float p_rate_scale, int p_frames);
GDVIRTUAL1(_start, double)
GDVIRTUAL0(_stop)
GDVIRTUAL0RC(bool, _is_playing)
@@ -120,6 +121,11 @@ public:
AudioStreamPlayback();
~AudioStreamPlayback();
+
+ Vector<AudioFrame> mix_audio(float p_rate_scale, int p_frames);
+ void start_playback(double p_from_pos = 0.0);
+ void stop_playback();
+ void seek_playback(double p_time);
};
class AudioStreamPlaybackResampled : public AudioStreamPlayback {
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index ca073aefbb..b5511acb9e 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -1232,6 +1232,10 @@ void DisplayServer::_input_set_custom_mouse_cursor_func(const Ref<Resource> &p_i
}
bool DisplayServer::can_create_rendering_device() {
+ if (get_singleton()->get_name() == "headless") {
+ return false;
+ }
+
#if defined(RD_ENABLED)
RenderingDevice *device = RenderingDevice::get_singleton();
if (device) {
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index 8a243c5963..7db025190d 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -80,6 +80,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override {}
+ virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override { return 0xFFFFFFFF; }
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 0668f0eb65..10bde96d53 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -624,6 +624,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
bool any_uses_time = false;
+ Vector3 cam_position = p_cam_transform.get_origin();
for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
@@ -654,41 +655,68 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
any_uses_time |= shader_data->uses_time;
- Vector3i min;
- Vector3i max;
+ Vector3i froxel_min;
+ Vector3i froxel_max;
Vector3i kernel_size;
- Vector3 position = fog_volume_instance->transform.get_origin();
+ Vector3 fog_position = fog_volume_instance->transform.get_origin();
RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2;
if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
// Local fog volume.
- Vector3i points[8];
Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);
float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
- points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
-
- min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
- max = Vector3i(1, 1, 1);
-
+ Vector3 corners[8]{
+ fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)),
+ fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z))
+ };
+ Vector3i froxels[8];
+ Vector3 corner_min = corners[0];
+ Vector3 corner_max = corners[0];
for (int j = 0; j < 8; j++) {
- min = min.min(points[j]);
- max = max.max(points[j]);
+ froxels[j] = _point_get_position_in_froxel_volume(corners[j], fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ corner_min = corner_min.min(corners[j]);
+ corner_max = corner_max.max(corners[j]);
+ }
+
+ froxel_min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
+ froxel_max = Vector3i(1, 1, 1);
+
+ // Tracking just the corners of the fog volume can result in missing some fog:
+ // when the camera's near plane is inside the fog, we must always consider the entire screen
+ Vector3 near_plane_corner(frustum_near_size.x, frustum_near_size.y, z_near);
+ float expand = near_plane_corner.length();
+ if (cam_position.x > (corner_min.x - expand) && cam_position.x < (corner_max.x + expand) &&
+ cam_position.y > (corner_min.y - expand) && cam_position.y < (corner_max.y + expand) &&
+ cam_position.z > (corner_min.z - expand) && cam_position.z < (corner_max.z + expand)) {
+ froxel_min.x = 0;
+ froxel_min.y = 0;
+ froxel_min.z = 0;
+ froxel_max.x = int32_t(fog->width);
+ froxel_max.y = int32_t(fog->height);
+ for (int j = 0; j < 8; j++) {
+ froxel_max.z = MAX(froxel_max.z, froxels[j].z);
+ }
+ } else {
+ // Camera is guaranteed to be outside the fog volume
+ for (int j = 0; j < 8; j++) {
+ froxel_min = froxel_min.min(froxels[j]);
+ froxel_max = froxel_max.max(froxels[j]);
+ }
}
- kernel_size = max - min;
+ kernel_size = froxel_max - froxel_min;
} else {
// Volume type global runs on all cells
extents = Vector3(fog->width, fog->height, fog->depth);
- min = Vector3i(0, 0, 0);
+ froxel_min = Vector3i(0, 0, 0);
kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
}
@@ -697,15 +725,15 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
}
VolumetricFogShader::FogPushConstant push_constant;
- push_constant.position[0] = position.x;
- push_constant.position[1] = position.y;
- push_constant.position[2] = position.z;
+ push_constant.position[0] = fog_position.x;
+ push_constant.position[1] = fog_position.y;
+ push_constant.position[2] = fog_position.z;
push_constant.size[0] = extents.x * 2;
push_constant.size[1] = extents.y * 2;
push_constant.size[2] = extents.z * 2;
- push_constant.corner[0] = min.x;
- push_constant.corner[1] = min.y;
- push_constant.corner[2] = min.z;
+ push_constant.corner[0] = froxel_min.x;
+ push_constant.corner[1] = froxel_min.y;
+ push_constant.corner[2] = froxel_min.z;
push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume));
RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform);
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index ecccbae939..059b28b9b3 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -287,6 +287,23 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
+void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL(light);
+
+ light->shadow_caster_mask = p_caster_mask;
+
+ light->version++;
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
+}
+
+uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL_V(light, 0);
+
+ return light->shadow_caster_mask;
+}
+
void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 025b51b752..e05543be68 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -74,6 +74,7 @@ private:
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
uint32_t max_sdfgi_cascade = 2;
uint32_t cull_mask = 0xFFFFFFFF;
+ uint32_t shadow_caster_mask = 0xFFFFFFFF;
bool distance_fade = false;
real_t distance_fade_begin = 40.0;
real_t distance_fade_shadow = 50.0;
@@ -482,6 +483,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
+ virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 3f385888b2..66ba76fc00 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -2301,6 +2301,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
cull.shadow_count = p_shadow_index + 1;
cull.shadows[p_shadow_index].cascade_count = splits;
cull.shadows[p_shadow_index].light_instance = light->instance;
+ cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base);
for (int i = 0; i < splits; i++) {
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
@@ -2531,7 +2532,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
+ if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2613,7 +2614,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
+ if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2680,7 +2681,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
+ if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -3038,6 +3039,10 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
for (const Instance *E : geom->lights) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
+ if (!(RSG::light_storage->light_get_cull_mask(E->base) & idata.layer_mask)) {
+ continue;
+ }
+
instance_pair_buffer[idx++] = light->instance;
if (idx == MAX_INSTANCE_PAIRS) {
break;
@@ -3142,7 +3147,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
- if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) {
+ if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) {
cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
mesh_visible = true;
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index b719698eea..a6a099c19a 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -1123,6 +1123,7 @@ public:
struct Cull {
struct Shadow {
RID light_instance;
+ uint32_t caster_mask;
struct Cascade {
Frustum frustum;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 1d01bb8b30..f2aa28c0b7 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -7262,6 +7262,10 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_PASS);
}
+void RenderingDevice::make_current() {
+ render_thread_id = Thread::get_caller_id();
+}
+
RenderingDevice::~RenderingDevice() {
finalize();
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 3d6a8fc4a8..9eeddab6e9 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1498,6 +1498,8 @@ public:
static RenderingDevice *get_singleton();
+ void make_current();
+
RenderingDevice();
~RenderingDevice();
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index 06a4d8737a..4389e76515 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -33,7 +33,10 @@
#include "rendering_device_binds.h"
Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) {
- ERR_FAIL_NULL_V(RenderingDevice::get_singleton(), ERR_UNAVAILABLE);
+ ERR_FAIL_NULL_V_MSG(
+ RenderingDevice::get_singleton(),
+ ERR_UNAVAILABLE,
+ "Cannot import custom .glsl shaders when running without a RenderingDevice. This can happen if you are using the headless more or the Compatibility backend.");
Vector<String> lines = p_text.split("\n");
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 2eec36e9c9..d47cb8d676 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -372,6 +372,8 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const {
void RenderingServerDefault::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
server_thread = Thread::get_caller_id();
server_task_id = p_pump_task_id;
+ // This is needed because the main RD is created on the main thread.
+ RenderingDevice::get_singleton()->make_current();
}
void RenderingServerDefault::_thread_exit() {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 0bd5b2bb97..35c86c977e 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -445,6 +445,7 @@ public:
FUNC2(light_set_cull_mask, RID, uint32_t)
FUNC5(light_set_distance_fade, RID, bool, float, float, float)
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
+ FUNC2(light_set_shadow_caster_mask, RID, uint32_t)
FUNC2(light_set_bake_mode, RID, LightBakeMode)
FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 94d3ddb4aa..517fd898e0 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -358,7 +358,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_CF_BREAK, "break", CF_BLOCK, {}, {} },
{ TK_CF_CONTINUE, "continue", CF_BLOCK, {}, {} },
{ TK_CF_RETURN, "return", CF_BLOCK, {}, {} },
- { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "fragment" } },
+ { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "vertex" } },
// function specifier keywords
@@ -3567,28 +3567,33 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
int argcount = args.size();
- if (p_function_info.stage_functions.has(name)) {
- //stage based function
- const StageFunctionInfo &sf = p_function_info.stage_functions[name];
- if (argcount != sf.arguments.size()) {
- _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size()));
- return false;
- }
- //validate arguments
- for (int i = 0; i < argcount; i++) {
- if (args[i] != sf.arguments[i].type) {
- _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type)));
- return false;
- }
- }
+ if (stages) {
+ // Stage functions can be used in custom functions as well, that why need to check them all.
+ for (const KeyValue<StringName, FunctionInfo> &E : *stages) {
+ if (E.value.stage_functions.has(name)) {
+ // Stage-based function.
+ const StageFunctionInfo &sf = E.value.stage_functions[name];
+ if (argcount != sf.arguments.size()) {
+ _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size()));
+ return false;
+ }
+ // Validate arguments.
+ for (int i = 0; i < argcount; i++) {
+ if (args[i] != sf.arguments[i].type) {
+ _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type)));
+ return false;
+ }
+ }
- if (r_ret_type) {
- *r_ret_type = sf.return_type;
- }
- if (r_ret_type_str) {
- *r_ret_type_str = "";
+ if (r_ret_type) {
+ *r_ret_type = sf.return_type;
+ }
+ if (r_ret_type_str) {
+ *r_ret_type_str = "";
+ }
+ return true;
+ }
}
- return true;
}
bool failed_builtin = false;
@@ -5939,22 +5944,35 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
calls_info[current_function].calls.push_back(&calls_info[name]);
}
- int idx = 0;
bool is_builtin = false;
- while (frag_only_func_defs[idx].name) {
- if (frag_only_func_defs[idx].name == name) {
- // If a built-in function not found for the current shader type, then it shouldn't be parsed further.
- if (!is_supported_frag_only_funcs) {
- _set_error(vformat(RTR("Built-in function '%s' is not supported for the '%s' shader type."), name, shader_type_identifier));
- return nullptr;
+ if (is_supported_frag_only_funcs && stages) {
+ for (const KeyValue<StringName, FunctionInfo> &E : *stages) {
+ if (E.value.stage_functions.has(name)) {
+ // Register usage of the restricted stage function.
+ calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos())));
+ is_builtin = true;
+ break;
}
- // Register usage of the restricted function.
- calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos())));
- is_builtin = true;
- break;
}
- idx++;
+ }
+
+ if (!is_builtin) {
+ int idx = 0;
+ while (frag_only_func_defs[idx].name) {
+ if (frag_only_func_defs[idx].name == name) {
+ // If a built-in function not found for the current shader type, then it shouldn't be parsed further.
+ if (!is_supported_frag_only_funcs) {
+ _set_error(vformat(RTR("Built-in function '%s' is not supported for the '%s' shader type."), name, shader_type_identifier));
+ return nullptr;
+ }
+ // Register usage of the restricted function.
+ calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos())));
+ is_builtin = true;
+ break;
+ }
+ idx++;
+ }
}
// Recursively checks for the restricted function call.
@@ -8583,6 +8601,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
block = block->parent_block;
}
} else if (tk.type == TK_CF_DISCARD) {
+ if (!is_discard_supported) {
+ _set_error(vformat(RTR("Use of '%s' is not supported for the '%s' shader type."), "discard", shader_type_identifier));
+ return ERR_PARSE_ERROR;
+ }
+
//check return type
BlockNode *b = p_block;
while (b && !b->parent_function) {
@@ -8594,7 +8617,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (!b->parent_function->can_discard) {
- _set_error(vformat(RTR("Use of '%s' is not allowed here."), "discard"));
+ _set_error(vformat(RTR("'%s' cannot be used within the '%s' processor function."), "discard", b->parent_function->name));
return ERR_PARSE_ERROR;
}
@@ -8603,6 +8626,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
+
+ calls_info[b->parent_function->name].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>("discard", CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, pos)));
+
if (tk.type != TK_SEMICOLON) {
_set_expected_after_error(";", "discard");
return ERR_PARSE_ERROR;
@@ -8840,7 +8866,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions;
- is_supported_frag_only_funcs = shader_type_identifier == "canvas_item" || shader_type_identifier == "spatial" || shader_type_identifier == "sky";
+
+ is_discard_supported = shader_type_identifier == "canvas_item" || shader_type_identifier == "spatial";
+ is_supported_frag_only_funcs = is_discard_supported || shader_type_identifier == "sky";
const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
@@ -10334,6 +10362,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
+ } else {
+ func_node->can_discard = is_discard_supported; // Allow use it for custom functions (in supported shader types).
}
if (!function_overload_count.has(name)) {
@@ -10924,10 +10954,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
break; // Ignore hint keywords (parsed below).
}
if (keyword_list[i].flags & keyword_completion_context) {
- if (keyword_list[i].excluded_shader_types.has(shader_type_identifier)) {
- continue;
- }
- if (!keyword_list[i].functions.is_empty() && !keyword_list[i].functions.has(current_function)) {
+ if (keyword_list[i].excluded_shader_types.has(shader_type_identifier) || keyword_list[i].excluded_functions.has(current_function)) {
continue;
}
ScriptLanguage::CodeCompletionOption option(keyword_list[i].text, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
@@ -11162,9 +11189,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
int idx = 0;
bool low_end = RenderingServer::get_singleton()->is_low_end();
- if (stages && stages->has(skip_function)) {
- for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) {
- matches.insert(String(E.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ if (stages) {
+ // Stage functions can be used in custom functions as well, that why need to check them all.
+ for (const KeyValue<StringName, FunctionInfo> &E : *stages) {
+ for (const KeyValue<StringName, StageFunctionInfo> &F : E.value.stage_functions) {
+ if (F.value.skip_function == skip_function && stages->has(skip_function)) {
+ continue;
+ }
+ matches.insert(String(F.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ }
}
}
@@ -11294,9 +11327,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
return OK;
}
- if (stages && stages->has(block_function)) {
- for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[block_function].stage_functions) {
- if (completion_function == E.key) {
+ if (stages) {
+ // Stage functions can be used in custom functions as well, that why need to check them all.
+ for (const KeyValue<StringName, FunctionInfo> &S : *stages) {
+ for (const KeyValue<StringName, StageFunctionInfo> &E : S.value.stage_functions) {
+ // No need to check for the skip function here.
+ if (completion_function != E.key) {
+ continue;
+ }
+
calltip += get_datatype_name(E.value.return_type);
calltip += " ";
calltip += E.key;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 9e65020bb8..f37a37e0bf 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -861,6 +861,7 @@ public:
Vector<Argument> arguments;
DataType return_type = TYPE_VOID;
+ String skip_function;
};
struct ModeInfo {
@@ -936,7 +937,7 @@ private:
const char *text;
uint32_t flags;
const Vector<String> excluded_shader_types;
- const Vector<String> functions;
+ const Vector<String> excluded_functions;
};
static const KeyWord keyword_list[];
@@ -1152,6 +1153,7 @@ private:
const HashMap<StringName, FunctionInfo> *stages = nullptr;
bool is_supported_frag_only_funcs = false;
+ bool is_discard_supported = false;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 6c27ce9622..70a7bdfb08 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -286,6 +286,7 @@ ShaderTypes::ShaderTypes() {
{
ShaderLanguage::StageFunctionInfo func;
+ func.skip_function = "vertex";
func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("sdf_pos", ShaderLanguage::TYPE_VEC2));
func.return_type = ShaderLanguage::TYPE_FLOAT; //whether it could emit
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf"] = func;
@@ -299,6 +300,7 @@ ShaderTypes::ShaderTypes() {
{
ShaderLanguage::StageFunctionInfo func;
+ func.skip_function = "vertex";
func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("uv", ShaderLanguage::TYPE_VEC2));
func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["screen_uv_to_sdf"] = func;
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 3c7955c7c7..69f47e2814 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -61,6 +61,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0;
+ virtual uint32_t light_get_shadow_caster_mask(RID p_light) const = 0;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index daffea5e93..59bf16d315 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2481,6 +2481,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask);
ClassDB::bind_method(D_METHOD("light_set_distance_fade", "decal", "enabled", "begin", "shadow", "length"), &RenderingServer::light_set_distance_fade);
ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode);
+ ClassDB::bind_method(D_METHOD("light_set_shadow_caster_mask", "light", "mask"), &RenderingServer::light_set_shadow_caster_mask);
ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode);
ClassDB::bind_method(D_METHOD("light_set_max_sdfgi_cascade", "light", "cascade"), &RenderingServer::light_set_max_sdfgi_cascade);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 2b84d8f2c7..291c535de0 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -544,6 +544,7 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0;
enum LightBakeMode {
LIGHT_BAKE_DISABLED,