summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_driver_dummy.h2
-rw-r--r--servers/audio/audio_effect.h6
-rw-r--r--servers/audio/audio_stream.cpp96
-rw-r--r--servers/audio/audio_stream.h43
-rw-r--r--servers/audio/effects/audio_effect_amplify.h6
-rw-r--r--servers/audio/effects/audio_effect_chorus.h6
-rw-r--r--servers/audio/effects/audio_effect_compressor.h6
-rw-r--r--servers/audio/effects/audio_effect_delay.h6
-rw-r--r--servers/audio/effects/audio_effect_distortion.h6
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp1
-rw-r--r--servers/audio/effects/audio_effect_eq.h8
-rw-r--r--servers/audio/effects/audio_effect_filter.h6
-rw-r--r--servers/audio/effects/audio_effect_panner.h6
-rw-r--r--servers/audio/effects/audio_effect_record.h6
-rw-r--r--servers/audio/effects/audio_effect_reverb.h8
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp6
-rw-r--r--servers/audio/effects/audio_stream_generator.h5
-rw-r--r--servers/audio/effects/eq_filter.cpp (renamed from servers/audio/effects/eq.cpp)6
-rw-r--r--servers/audio/effects/eq_filter.h (renamed from servers/audio/effects/eq.h)2
-rw-r--r--servers/audio/effects/reverb_filter.cpp (renamed from servers/audio/effects/reverb.cpp)4
-rw-r--r--servers/audio/effects/reverb_filter.h (renamed from servers/audio/effects/reverb.h)8
-rw-r--r--servers/audio_server.cpp14
-rw-r--r--servers/audio_server.h5
-rw-r--r--servers/debugger/servers_debugger.h4
-rw-r--r--servers/extensions/physics_server_3d_extension.h2
-rw-r--r--servers/movie_writer/movie_writer.cpp41
-rw-r--r--servers/movie_writer/movie_writer.h2
-rw-r--r--servers/physics_2d/godot_step_2d.cpp9
-rw-r--r--servers/physics_2d/godot_step_2d.h4
-rw-r--r--servers/physics_3d/gjk_epa.h2
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.h6
-rw-r--r--servers/physics_3d/godot_step_3d.cpp9
-rw-r--r--servers/physics_3d/godot_step_3d.h4
-rw-r--r--servers/rendering/dummy/environment/fog.h2
-rw-r--r--servers/rendering/dummy/environment/gi.h2
-rw-r--r--servers/rendering/dummy/rasterizer_canvas_dummy.h2
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h39
-rw-r--r--servers/rendering/dummy/storage/light_storage.h2
-rw-r--r--servers/rendering/dummy/storage/material_storage.h4
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h2
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h2
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h2
-rw-r--r--servers/rendering/dummy/storage/utilities.h2
-rw-r--r--servers/rendering/environment/renderer_fog.h2
-rw-r--r--servers/rendering/environment/renderer_gi.h2
-rw-r--r--servers/rendering/renderer_canvas_cull.h6
-rw-r--r--servers/rendering/renderer_canvas_render.h8
-rw-r--r--servers/rendering/renderer_compositor.cpp7
-rw-r--r--servers/rendering/renderer_compositor.h6
-rw-r--r--servers/rendering/renderer_geometry_instance.cpp138
-rw-r--r--servers/rendering/renderer_geometry_instance.h150
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h8
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h2
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp106
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h36
-rw-r--r--servers/rendering/renderer_rd/effects/resolve.h2
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp1715
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h508
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h2
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp1245
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h390
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp1076
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h248
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp32
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h26
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp (renamed from servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp)159
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h (renamed from servers/rendering/renderer_rd/renderer_scene_sky_rd.h)33
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp282
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h122
-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.h8
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp293
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h109
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp21
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h9
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp31
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h7
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h8
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1492
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h334
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl)38
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl)20
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl28
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl)48
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl112
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl (renamed from servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_blur.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_interleave.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_blur.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_interleave.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/gi.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl (renamed from servers/rendering/renderer_rd/shaders/sky.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl (renamed from servers/rendering/renderer_rd/shaders/volumetric_fog.glsl)4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl (renamed from servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl)4
-rw-r--r--servers/rendering/renderer_rd/shaders/specular_merge.glsl53
-rw-r--r--servers/rendering/renderer_rd/shaders/taa_resolve.glsl2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp283
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h9
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.h2
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.h6
-rw-r--r--servers/rendering/renderer_scene.h6
-rw-r--r--servers/rendering/renderer_scene_cull.cpp136
-rw-r--r--servers/rendering/renderer_scene_cull.h28
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h9
-rw-r--r--servers/rendering/renderer_scene_render.cpp41
-rw-r--r--servers/rendering/renderer_scene_render.h65
-rw-r--r--servers/rendering/renderer_thread_pool.cpp42
-rw-r--r--servers/rendering/renderer_thread_pool.h45
-rw-r--r--servers/rendering/renderer_viewport.cpp2
-rw-r--r--servers/rendering/renderer_viewport.h37
-rw-r--r--servers/rendering/rendering_server_default.h3
-rw-r--r--servers/rendering/shader_compiler.cpp70
-rw-r--r--servers/rendering/shader_language.cpp416
-rw-r--r--servers/rendering/shader_language.h18
-rw-r--r--servers/rendering/shader_preprocessor.cpp1048
-rw-r--r--servers/rendering/shader_preprocessor.h200
-rw-r--r--servers/rendering/shader_types.h6
-rw-r--r--servers/rendering/shader_warnings.h6
-rw-r--r--servers/rendering/storage/light_storage.h2
-rw-r--r--servers/rendering/storage/material_storage.h3
-rw-r--r--servers/rendering/storage/mesh_storage.h2
-rw-r--r--servers/rendering/storage/particles_storage.h2
-rw-r--r--servers/rendering/storage/texture_storage.h2
-rw-r--r--servers/rendering/storage/utilities.h2
-rw-r--r--servers/rendering_server.cpp4
-rw-r--r--servers/rendering_server.h5
-rw-r--r--servers/server_wrap_mt_common.h5
-rw-r--r--servers/xr/xr_interface.cpp2
-rw-r--r--servers/xr/xr_interface.h4
-rw-r--r--servers/xr/xr_interface_extension.cpp8
-rw-r--r--servers/xr/xr_interface_extension.h4
-rw-r--r--servers/xr/xr_pose.h2
-rw-r--r--servers/xr_server.cpp10
-rw-r--r--servers/xr_server.h11
149 files changed, 7169 insertions, 4789 deletions
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 232a8d5e1f..8f47e64d8b 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -85,4 +85,4 @@ public:
~AudioDriverDummy() {}
};
-#endif
+#endif // AUDIO_DRIVER_DUMMY_H
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 3a0578679d..653d04595e 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECT_H
-#define AUDIOEFFECT_H
+#ifndef AUDIO_EFFECT_H
+#define AUDIO_EFFECT_H
#include "core/io/resource.h"
#include "core/math/audio_frame.h"
@@ -62,4 +62,4 @@ public:
AudioEffect();
};
-#endif // AUDIOEFFECT_H
+#endif // AUDIO_EFFECT_H
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 0408db2539..80485845c9 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -83,6 +83,10 @@ int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_fra
return 0;
}
+void AudioStreamPlayback::tag_used_streams() {
+ GDVIRTUAL_CALL(_tag_used_streams);
+}
+
void AudioStreamPlayback::_bind_methods() {
GDVIRTUAL_BIND(_start, "from_pos")
GDVIRTUAL_BIND(_stop)
@@ -91,6 +95,7 @@ void AudioStreamPlayback::_bind_methods() {
GDVIRTUAL_BIND(_get_playback_position)
GDVIRTUAL_BIND(_seek, "position")
GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames");
+ GDVIRTUAL_BIND(_tag_used_streams);
}
//////////////////////////////
@@ -187,9 +192,9 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
////////////////////////////////
-Ref<AudioStreamPlayback> AudioStream::instance_playback() {
+Ref<AudioStreamPlayback> AudioStream::instantiate_playback() {
Ref<AudioStreamPlayback> ret;
- if (GDVIRTUAL_CALL(_instance_playback, ret)) {
+ if (GDVIRTUAL_CALL(_instantiate_playback, ret)) {
return ret;
}
ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!");
@@ -218,19 +223,74 @@ bool AudioStream::is_monophonic() const {
return true;
}
+double AudioStream::get_bpm() const {
+ double ret = 0;
+ if (GDVIRTUAL_CALL(_get_bpm, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+bool AudioStream::has_loop() const {
+ bool ret = 0;
+ if (GDVIRTUAL_CALL(_has_loop, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int AudioStream::get_bar_beats() const {
+ int ret = 0;
+ if (GDVIRTUAL_CALL(_get_bar_beats, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int AudioStream::get_beat_count() const {
+ int ret = 0;
+ if (GDVIRTUAL_CALL(_get_beat_count, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void AudioStream::tag_used(float p_offset) {
+ if (tagged_frame != AudioServer::get_singleton()->get_mixed_frames()) {
+ offset_count = 0;
+ tagged_frame = AudioServer::get_singleton()->get_mixed_frames();
+ }
+ if (offset_count < MAX_TAGGED_OFFSETS) {
+ tagged_offsets[offset_count++] = p_offset;
+ }
+}
+
+uint64_t AudioStream::get_tagged_frame() const {
+ return tagged_frame;
+}
+uint32_t AudioStream::get_tagged_frame_count() const {
+ return offset_count;
+}
+float AudioStream::get_tagged_frame_offset(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, MAX_TAGGED_OFFSETS, 0);
+ return tagged_offsets[p_index];
+}
+
void AudioStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length);
ClassDB::bind_method(D_METHOD("is_monophonic"), &AudioStream::is_monophonic);
- ClassDB::bind_method(D_METHOD("instance_playback"), &AudioStream::instance_playback);
- GDVIRTUAL_BIND(_instance_playback);
+ ClassDB::bind_method(D_METHOD("instantiate_playback"), &AudioStream::instantiate_playback);
+ GDVIRTUAL_BIND(_instantiate_playback);
GDVIRTUAL_BIND(_get_stream_name);
GDVIRTUAL_BIND(_get_length);
GDVIRTUAL_BIND(_is_monophonic);
+ GDVIRTUAL_BIND(_get_bpm)
+ GDVIRTUAL_BIND(_get_beat_count)
}
////////////////////////////////
-Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamMicrophone::instantiate_playback() {
Ref<AudioStreamPlaybackMicrophone> playback;
playback.instantiate();
@@ -363,6 +423,10 @@ void AudioStreamPlaybackMicrophone::seek(float p_time) {
// Can't seek a microphone input
}
+void AudioStreamPlaybackMicrophone::tag_used_streams() {
+ microphone->tag_used(0);
+}
+
AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() {
microphone->playbacks.erase(this);
stop();
@@ -490,7 +554,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() {
for (PoolEntry &entry : local_pool) {
cumulative_weight += entry.weight;
if (cumulative_weight > chosen_cumulative_weight) {
- playback->playback = entry.stream->instance_playback();
+ playback->playback = entry.stream->instantiate_playback();
last_playback = entry.stream;
break;
}
@@ -498,7 +562,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() {
if (playback->playback.is_null()) {
// This indicates a floating point error. Take the last element.
last_playback = local_pool[local_pool.size() - 1].stream;
- playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback();
+ playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback();
}
return playback;
}
@@ -532,14 +596,14 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_no_repeats() {
cumulative_weight += entry.weight;
if (cumulative_weight > chosen_cumulative_weight) {
last_playback = entry.stream;
- playback->playback = entry.stream->instance_playback();
+ playback->playback = entry.stream->instantiate_playback();
break;
}
}
if (playback->playback.is_null()) {
// This indicates a floating point error. Take the last element.
last_playback = local_pool[local_pool.size() - 1].stream;
- playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback();
+ playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback();
}
return playback;
}
@@ -568,7 +632,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
for (Ref<AudioStream> &entry : local_pool) {
if (found_last_stream) {
last_playback = entry;
- playback->playback = entry->instance_playback();
+ playback->playback = entry->instantiate_playback();
break;
}
if (entry == last_playback) {
@@ -578,12 +642,12 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
if (playback->playback.is_null()) {
// Wrap around
last_playback = local_pool[0];
- playback->playback = local_pool.write[0]->instance_playback();
+ playback->playback = local_pool.write[0]->instantiate_playback();
}
return playback;
}
-Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamRandomizer::instantiate_playback() {
switch (playback_mode) {
case PLAYBACK_RANDOM:
return instance_playback_random();
@@ -762,6 +826,14 @@ void AudioStreamPlaybackRandomizer::seek(float p_time) {
}
}
+void AudioStreamPlaybackRandomizer::tag_used_streams() {
+ Ref<AudioStreamPlayback> p = playing; // Thread safety
+ if (p.is_valid()) {
+ p->tag_used_streams();
+ }
+ randomizer->tag_used(0);
+}
+
int AudioStreamPlaybackRandomizer::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (playing.is_valid()) {
return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index bf200e7ecf..7c4577977d 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -40,6 +40,8 @@
#include "core/object/script_language.h"
#include "core/variant/native_ptr.h"
+class AudioStream;
+
class AudioStreamPlayback : public RefCounted {
GDCLASS(AudioStreamPlayback, RefCounted);
@@ -52,6 +54,7 @@ protected:
GDVIRTUAL0RC(float, _get_playback_position)
GDVIRTUAL1(_seek, float)
GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int)
+ GDVIRTUAL0(_tag_used_streams)
public:
virtual void start(float p_from_pos = 0.0);
virtual void stop();
@@ -62,6 +65,8 @@ public:
virtual float get_playback_position() const;
virtual void seek(float p_time);
+ virtual void tag_used_streams();
+
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
};
@@ -72,7 +77,7 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
FP_BITS = 16, //fixed point used for resampling
FP_LEN = (1 << FP_BITS),
FP_MASK = FP_LEN - 1,
- INTERNAL_BUFFER_LEN = 256,
+ INTERNAL_BUFFER_LEN = 128, // 128 warrants 3ms positional jitter at much at 44100hz
CUBIC_INTERP_HISTORY = 4
};
@@ -101,20 +106,42 @@ class AudioStream : public Resource {
GDCLASS(AudioStream, Resource);
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
+ enum {
+ MAX_TAGGED_OFFSETS = 8
+ };
+
+ uint64_t tagged_frame = 0;
+ uint64_t offset_count = 0;
+ float tagged_offsets[MAX_TAGGED_OFFSETS];
+
protected:
static void _bind_methods();
- GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instance_playback)
+ GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instantiate_playback)
GDVIRTUAL0RC(String, _get_stream_name)
GDVIRTUAL0RC(float, _get_length)
GDVIRTUAL0RC(bool, _is_monophonic)
+ GDVIRTUAL0RC(double, _get_bpm)
+ GDVIRTUAL0RC(bool, _has_loop)
+ GDVIRTUAL0RC(int, _get_bar_beats)
+ GDVIRTUAL0RC(int, _get_beat_count)
public:
- virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual Ref<AudioStreamPlayback> instantiate_playback();
virtual String get_stream_name() const;
+ virtual double get_bpm() const;
+ virtual bool has_loop() const;
+ virtual int get_bar_beats() const;
+ virtual int get_beat_count() const;
+
virtual float get_length() const;
virtual bool is_monophonic() const;
+
+ void tag_used(float p_offset);
+ uint64_t get_tagged_frame() const;
+ uint32_t get_tagged_frame_count() const;
+ float get_tagged_frame_offset(int p_index) const;
};
// Microphone
@@ -131,7 +158,7 @@ protected:
static void _bind_methods();
public:
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
virtual float get_length() const override; //if supported, otherwise return 0
@@ -153,6 +180,7 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
protected:
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
virtual float get_stream_sampling_rate() override;
+ virtual float get_playback_position() const override;
public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
@@ -163,9 +191,10 @@ public:
virtual int get_loop_count() const override; //times it looped
- virtual float get_playback_position() const override;
virtual void seek(float p_time) override;
+ virtual void tag_used_streams() override;
+
~AudioStreamPlaybackMicrophone();
AudioStreamPlaybackMicrophone();
};
@@ -233,7 +262,7 @@ public:
void set_playback_mode(PlaybackMode p_playback_mode);
PlaybackMode get_playback_mode() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
virtual float get_length() const override; //if supported, otherwise return 0
@@ -265,6 +294,8 @@ public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
+ virtual void tag_used_streams() override;
+
~AudioStreamPlaybackRandomizer();
};
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
index bd0fcaa94d..fd424cbe9a 100644
--- a/servers/audio/effects/audio_effect_amplify.h
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTAMPLIFY_H
-#define AUDIOEFFECTAMPLIFY_H
+#ifndef AUDIO_EFFECT_AMPLIFY_H
+#define AUDIO_EFFECT_AMPLIFY_H
#include "servers/audio/audio_effect.h"
@@ -63,4 +63,4 @@ public:
AudioEffectAmplify();
};
-#endif // AUDIOEFFECTAMPLIFY_H
+#endif // AUDIO_EFFECT_AMPLIFY_H
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index 19035222c5..72b495f7f9 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTCHORUS_H
-#define AUDIOEFFECTCHORUS_H
+#ifndef AUDIO_EFFECT_CHORUS_H
+#define AUDIO_EFFECT_CHORUS_H
#include "servers/audio/audio_effect.h"
@@ -133,4 +133,4 @@ public:
AudioEffectChorus();
};
-#endif // AUDIOEFFECTCHORUS_H
+#endif // AUDIO_EFFECT_CHORUS_H
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index 53c448e5db..998bd3c978 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTCOMPRESSOR_H
-#define AUDIOEFFECTCOMPRESSOR_H
+#ifndef AUDIO_EFFECT_COMPRESSOR_H
+#define AUDIO_EFFECT_COMPRESSOR_H
#include "servers/audio/audio_effect.h"
@@ -91,4 +91,4 @@ public:
AudioEffectCompressor();
};
-#endif // AUDIOEFFECTCOMPRESSOR_H
+#endif // AUDIO_EFFECT_COMPRESSOR_H
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
index 5cc6d72c99..137a4e7dbe 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTDELAY_H
-#define AUDIOEFFECTDELAY_H
+#ifndef AUDIO_EFFECT_DELAY_H
+#define AUDIO_EFFECT_DELAY_H
#include "servers/audio/audio_effect.h"
@@ -131,4 +131,4 @@ public:
AudioEffectDelay();
};
-#endif // AUDIOEFFECTDELAY_H
+#endif // AUDIO_EFFECT_DELAY_H
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
index 487babbdda..c845a0e53c 100644
--- a/servers/audio/effects/audio_effect_distortion.h
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTDISTORTION_H
-#define AUDIOEFFECTDISTORTION_H
+#ifndef AUDIO_EFFECT_DISTORTION_H
+#define AUDIO_EFFECT_DISTORTION_H
#include "servers/audio/audio_effect.h"
@@ -90,4 +90,4 @@ public:
VARIANT_ENUM_CAST(AudioEffectDistortion::Mode)
-#endif // AUDIOEFFECTDISTORTION_H
+#endif // AUDIO_EFFECT_DISTORTION_H
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index b7c373479a..500abd3a6f 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_effect_eq.h"
+
#include "servers/audio_server.h"
void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index 9b0560223f..b80fb7c73c 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTEQ_H
-#define AUDIOEFFECTEQ_H
+#ifndef AUDIO_EFFECT_EQ_H
+#define AUDIO_EFFECT_EQ_H
#include "servers/audio/audio_effect.h"
-#include "servers/audio/effects/eq.h"
+#include "servers/audio/effects/eq_filter.h"
class AudioEffectEQ;
@@ -98,4 +98,4 @@ public:
AudioEffectEQ(EQ::PRESET_21_BANDS) {}
};
-#endif // AUDIOEFFECTEQ_H
+#endif // AUDIO_EFFECT_EQ_H
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index d5d58ddaa3..a40af2f13c 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTFILTER_H
-#define AUDIOEFFECTFILTER_H
+#ifndef AUDIO_EFFECT_FILTER_H
+#define AUDIO_EFFECT_FILTER_H
#include "servers/audio/audio_effect.h"
#include "servers/audio/audio_filter_sw.h"
@@ -167,4 +167,4 @@ public:
AudioEffectFilter(AudioFilterSW::HIGHSHELF) {}
};
-#endif // AUDIOEFFECTFILTER_H
+#endif // AUDIO_EFFECT_FILTER_H
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
index d05c9902af..3eca71a926 100644
--- a/servers/audio/effects/audio_effect_panner.h
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTPANNER_H
-#define AUDIOEFFECTPANNER_H
+#ifndef AUDIO_EFFECT_PANNER_H
+#define AUDIO_EFFECT_PANNER_H
#include "servers/audio/audio_effect.h"
@@ -61,4 +61,4 @@ public:
AudioEffectPanner();
};
-#endif // AUDIOEFFECTPANNER_H
+#endif // AUDIO_EFFECT_PANNER_H
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 8a6247e27a..b23b63dbd8 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTRECORD_H
-#define AUDIOEFFECTRECORD_H
+#ifndef AUDIO_EFFECT_RECORD_H
+#define AUDIO_EFFECT_RECORD_H
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
@@ -103,4 +103,4 @@ public:
AudioEffectRecord();
};
-#endif // AUDIOEFFECTRECORD_H
+#endif // AUDIO_EFFECT_RECORD_H
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index 90694c5492..a2c1fc5ea5 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTREVERB_H
-#define AUDIOEFFECTREVERB_H
+#ifndef AUDIO_EFFECT_REVERB_H
+#define AUDIO_EFFECT_REVERB_H
#include "servers/audio/audio_effect.h"
-#include "servers/audio/effects/reverb.h"
+#include "servers/audio/effects/reverb_filter.h"
class AudioEffectReverb;
@@ -94,4 +94,4 @@ public:
AudioEffectReverb();
};
-#endif // AUDIOEFFECTREVERB_H
+#endif // AUDIO_EFFECT_REVERB_H
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index 46de1692e4..6365dacc80 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -46,7 +46,7 @@ float AudioStreamGenerator::get_buffer_length() const {
return buffer_len;
}
-Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamGenerator::instantiate_playback() {
Ref<AudioStreamGeneratorPlayback> playback;
playback.instantiate();
playback->generator = this;
@@ -196,6 +196,10 @@ void AudioStreamGeneratorPlayback::seek(float p_time) {
//no seek possible
}
+void AudioStreamGeneratorPlayback::tag_used_streams() {
+ generator->tag_used(0);
+}
+
void AudioStreamGeneratorPlayback::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame);
ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer);
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 2ce4b95fcf..a0bed0fda5 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -50,7 +50,7 @@ public:
void set_buffer_length(float p_seconds);
float get_buffer_length() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
virtual float get_length() const override;
@@ -89,8 +89,11 @@ public:
int get_frames_available() const;
int get_skips() const;
+ virtual void tag_used_streams() override;
+
void clear_buffer();
AudioStreamGeneratorPlayback();
};
+
#endif // AUDIO_STREAM_GENERATOR_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq_filter.cpp
index 2123284b3b..6807e81cc4 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq_filter.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* eq.cpp */
+/* eq_filter.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Author: reduzio@gmail.com (C) 2006
+#include "eq_filter.h"
-#include "eq.h"
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
+
#include <math.h>
#define POW2(v) ((v) * (v))
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq_filter.h
index d6293bf875..9dcad4dcea 100644
--- a/servers/audio/effects/eq.h
+++ b/servers/audio/effects/eq_filter.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* eq.h */
+/* eq_filter.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb_filter.cpp
index adfd648514..0363706714 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb_filter.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* reverb.cpp */
+/* reverb_filter.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "reverb.h"
+#include "reverb_filter.h"
#include "core/math/math_funcs.h"
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb_filter.h
index c9602c5b5a..fe846fe2e7 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb_filter.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* reverb.h */
+/* reverb_filter.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REVERB_H
-#define REVERB_H
+#ifndef REVERB_FILTER_H
+#define REVERB_FILTER_H
#include "core/math/audio_frame.h"
#include "core/os/memory.h"
@@ -119,4 +119,4 @@ public:
~Reverb();
};
-#endif // REVERB_H
+#endif // REVERB_FILTER_H
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 8ec3e469d3..1054073377 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -350,6 +350,10 @@ void AudioServer::_mix_step() {
// Mix the audio stream
unsigned int mixed_frames = playback->stream_playback->mix(&buf[LOOKAHEAD_BUFFER_SIZE], playback->pitch_scale.get(), buffer_size);
+ if (tag_used_audio_streams && playback->stream_playback->is_playing()) {
+ playback->stream_playback->tag_used_streams();
+ }
+
if (mixed_frames != buffer_size) {
// We know we have at least the size of our lookahead buffer for fade-out purposes.
@@ -1312,6 +1316,10 @@ uint64_t AudioServer::get_mix_count() const {
return mix_count;
}
+uint64_t AudioServer::get_mixed_frames() const {
+ return mix_frames;
+}
+
void AudioServer::notify_listener_changed() {
for (CallbackItem *ci : listener_changed_callback_list) {
ci->callback(ci->userdata);
@@ -1653,6 +1661,10 @@ void AudioServer::capture_set_device(const String &p_name) {
AudioDriver::get_singleton()->capture_set_device(p_name);
}
+void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) {
+ tag_used_audio_streams = p_enable;
+}
+
void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count);
ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count);
@@ -1719,6 +1731,8 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout);
ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout);
+ ClassDB::bind_method(D_METHOD("set_enable_tagging_used_audio_streams", "enable"), &AudioServer::set_enable_tagging_used_audio_streams);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device");
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 18e173ff0b..287a18ecde 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -187,6 +187,8 @@ private:
float playback_speed_scale = 1.0f;
+ bool tag_used_audio_streams = false;
+
struct Bus {
StringName name;
bool solo = false;
@@ -380,6 +382,7 @@ public:
bool is_playback_paused(Ref<AudioStreamPlayback> p_playback);
uint64_t get_mix_count() const;
+ uint64_t get_mixed_frames() const;
void notify_listener_changed();
@@ -424,6 +427,8 @@ public:
String capture_get_device();
void capture_set_device(const String &p_name);
+ void set_enable_tagging_used_audio_streams(bool p_enable);
+
AudioServer();
virtual ~AudioServer();
};
diff --git a/servers/debugger/servers_debugger.h b/servers/debugger/servers_debugger.h
index f949c436e7..be0e64fbc0 100644
--- a/servers/debugger/servers_debugger.h
+++ b/servers/debugger/servers_debugger.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SERVER_DEBUGGER_H
-#define SERVER_DEBUGGER_H
+#ifndef SERVERS_DEBUGGER_H
+#define SERVERS_DEBUGGER_H
#include "core/debugger/debugger_marshalls.h"
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
index 663af1ae6c..c4b4a00eaf 100644
--- a/servers/extensions/physics_server_3d_extension.h
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -545,4 +545,4 @@ public:
~PhysicsServer3DExtension();
};
-#endif // PHYSICSSERVER3DEXTENSION_H
+#endif // PHYSICS_SERVER_3D_EXTENSION_H
diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp
index 9f96b8cfda..40b2b2539e 100644
--- a/servers/movie_writer/movie_writer.cpp
+++ b/servers/movie_writer/movie_writer.cpp
@@ -30,6 +30,9 @@
#include "movie_writer.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/os/time.h"
+#include "servers/display_server.h"
MovieWriter *MovieWriter::writers[MovieWriter::MAX_WRITERS];
uint32_t MovieWriter::writer_count = 0;
@@ -101,6 +104,7 @@ void MovieWriter::get_supported_extensions(List<String> *r_extensions) const {
}
void MovieWriter::begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+ project_name = GLOBAL_GET("application/config/name");
mix_rate = get_audio_mix_rate();
AudioDriverDummy::get_dummy_singleton()->set_mix_rate(mix_rate);
AudioDriverDummy::get_dummy_singleton()->set_speaker_mode(AudioDriver::SpeakerMode(get_audio_speaker_mode()));
@@ -162,10 +166,47 @@ void MovieWriter::set_extensions_hint() {
}
void MovieWriter::add_frame(const Ref<Image> &p_image) {
+ const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps;
+ const String movie_time = vformat("%s:%s:%s",
+ String::num(movie_time_seconds / 3600).pad_zeros(2),
+ String::num((movie_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(movie_time_seconds % 60).pad_zeros(2));
+
+#ifdef DEBUG_ENABLED
+ DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s (DEBUG)", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name));
+#else
+ DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name));
+#endif
+
AudioDriverDummy::get_dummy_singleton()->mix_audio(mix_rate / fps, audio_mix_buffer.ptr());
write_frame(p_image, audio_mix_buffer.ptr());
}
void MovieWriter::end() {
write_end();
+
+ // Print a report with various statistics.
+ print_line("----------------");
+ String movie_path = Engine::get_singleton()->get_write_movie_path();
+ 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);
+ }
+ print_line(vformat("Done recording movie at path: %s", movie_path));
+
+ const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps;
+ const String movie_time = vformat("%s:%s:%s",
+ String::num(movie_time_seconds / 3600).pad_zeros(2),
+ String::num((movie_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(movie_time_seconds % 60).pad_zeros(2));
+
+ const int real_time_seconds = Time::get_singleton()->get_ticks_msec() / 1000;
+ const String real_time = vformat("%s:%s:%s",
+ String::num(real_time_seconds / 3600).pad_zeros(2),
+ String::num((real_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(real_time_seconds % 60).pad_zeros(2));
+
+ print_line(vformat("%d frames at %d FPS (movie length: %s), recorded in %s (%d%% of real-time speed).", Engine::get_singleton()->get_frames_drawn(), fps, movie_time, real_time, (float(movie_time_seconds) / real_time_seconds) * 100));
+ print_line("----------------");
}
diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h
index 1ec6e93052..7877a60715 100644
--- a/servers/movie_writer/movie_writer.h
+++ b/servers/movie_writer/movie_writer.h
@@ -42,6 +42,8 @@ class MovieWriter : public Object {
uint64_t mix_rate = 0;
uint32_t audio_channels = 0;
+ String project_name;
+
LocalVector<int32_t> audio_mix_buffer;
enum {
diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp
index 551fd9329f..0603458acd 100644
--- a/servers/physics_2d/godot_step_2d.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -239,7 +239,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &GodotStep2D::_setup_contraint, nullptr);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics2DConstraintSetup"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -258,7 +259,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
+ group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics2DConstraintSolveIslands"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -297,10 +299,7 @@ GodotStep2D::GodotStep2D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
-
- work_pool.init();
}
GodotStep2D::~GodotStep2D() {
- work_pool.finish();
}
diff --git a/servers/physics_2d/godot_step_2d.h b/servers/physics_2d/godot_step_2d.h
index 9a6d8caf9b..9f8fdd6ce3 100644
--- a/servers/physics_2d/godot_step_2d.h
+++ b/servers/physics_2d/godot_step_2d.h
@@ -33,8 +33,8 @@
#include "godot_space_2d.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
-#include "core/templates/thread_work_pool.h"
class GodotStep2D {
uint64_t _step = 1;
@@ -42,8 +42,6 @@ class GodotStep2D {
int iterations = 0;
real_t delta = 0.0;
- ThreadWorkPool work_pool;
-
LocalVector<LocalVector<GodotBody2D *>> body_islands;
LocalVector<LocalVector<GodotConstraint2D *>> constraint_islands;
LocalVector<GodotConstraint2D *> all_constraints;
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index 01a47f222e..309af76561 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -37,4 +37,4 @@
bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
-#endif
+#endif // GJK_EPA_H
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.h b/servers/physics_3d/godot_collision_solver_3d_sat.h
index 3eb7aa4c9e..46c5ec3254 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.h
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_COLLISION_SOLVER_SAT_H
-#define GODOT_COLLISION_SOLVER_SAT_H
+#ifndef GODOT_COLLISION_SOLVER_3D_SAT_H
+#define GODOT_COLLISION_SOLVER_3D_SAT_H
#include "godot_collision_solver_3d.h"
bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
-#endif // GODOT_COLLISION_SOLVER_SAT_H
+#endif // GODOT_COLLISION_SOLVER_3D_SAT_H
diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp
index 99656d01a0..f384c829a4 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -343,7 +343,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &GodotStep3D::_setup_contraint, nullptr);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics3DConstraintSetup"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -362,7 +363,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
+ group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics3DConstraintSolveIslands"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -409,10 +411,7 @@ GodotStep3D::GodotStep3D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
-
- work_pool.init();
}
GodotStep3D::~GodotStep3D() {
- work_pool.finish();
}
diff --git a/servers/physics_3d/godot_step_3d.h b/servers/physics_3d/godot_step_3d.h
index 6d975b0dd3..189487757f 100644
--- a/servers/physics_3d/godot_step_3d.h
+++ b/servers/physics_3d/godot_step_3d.h
@@ -33,8 +33,8 @@
#include "godot_space_3d.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
-#include "core/templates/thread_work_pool.h"
class GodotStep3D {
uint64_t _step = 1;
@@ -42,8 +42,6 @@ class GodotStep3D {
int iterations = 0;
real_t delta = 0.0;
- ThreadWorkPool work_pool;
-
LocalVector<LocalVector<GodotBody3D *>> body_islands;
LocalVector<LocalVector<GodotConstraint3D *>> constraint_islands;
LocalVector<GodotConstraint3D *> all_constraints;
diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h
index 8a2be90507..623f94b95f 100644
--- a/servers/rendering/dummy/environment/fog.h
+++ b/servers/rendering/dummy/environment/fog.h
@@ -52,4 +52,4 @@ public:
} // namespace RendererDummy
-#endif // !FOG_DUMMY_H
+#endif // FOG_DUMMY_H
diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h
index 9c7647c2de..76d34cd14e 100644
--- a/servers/rendering/dummy/environment/gi.h
+++ b/servers/rendering/dummy/environment/gi.h
@@ -79,4 +79,4 @@ public:
} // namespace RendererDummy
-#endif // !GI_DUMMY_H
+#endif // GI_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h
index 194b5b5cfe..64c4cf5024 100644
--- a/servers/rendering/dummy/rasterizer_canvas_dummy.h
+++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h
@@ -60,4 +60,4 @@ public:
~RasterizerCanvasDummy() {}
};
-#endif // !RASTERIZER_CANVAS_DUMMY_H
+#endif // RASTERIZER_CANVAS_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
index b49d6cff69..9a376b8806 100644
--- a/servers/rendering/dummy/rasterizer_scene_dummy.h
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -35,33 +35,10 @@
class RasterizerSceneDummy : public RendererSceneRender {
public:
- GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
- void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
- void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
- void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
- void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
- void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
- void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
- void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
- void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
- void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
- void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
- void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
- void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
+ RenderGeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
+ void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override {}
uint32_t geometry_instance_get_pair_mask() override { return 0; }
- void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
- void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
- void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
- void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
-
- void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
/* SHADOW ATLAS API */
@@ -149,7 +126,7 @@ public:
RID light_instance_create(RID p_light) override { return RID(); }
void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
+ void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
void light_instance_mark_visible(RID p_light_instance) override {}
RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
@@ -179,13 +156,13 @@ public:
RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
bool voxel_gi_needs_update(RID p_probe) const override { return false; }
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override {}
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+ void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {}
void set_scene_pass(uint64_t p_pass) override {}
void set_time(double p_time, double p_step) override {}
@@ -214,4 +191,4 @@ public:
~RasterizerSceneDummy() {}
};
-#endif // !RASTERIZER_SCENE_DUMMY_H
+#endif // RASTERIZER_SCENE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index b0100a5fe7..0c0ea61df5 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -132,4 +132,4 @@ public:
} // namespace RendererDummy
-#endif // !LIGHT_STORAGE_DUMMY_H
+#endif // LIGHT_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index d4809f81e3..6721284b23 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -63,6 +63,8 @@ public:
virtual void shader_free(RID p_rid) override{};
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_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 {}
@@ -93,4 +95,4 @@ public:
} // namespace RendererDummy
-#endif // !MATERIAL_STORAGE_DUMMY_H
+#endif // MATERIAL_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index 78b19d721d..8dfcd978ac 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -131,4 +131,4 @@ public:
} // namespace RendererDummy
-#endif // !MESH_STORAGE_DUMMY_H
+#endif // MESH_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
index f614b41c4c..7cee55922d 100644
--- a/servers/rendering/dummy/storage/particles_storage.h
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -123,4 +123,4 @@ public:
} // namespace RendererDummy
-#endif // !PARTICLES_STORAGE_DUMMY_H
+#endif // PARTICLES_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 195d378a41..73b1284558 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -176,4 +176,4 @@ public:
} // namespace RendererDummy
-#endif // !TEXTURE_STORAGE_DUMMY_H
+#endif // TEXTURE_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h
index f090309e88..b94f678c75 100644
--- a/servers/rendering/dummy/storage/utilities.h
+++ b/servers/rendering/dummy/storage/utilities.h
@@ -95,4 +95,4 @@ public:
} // namespace RendererDummy
-#endif // !UTILITIES_DUMMY_H
+#endif // UTILITIES_DUMMY_H
diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h
index ac50da0fc0..c55021e1a1 100644
--- a/servers/rendering/environment/renderer_fog.h
+++ b/servers/rendering/environment/renderer_fog.h
@@ -50,4 +50,4 @@ public:
virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
};
-#endif // !RENDERER_FOG_H
+#endif // RENDERER_FOG_H
diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h
index 4f93bb8675..70d2bb3a9c 100644
--- a/servers/rendering/environment/renderer_gi.h
+++ b/servers/rendering/environment/renderer_gi.h
@@ -78,4 +78,4 @@ public:
virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0;
};
-#endif // !RENDERER_GI_H
+#endif // RENDERER_GI_H
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 48d0598c9f..e8c54310c9 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_CANVAS_CULL_H
-#define RENDERING_SERVER_CANVAS_CULL_H
+#ifndef RENDERER_CANVAS_CULL_H
+#define RENDERER_CANVAS_CULL_H
#include "core/templates/paged_allocator.h"
#include "renderer_compositor.h"
@@ -317,4 +317,4 @@ public:
~RendererCanvasCull();
};
-#endif // RENDERING_SERVER_CANVAS_CULL_H
+#endif // RENDERER_CANVAS_CULL_H
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 52b2f82089..11a7d34291 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERCANVASRENDER_H
-#define RENDERINGSERVERCANVASRENDER_H
+#ifndef RENDERER_CANVAS_RENDER_H
+#define RENDERER_CANVAS_RENDER_H
#include "servers/rendering_server.h"
@@ -77,7 +77,7 @@ public:
Rect2 rect_cache;
Transform2D xform_cache;
float radius_cache; //used for shadow far plane
- //CameraMatrix shadow_matrix_cache;
+ //Projection shadow_matrix_cache;
Transform2D light_shader_xform;
//Vector2 light_shader_pos;
@@ -520,4 +520,4 @@ public:
virtual ~RendererCanvasRender() {}
};
-#endif // RENDERINGSERVERCANVASRENDER_H
+#endif // RENDERER_CANVAS_RENDER_H
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index b331ec2c1d..80e71a0df3 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "servers/xr_server.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
bool RendererCompositor::low_end = false;
@@ -46,7 +47,11 @@ bool RendererCompositor::is_xr_enabled() const {
}
RendererCompositor::RendererCompositor() {
- xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
+ xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ } else {
+ xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
+ }
}
RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index a67eb25736..4cfded8460 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_COMPOSITOR_H
-#define RENDERING_SERVER_COMPOSITOR_H
+#ifndef RENDERER_COMPOSITOR_H
+#define RENDERER_COMPOSITOR_H
#include "servers/rendering/environment/renderer_fog.h"
#include "servers/rendering/environment/renderer_gi.h"
@@ -109,4 +109,4 @@ public:
virtual ~RendererCompositor() {}
};
-#endif // RASTERIZER_H
+#endif // RENDERER_COMPOSITOR_H
diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp
new file mode 100644
index 0000000000..3a9bab022c
--- /dev/null
+++ b/servers/rendering/renderer_geometry_instance.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* renderer_geometry_instance.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 "servers/rendering/renderer_geometry_instance.h"
+
+void RenderGeometryInstanceBase::set_skeleton(RID p_skeleton) {
+ data->skeleton = p_skeleton;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_material_override(RID p_override) {
+ data->material_override = p_override;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_material_overlay(RID p_overlay) {
+ data->material_overlay = p_overlay;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_surface_materials(const Vector<RID> &p_materials) {
+ data->surface_materials = p_materials;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_mesh_instance(RID p_mesh_instance) {
+ mesh_instance = p_mesh_instance;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+ transform = p_transform;
+ mirror = p_transform.basis.determinant() < 0;
+ data->aabb = p_aabb;
+ transformed_aabb = p_transformed_aabb;
+
+ Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
+ // handle non uniform scale here
+
+ float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+ non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
+
+ lod_model_scale = max_scale;
+}
+
+void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) {
+ lod_bias = p_lod_bias;
+}
+
+void RenderGeometryInstanceBase::set_layer_mask(uint32_t p_layer_mask) {
+ layer_mask = p_layer_mask;
+}
+
+void RenderGeometryInstanceBase::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) {
+ fade_near = p_enable_near;
+ fade_near_begin = p_near_begin;
+ fade_near_end = p_near_end;
+ fade_far = p_enable_far;
+ fade_far_begin = p_far_begin;
+ fade_far_end = p_far_end;
+}
+
+void RenderGeometryInstanceBase::set_parent_fade_alpha(float p_alpha) {
+ parent_fade_alpha = p_alpha;
+}
+
+void RenderGeometryInstanceBase::set_transparency(float p_transparency) {
+ force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+}
+
+void RenderGeometryInstanceBase::set_use_baked_light(bool p_enable) {
+ data->use_baked_light = p_enable;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_use_dynamic_gi(bool p_enable) {
+ data->use_dynamic_gi = p_enable;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_instance_shader_parameters_offset(int32_t p_offset) {
+ shader_parameters_offset = p_offset;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_cast_double_sided_shadows(bool p_enable) {
+ data->cast_double_sided_shadows = p_enable;
+
+ _mark_dirty();
+}
+
+Transform3D RenderGeometryInstanceBase::get_transform() {
+ return transform;
+}
+
+AABB RenderGeometryInstanceBase::get_aabb() {
+ return data->aabb;
+}
diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h
new file mode 100644
index 0000000000..279566d5c9
--- /dev/null
+++ b/servers/rendering/renderer_geometry_instance.h
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* renderer_geometry_instance.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 RENDERER_GEOMETRY_INSTANCE_H
+#define RENDERER_GEOMETRY_INSTANCE_H
+
+#include "core/math/rect2.h"
+#include "core/math/transform_3d.h"
+#include "core/math/vector3.h"
+#include "core/templates/rid.h"
+#include "storage/utilities.h"
+
+// API definition for our RenderGeometryInstance class so we can expose this through GDExternal in the near future
+class RenderGeometryInstance {
+public:
+ virtual ~RenderGeometryInstance() {}
+
+ virtual void _mark_dirty() = 0;
+
+ virtual void set_skeleton(RID p_skeleton) = 0;
+ virtual void set_material_override(RID p_override) = 0;
+ virtual void set_material_overlay(RID p_overlay) = 0;
+ virtual void set_surface_materials(const Vector<RID> &p_materials) = 0;
+ virtual void set_mesh_instance(RID p_mesh_instance) = 0;
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) = 0;
+ virtual void set_lod_bias(float p_lod_bias) = 0;
+ virtual void set_layer_mask(uint32_t p_layer_mask) = 0;
+ 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) = 0;
+ virtual void set_parent_fade_alpha(float p_alpha) = 0;
+ virtual void set_transparency(float p_transparency) = 0;
+ virtual void set_use_baked_light(bool p_enable) = 0;
+ 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_cast_double_sided_shadows(bool p_enable) = 0;
+
+ virtual Transform3D get_transform() = 0;
+ virtual AABB get_aabb() = 0;
+
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
+
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) = 0;
+};
+
+// Base implementation of RenderGeometryInstance shared by internal renderers.
+class RenderGeometryInstanceBase : public RenderGeometryInstance {
+public:
+ // setup
+ uint32_t base_flags = 0;
+ uint32_t flags_cache = 0;
+
+ // used during rendering
+ float depth = 0;
+
+ RID mesh_instance;
+
+ Transform3D transform;
+ bool mirror = false; // move into data?
+ AABB transformed_aabb; //needed for LOD
+ bool non_uniform_scale = false;
+ float lod_model_scale = 1.0;
+ float lod_bias = 0.0;
+
+ uint32_t layer_mask = 1;
+
+ bool fade_near = false;
+ float fade_near_begin = 0;
+ float fade_near_end = 0;
+ bool fade_far = false;
+ float fade_far_begin = 0;
+ float fade_far_end = 0;
+
+ float parent_fade_alpha = 1.0;
+ float force_alpha = 1.0;
+
+ int32_t shader_parameters_offset = -1;
+
+ struct Data {
+ //data used less often goes into regular heap
+ RID base;
+ RS::InstanceType base_type;
+
+ RID skeleton;
+ Vector<RID> surface_materials;
+ RID material_override;
+ RID material_overlay;
+ AABB aabb;
+
+ bool use_baked_light = false;
+ bool use_dynamic_gi = false;
+ bool cast_double_sided_shadows = false;
+ bool dirty_dependencies = false;
+
+ DependencyTracker dependency_tracker;
+ };
+
+ Data *data = nullptr;
+
+ 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_instance_shader_parameters_offset(int32_t p_offset) override;
+ virtual void set_cast_double_sided_shadows(bool p_enable) override;
+
+ virtual Transform3D get_transform() override;
+ virtual AABB get_aabb() override;
+};
+
+#endif // RENDERER_GEOMETRY_INSTANCE_H
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 228933d618..1bb45cbcc1 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -374,7 +374,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
}
}
-void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) {
+void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y) {
view_xform = p_view_transform.affine_inverse();
projection = p_cam_projection;
z_near = projection.get_z_near();
@@ -385,7 +385,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa
adjusted_projection.adjust_perspective_znear(0.0001);
}
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
projection = correction * projection;
adjusted_projection = correction * adjusted_projection;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 74ca530ff6..17ca1986c6 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -168,8 +168,8 @@ private:
uint32_t render_element_max = 0;
Transform3D view_xform;
- CameraMatrix adjusted_projection;
- CameraMatrix projection;
+ Projection adjusted_projection;
+ Projection projection;
float z_far = 0;
float z_near = 0;
bool orthogonal = false;
@@ -220,7 +220,7 @@ private:
public:
void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer);
- void begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y);
+ void begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y);
_FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) {
@@ -375,4 +375,4 @@ public:
~ClusterBuilderRD();
};
-#endif // CLUSTER_BUILDER_H
+#endif // CLUSTER_BUILDER_RD_H
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
index d7b736119c..30b33be168 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.h
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -117,4 +117,4 @@ public:
} // namespace RendererRD
-#endif // !BOKEH_DOF_RD_H
+#endif // BOKEH_DOF_RD_H
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index cbf7046887..5507483cee 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -249,6 +249,56 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
roughness.raster_pipeline.clear();
}
}
+
+ {
+ Vector<String> specular_modes;
+ specular_modes.push_back("\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD
+ specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR
+ specular_modes.push_back("\n"); // SPECULAR_MERGE_ADDITIVE_ADD
+ specular_modes.push_back("\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR
+
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n"); // SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW
+
+ specular_merge.shader.initialize(specular_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADD_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_SSR_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, false);
+ }
+
+ specular_merge.shader_version = specular_merge.shader.version_create();
+
+ //use additive
+
+ RD::PipelineColorBlendState::Attachment ba;
+ ba.enable_blend = true;
+ ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.color_blend_op = RD::BLEND_OP_ADD;
+ ba.alpha_blend_op = RD::BLEND_OP_ADD;
+
+ RD::PipelineColorBlendState blend_additive;
+ blend_additive.attachments.push_back(ba);
+
+ for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
+ if (specular_merge.shader.is_variant_enabled(i)) {
+ RD::PipelineColorBlendState blend_state;
+ if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR || i == SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW || i == SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW) {
+ blend_state = blend_additive;
+ } else {
+ blend_state = RD::PipelineColorBlendState::create_disabled();
+ }
+ specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ }
+ }
}
CopyEffects::~CopyEffects() {
@@ -264,6 +314,8 @@ CopyEffects::~CopyEffects() {
roughness.compute_shader.version_free(roughness.shader_version);
}
+ specular_merge.shader.version_free(specular_merge.shader_version);
+
RD::get_singleton()->free(filter.coefficient_buffer);
if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
@@ -1083,3 +1135,57 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
+
+void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::get_singleton()->draw_command_begin_label("Merge specular");
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>());
+
+ int mode;
+ if (p_reflection.is_valid()) {
+ if (p_base.is_valid()) {
+ mode = SPECULAR_MERGE_SSR;
+ } else {
+ mode = SPECULAR_MERGE_ADDITIVE_SSR;
+ }
+ } else {
+ if (p_base.is_valid()) {
+ mode = SPECULAR_MERGE_ADD;
+ } else {
+ mode = SPECULAR_MERGE_ADDITIVE_ADD;
+ }
+ }
+
+ if (p_view_count > 1) {
+ mode += SPECULAR_MERGE_ADD_MULTIVIEW;
+ }
+
+ RID shader = specular_merge.shader.version_get_shader(specular_merge.shader_version, mode);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+
+ if (p_base.is_valid()) {
+ RD::Uniform u_base(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_base }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_base), 2);
+ }
+
+ RD::Uniform u_specular(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_specular }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_specular), 0);
+
+ if (p_reflection.is_valid()) {
+ RD::Uniform u_reflection(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_reflection }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1);
+ }
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index 882b446964..d25555eee5 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COPY_RD_H
-#define COPY_RD_H
+#ifndef COPY_EFFECTS_RD_H
+#define COPY_EFFECTS_RD_H
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h"
@@ -42,6 +42,7 @@
#include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -274,6 +275,33 @@ private:
PipelineCacheRD raster_pipeline;
} roughness;
+ // Merge specular
+
+ enum SpecularMergeMode {
+ SPECULAR_MERGE_ADD,
+ SPECULAR_MERGE_SSR,
+ SPECULAR_MERGE_ADDITIVE_ADD,
+ SPECULAR_MERGE_ADDITIVE_SSR,
+
+ SPECULAR_MERGE_ADD_MULTIVIEW,
+ SPECULAR_MERGE_SSR_MULTIVIEW,
+ SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW,
+ SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW,
+
+ SPECULAR_MERGE_MAX
+ };
+
+ /* Specular merge must be done using raster, rather than compute
+ * because it must continue the existing color buffer
+ */
+
+ struct SpecularMerge {
+ SpecularMergeShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[SPECULAR_MERGE_MAX];
+
+ } specular_merge;
+
static CopyEffects *singleton;
public:
@@ -309,8 +337,10 @@ public:
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
+
+ void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count);
};
} // namespace RendererRD
-#endif // !COPY_RD_H
+#endif // COPY_EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h
index d4b24a610f..2a4cd06827 100644
--- a/servers/rendering/renderer_rd/effects/resolve.h
+++ b/servers/rendering/renderer_rd/effects/resolve.h
@@ -71,4 +71,4 @@ public:
} // namespace RendererRD
-#endif // !RESOLVE_RD_H
+#endif // RESOLVE_RD_H
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
new file mode 100644
index 0000000000..0f896a8aa7
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -0,0 +1,1715 @@
+/*************************************************************************/
+/* ss_effects.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "ss_effects.h"
+
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+SSEffects *SSEffects::singleton = nullptr;
+
+static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ }
+ }
+}
+
+SSEffects::SSEffects() {
+ singleton = this;
+
+ {
+ // Initialize depth buffer for screen space effects
+ Vector<String> downsampler_modes;
+ downsampler_modes.push_back("\n");
+ downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
+
+ ss_effects.downsample_shader.initialize(downsampler_modes);
+
+ ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
+
+ for (int i = 0; i < SS_EFFECTS_MAX; i++) {
+ ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
+ }
+
+ ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
+ SSEffectsGatherConstants gather_constants;
+
+ const int sub_pass_count = 5;
+ for (int pass = 0; pass < 4; pass++) {
+ for (int subPass = 0; subPass < sub_pass_count; subPass++) {
+ int a = pass;
+ int b = subPass;
+
+ int spmap[5]{ 0, 1, 4, 3, 2 };
+ b = spmap[subPass];
+
+ float ca, sa;
+ float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
+
+ ca = Math::cos(angle0);
+ sa = Math::sin(angle0);
+
+ float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
+
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
+ }
+ }
+
+ RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
+ }
+
+ // Initialize Screen Space Indirect Lighting (SSIL)
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n");
+ ssil_modes.push_back("\n#define SSIL_BASE\n");
+ ssil_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssil.gather_shader.initialize(ssil_modes);
+
+ ssil.gather_shader_version = ssil.gather_shader.version_create();
+
+ for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
+ }
+ ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define GENERATE_MAP\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssil.importance_map_shader.initialize(ssil_modes);
+
+ ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
+
+ for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
+ }
+ ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssil.blur_shader.initialize(ssil_modes);
+
+ ssil.blur_shader_version = ssil.blur_shader.version_create();
+ for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
+ }
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_HALF\n");
+
+ ssil.interleave_shader.initialize(ssil_modes);
+
+ ssil.interleave_shader_version = ssil.interleave_shader.version_create();
+ for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
+ }
+ }
+
+ {
+ // Initialize Screen Space Ambient Occlusion (SSAO)
+
+ RD::SamplerState sampler;
+ sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.max_lod = 4;
+
+ uint32_t pipeline = 0;
+ {
+ Vector<String> ssao_modes;
+
+ ssao_modes.push_back("\n");
+ ssao_modes.push_back("\n#define SSAO_BASE\n");
+ ssao_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssao.gather_shader.initialize(ssao_modes);
+
+ ssao.gather_shader_version = ssao.gather_shader.version_create();
+
+ for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
+ pipeline++;
+ }
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define GENERATE_MAP\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssao.importance_map_shader.initialize(ssao_modes);
+
+ ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
+
+ for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
+
+ pipeline++;
+ }
+
+ ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssao.blur_shader.initialize(ssao_modes);
+
+ ssao.blur_shader_version = ssao.blur_shader.version_create();
+
+ for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
+
+ pipeline++;
+ }
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_HALF\n");
+
+ ssao.interleave_shader.initialize(ssao_modes);
+
+ ssao.interleave_shader_version = ssao.interleave_shader.version_create();
+ for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
+ RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
+ pipeline++;
+ }
+ }
+
+ ERR_FAIL_COND(pipeline != SSAO_MAX);
+
+ ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
+ }
+
+ {
+ // Screen Space Reflections
+
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
+
+ {
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+ }
+
+ {
+ Vector<String> ssr_scale_modes;
+ ssr_scale_modes.push_back("\n");
+
+ ssr_scale.shader.initialize(ssr_scale_modes);
+ ssr_scale.shader_version = ssr_scale.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);
+ }
+ }
+
+ {
+ Vector<String> ssr_modes;
+ ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL
+ ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH
+
+ ssr.shader.initialize(ssr_modes);
+ ssr.shader_version = ssr.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
+ ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);
+ }
+ }
+ }
+
+ {
+ Vector<String> ssr_filter_modes;
+ ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL
+ ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL
+
+ ssr_filter.shader.initialize(ssr_filter_modes);
+ ssr_filter.shader_version = ssr_filter.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
+ ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);
+ }
+ }
+ }
+ }
+}
+
+SSEffects::~SSEffects() {
+ {
+ // Cleanup SS Reflections
+ ssr.shader.version_free(ssr.shader_version);
+ ssr_filter.shader.version_free(ssr_filter.shader_version);
+ ssr_scale.shader.version_free(ssr_scale.shader_version);
+
+ if (ssr.ubo.is_valid()) {
+ RD::get_singleton()->free(ssr.ubo);
+ }
+ }
+
+ {
+ // Cleanup SS downsampler
+ ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
+
+ RD::get_singleton()->free(ss_effects.mirror_sampler);
+ RD::get_singleton()->free(ss_effects.gather_constants_buffer);
+ }
+
+ {
+ // Cleanup SSIL
+ ssil.blur_shader.version_free(ssil.blur_shader_version);
+ ssil.gather_shader.version_free(ssil.gather_shader_version);
+ ssil.interleave_shader.version_free(ssil.interleave_shader_version);
+ ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
+
+ RD::get_singleton()->free(ssil.importance_map_load_counter);
+ RD::get_singleton()->free(ssil.projection_uniform_buffer);
+ }
+
+ {
+ // Cleanup SSAO
+ ssao.blur_shader.version_free(ssao.blur_shader_version);
+ ssao.gather_shader.version_free(ssao.gather_shader_version);
+ ssao.interleave_shader.version_free(ssao.interleave_shader_version);
+ ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
+
+ RD::get_singleton()->free(ssao.importance_map_load_counter);
+ }
+
+ singleton = nullptr;
+}
+
+/* SS Downsampler */
+
+void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // Downsample and deinterleave the depth buffer for SSAO and SSIL
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int downsample_mode = SS_EFFECTS_DOWNSAMPLE;
+ bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
+
+ if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;
+ } else if (use_mips) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ }
+
+ bool use_half_size = false;
+ bool use_full_mips = false;
+
+ if (p_ssao_half_size && p_ssil_half_size) {
+ downsample_mode++;
+ use_half_size = true;
+ } else if (p_ssao_half_size != p_ssil_half_size) {
+ if (use_mips) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
+ use_full_mips = true;
+ } else {
+ // Only need the first two mipmaps, but the cost to generate the next two is trivial
+ // TODO investigate the benefit of a shader version to generate only 2 mips
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ use_mips = true;
+ }
+ }
+
+ int depth_index = use_half_size ? 1 : 0;
+
+ RD::get_singleton()->draw_command_begin_label("Downsample Depth");
+ if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_depth_mipmaps[depth_index + 1]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_depth_mipmaps[depth_index + 2]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.append_id(p_depth_mipmaps[depth_index + 3]);
+ uniforms.push_back(u);
+ }
+ if (use_full_mips) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.append_id(p_depth_mipmaps[4]);
+ uniforms.push_back(u);
+ }
+ ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
+ }
+
+ float depth_linearize_mul = -p_projection.matrix[3][2];
+ float depth_linearize_add = p_projection.matrix[2][2];
+ if (depth_linearize_mul * depth_linearize_add < 0) {
+ depth_linearize_add = -depth_linearize_add;
+ }
+
+ ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
+ ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
+ ss_effects.downsample_push_constant.z_far = depth_linearize_add;
+ if (ss_effects.downsample_push_constant.orthogonal) {
+ ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
+ ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
+ }
+ ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
+ ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
+ ss_effects.downsample_push_constant.radius_sq = 1.0;
+
+ RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer }));
+ RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1);
+ if (use_mips) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
+
+ Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
+
+ ss_effects.used_full_mips_last_frame = use_full_mips;
+ ss_effects.used_half_size_last_frame = use_half_size;
+}
+
+/* SSIL */
+
+void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
+
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));
+
+ ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssil.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) {
+ if (p_ssil_buffers.half_size != p_settings.half_size) {
+ ssil_free(p_ssil_buffers);
+ }
+
+ if (p_settings.half_size) {
+ p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
+ p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
+ } else {
+ p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
+ p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
+ p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ }
+
+ if (p_ssil_buffers.ssil_final.is_null()) {
+ {
+ p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = p_settings.full_screen_size.x;
+ tf.height = p_settings.full_screen_size.y;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture");
+ RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ if (p_ssil_buffers.last_frame.is_null()) {
+ tf.mipmaps = 6;
+ p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance");
+ RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
+ for (uint32_t i = 0; i < 6; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i);
+ p_ssil_buffers.last_frame_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
+ }
+ }
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0);
+ p_ssil_buffers.deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0);
+ p_ssil_buffers.pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0);
+ p_ssil_buffers.edges_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_ssil_buffers.half_buffer_width;
+ tf.height = p_ssil_buffers.half_buffer_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map");
+ p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong");
+ }
+ p_ssil_buffers.half_size = p_settings.half_size;
+ }
+}
+
+void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
+ //Store projection info before starting the compute list
+ SSILProjectionUniforms projection_uniforms;
+ store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
+
+ RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
+
+ memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
+
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssil.gather_push_constant.z_near = p_projection.get_z_near();
+ ssil.gather_push_constant.z_far = p_projection.get_z_far();
+ ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssil.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ ssil.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
+ ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
+ ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
+ ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
+
+ ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);
+ ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+
+ ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
+ ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+
+ if (p_ssil_buffers.projection_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_mipmap_sampler);
+ u.append_id(p_ssil_buffers.last_frame);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 1;
+ u.append_id(ssil.projection_uniform_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
+ }
+
+ if (p_ssil_buffers.gather_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_sampler);
+ u.append_id(p_ssil_buffers.depth_texture_view);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
+ }
+
+ if (p_ssil_buffers.importance_map_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_ssil_buffers.pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.append_id(default_sampler);
+ u.append_id(p_ssil_buffers.importance_map[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
+ }
+
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
+ gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+
+ //generate importance map
+ RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // process Importance Map A
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] }));
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // process Importance Map B
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
+ }
+
+ gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); //Gather
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+
+ int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+
+ shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSIL_BLUR_PASS;
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ blur_pipeline = SSIL_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSIL_BLUR_PASS_WIDE;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ } else {
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ }
+
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1);
+ } else {
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ } else {
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ }
+
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1);
+ }
+
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
+
+ int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
+ int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+
+ int interleave_pipeline = SSIL_INTERLEAVE_HALF;
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
+ interleave_pipeline = SSIL_INTERLEAVE;
+ } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
+ interleave_pipeline = SSIL_INTERLEAVE_SMART;
+ }
+
+ shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
+
+ RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
+
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
+ } else {
+ RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);
+ }
+
+ RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // SSIL
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
+void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) {
+ if (p_ssil_buffers.ssil_final.is_valid()) {
+ RD::get_singleton()->free(p_ssil_buffers.ssil_final);
+ RD::get_singleton()->free(p_ssil_buffers.deinterleaved);
+ RD::get_singleton()->free(p_ssil_buffers.pong);
+ RD::get_singleton()->free(p_ssil_buffers.edges);
+ RD::get_singleton()->free(p_ssil_buffers.importance_map[0]);
+ RD::get_singleton()->free(p_ssil_buffers.importance_map[1]);
+ RD::get_singleton()->free(p_ssil_buffers.last_frame);
+
+ p_ssil_buffers.ssil_final = RID();
+ p_ssil_buffers.deinterleaved = RID();
+ p_ssil_buffers.pong = RID();
+ p_ssil_buffers.edges = RID();
+ p_ssil_buffers.deinterleaved_slices.clear();
+ p_ssil_buffers.pong_slices.clear();
+ p_ssil_buffers.edges_slices.clear();
+ p_ssil_buffers.importance_map[0] = RID();
+ p_ssil_buffers.importance_map[1] = RID();
+ p_ssil_buffers.last_frame = RID();
+ p_ssil_buffers.last_frame_slices.clear();
+
+ p_ssil_buffers.gather_uniform_set = RID();
+ p_ssil_buffers.importance_map_uniform_set = RID();
+ p_ssil_buffers.projection_uniform_set = RID();
+ }
+}
+
+/* SSAO */
+
+void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0);
+ }
+
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ao_slices[i] }));
+
+ ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssao.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) {
+ if (p_ssao_buffers.half_size != p_settings.half_size) {
+ ssao_free(p_ssao_buffers);
+ }
+
+ if (p_settings.half_size) {
+ p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
+ p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
+ } else {
+ p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
+ p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
+ p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ }
+
+ if (p_ssao_buffers.ao_deinterleaved.is_null()) {
+ {
+ p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0);
+ p_ssao_buffers.ao_deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0);
+ p_ssao_buffers.ao_pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map");
+ p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong");
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_settings.full_screen_size.x;
+ tf.height = p_settings.full_screen_size.y;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final");
+ }
+ p_ssao_buffers.half_size = p_settings.half_size;
+ }
+}
+
+void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
+ /* FIRST PASS */
+
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
+ /* SECOND PASS */
+ // Sample SSAO
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssao.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ ssao.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssao.gather_push_constant.intensity = p_settings.intensity;
+ ssao.gather_push_constant.shadow_power = p_settings.power;
+ ssao.gather_push_constant.shadow_clamp = 0.98;
+ ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
+ ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
+ ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
+
+ ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);
+ ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+
+ ssao.gather_push_constant.detail_intensity = p_settings.detail;
+ ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
+ ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+
+ if (p_ssao_buffers.gather_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_sampler);
+ u.append_id(p_ssao_buffers.depth_texture_view);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0);
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set");
+ }
+
+ if (p_ssao_buffers.importance_map_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_ssao_buffers.ao_pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.append_id(default_sampler);
+ u.append_id(p_ssao_buffers.importance_map[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set");
+ }
+
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ ssao.importance_map_push_constant.intensity = p_settings.intensity;
+ ssao.importance_map_push_constant.power = p_settings.power;
+
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
+ gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID());
+
+ //generate importance map
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
+
+ RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0);
+
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //process importance map A
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
+
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //process Importance Map B
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
+
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
+ }
+
+ gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); // Gather SSAO
+ }
+
+ // /* THIRD PASS */
+ // // Blur
+ //
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+
+ int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+
+ shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSAO_BLUR_PASS;
+ if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSAO_BLUR_PASS_WIDE;
+ } else {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ } else {
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ }
+
+ RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1);
+ } else {
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ } else {
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ }
+
+ RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
+
+ Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ }
+
+ if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ /* FOURTH PASS */
+ // Interleave buffers
+ // back to full size
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+
+ shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);
+
+ int interleave_pipeline = SSAO_INTERLEAVE_HALF;
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) {
+ interleave_pipeline = SSAO_INTERLEAVE;
+ } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
+ interleave_pipeline = SSAO_INTERLEAVE_SMART;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
+
+ RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0);
+
+ if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ } else {
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+ RD::get_singleton()->draw_command_end_label(); //SSAO
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
+void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) {
+ if (p_ssao_buffers.ao_final.is_valid()) {
+ RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved);
+ RD::get_singleton()->free(p_ssao_buffers.ao_pong);
+ RD::get_singleton()->free(p_ssao_buffers.ao_final);
+
+ RD::get_singleton()->free(p_ssao_buffers.importance_map[0]);
+ RD::get_singleton()->free(p_ssao_buffers.importance_map[1]);
+
+ p_ssao_buffers.ao_deinterleaved = RID();
+ p_ssao_buffers.ao_pong = RID();
+ p_ssao_buffers.ao_final = RID();
+ p_ssao_buffers.importance_map[0] = RID();
+ p_ssao_buffers.importance_map[1] = RID();
+ p_ssao_buffers.ao_deinterleaved_slices.clear();
+ p_ssao_buffers.ao_pong_slices.clear();
+
+ p_ssao_buffers.gather_uniform_set = RID();
+ p_ssao_buffers.importance_map_uniform_set = RID();
+ }
+}
+
+/* Screen Space Reflection */
+
+void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count) {
+ // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view.
+
+ if (p_ssr_buffers.depth_scaled.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled");
+
+ tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+
+ p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled");
+ }
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0");
+ p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1");
+ }
+
+ if (p_ssr_buffers.intermediate.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = p_color_format;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate");
+
+ if (p_view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.array_layers = p_view_count;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ }
+
+ p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output");
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0);
+ }
+ }
+}
+
+void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ {
+ // Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders
+ ScreenSpaceReflectionSceneData scene_data;
+
+ if (ssr.ubo.is_null()) {
+ ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));
+ }
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ store_camera(p_projections[v], scene_data.projection[v]);
+ store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
+ scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
+ scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
+ scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
+ scene_data.eye_offset[v][3] = 0.0;
+ }
+
+ RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
+ }
+
+ uint32_t pipeline_specialization = 0;
+ if (p_view_count > 1) {
+ pipeline_specialization |= SSR_MULTIVIEW;
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v));
+
+ { //scale color and depth to half
+ RD::get_singleton()->draw_command_begin_label("SSR Scale");
+
+ ScreenSpaceReflectionScalePushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.camera_z_far = p_projections[v].get_z_far();
+ push_constant.camera_z_near = p_projections[v].get_z_near();
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.filter = false; //enabling causes arctifacts
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+
+ RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);
+
+ RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);
+
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] }));
+ RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur), 2);
+
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("SSR main");
+
+ ScreenSpaceReflectionPushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.camera_z_far = p_projections[v].get_z_far();
+ push_constant.camera_z_near = p_projections[v].get_z_near();
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.curve_fade_in = p_fade_in;
+ push_constant.distance_fade = p_fade_out;
+ push_constant.num_steps = p_max_steps;
+ push_constant.depth_tolerance = p_tolerance;
+ push_constant.use_half_res = true;
+ 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];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
+ push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
+ push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
+ push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
+
+ ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
+ RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);
+
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_scale_depth), 0);
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1);
+ } else {
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
+ }
+
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2);
+
+ RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::get_singleton()->draw_command_begin_label("SSR filter");
+ //blur
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ 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.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];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ push_constant.vertical = 0;
+ if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
+ push_constant.steps = p_max_steps / 3;
+ push_constant.increment = 3;
+ } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
+ push_constant.steps = p_max_steps / 2;
+ push_constant.increment = 2;
+ } else {
+ push_constant.steps = p_max_steps;
+ push_constant.increment = 1;
+ }
+
+ push_constant.screen_size[0] = p_screen_size.width;
+ push_constant.screen_size[1] = p_screen_size.height;
+
+ // Horizontal pass
+
+ SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL;
+
+ RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
+
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0);
+
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2);
+
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // Vertical pass
+
+ mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL;
+ shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
+
+ push_constant.vertical = 1;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ if (v != p_view_count - 1) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ p_ssr_buffers.output_slices[v] = RID();
+ }
+
+ if (p_ssr_buffers.output.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.output);
+ p_ssr_buffers.output = RID();
+ }
+
+ if (p_ssr_buffers.intermediate.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.intermediate);
+ p_ssr_buffers.intermediate = RID();
+ }
+
+ if (p_ssr_buffers.blur_radius[0].is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]);
+ RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]);
+ p_ssr_buffers.blur_radius[0] = RID();
+ p_ssr_buffers.blur_radius[1] = RID();
+ }
+
+ if (p_ssr_buffers.depth_scaled.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.depth_scaled);
+ p_ssr_buffers.depth_scaled = RID();
+ RD::get_singleton()->free(p_ssr_buffers.normal_scaled);
+ p_ssr_buffers.normal_scaled = RID();
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
new file mode 100644
index 0000000000..c31271ffd2
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -0,0 +1,508 @@
+/*************************************************************************/
+/* ss_effects.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SS_EFFECTS_RD_H
+#define SS_EFFECTS_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class SSEffects {
+private:
+ static SSEffects *singleton;
+
+public:
+ static SSEffects *get_singleton() { return singleton; }
+
+ SSEffects();
+ ~SSEffects();
+
+ /* SS Downsampler */
+
+ void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection);
+
+ /* SSIL */
+
+ struct SSILRenderBuffers {
+ bool half_size = false;
+ int buffer_width;
+ int buffer_height;
+ int half_buffer_width;
+ int half_buffer_height;
+
+ RID ssil_final;
+ RID deinterleaved;
+ Vector<RID> deinterleaved_slices;
+ RID pong;
+ Vector<RID> pong_slices;
+ RID edges;
+ Vector<RID> edges_slices;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID last_frame;
+ Vector<RID> last_frame_slices;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ RID projection_uniform_set;
+ };
+
+ struct SSILSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float sharpness = 0.98;
+ float normal_rejection = 1.0;
+
+ RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool half_size = true;
+ float adaptive_target = 0.5;
+ int blur_passes = 4;
+ float fadeout_from = 50.0;
+ float fadeout_to = 300.0;
+
+ Size2i full_screen_size = Size2i();
+ };
+
+ void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
+ void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings);
+ void ssil_free(SSILRenderBuffers &p_ssil_buffers);
+
+ /* SSAO */
+
+ struct SSAORenderBuffers {
+ bool half_size = false;
+ int buffer_width;
+ int buffer_height;
+ int half_buffer_width;
+ int half_buffer_height;
+
+ RID ao_deinterleaved;
+ Vector<RID> ao_deinterleaved_slices;
+ RID ao_pong;
+ Vector<RID> ao_pong_slices;
+ RID ao_final;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ };
+
+ struct SSAOSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float power = 1.5;
+ float detail = 0.5;
+ float horizon = 0.06;
+ float sharpness = 0.98;
+
+ RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM;
+ bool half_size = false;
+ float adaptive_target = 0.5;
+ int blur_passes = 2;
+ float fadeout_from = 50.0;
+ float fadeout_to = 300.0;
+
+ Size2i full_screen_size = Size2i();
+ };
+
+ void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
+ void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings);
+ void ssao_free(SSAORenderBuffers &p_ssao_buffers);
+
+ /* Screen Space Reflection */
+
+ struct SSRRenderBuffers {
+ RID normal_scaled;
+ RID depth_scaled;
+ RID blur_radius[2];
+ RID intermediate;
+ RID output;
+ RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ };
+
+ void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count);
+ void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
+ void ssr_free(SSRRenderBuffers &p_ssr_buffers);
+
+private:
+ /* SS Downsampler */
+
+ struct SSEffectsDownsamplePushConstant {
+ float pixel_size[2];
+ float z_far;
+ float z_near;
+ uint32_t orthogonal;
+ float radius_sq;
+ uint32_t pad[2];
+ };
+
+ enum SSEffectsMode {
+ SS_EFFECTS_DOWNSAMPLE,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_HALF,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
+ SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
+ SS_EFFECTS_MAX
+ };
+
+ struct SSEffectsGatherConstants {
+ float rotation_matrices[80]; //5 vec4s * 4
+ };
+
+ struct SSEffectsShader {
+ SSEffectsDownsamplePushConstant downsample_push_constant;
+ SsEffectsDownsampleShaderRD downsample_shader;
+ RID downsample_shader_version;
+ RID downsample_uniform_set;
+ bool used_half_size_last_frame = false;
+ bool used_mips_last_frame = false;
+ bool used_full_mips_last_frame = false;
+
+ RID gather_constants_buffer;
+
+ RID mirror_sampler;
+
+ RID pipelines[SS_EFFECTS_MAX];
+ } ss_effects;
+
+ /* SSIL */
+
+ enum SSILMode {
+ SSIL_GATHER,
+ SSIL_GATHER_BASE,
+ SSIL_GATHER_ADAPTIVE,
+ SSIL_GENERATE_IMPORTANCE_MAP,
+ SSIL_PROCESS_IMPORTANCE_MAPA,
+ SSIL_PROCESS_IMPORTANCE_MAPB,
+ SSIL_BLUR_PASS,
+ SSIL_BLUR_PASS_SMART,
+ SSIL_BLUR_PASS_WIDE,
+ SSIL_INTERLEAVE,
+ SSIL_INTERLEAVE_SMART,
+ SSIL_INTERLEAVE_HALF,
+ SSIL_MAX
+ };
+
+ struct SSILGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ float half_screen_pixel_size_x025[2];
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad2[2];
+ float z_near;
+ float z_far;
+
+ float radius;
+ float intensity;
+ int size_multiplier;
+ int pad;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float normal_rejection_amount;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSILImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float pad;
+ };
+
+ struct SSILBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSILInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSILProjectionUniforms {
+ float inv_last_frame_projection_matrix[16];
+ };
+
+ struct SSIL {
+ SSILGatherPushConstant gather_push_constant;
+ SsilShaderRD gather_shader;
+ RID gather_shader_version;
+ RID projection_uniform_buffer;
+
+ SSILImportanceMapPushConstant importance_map_push_constant;
+ SsilImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSILBlurPushConstant blur_push_constant;
+ SsilBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSILInterleavePushConstant interleave_push_constant;
+ SsilInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSIL_MAX];
+ } ssil;
+
+ void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
+
+ /* SSAO */
+
+ enum SSAOMode {
+ SSAO_GATHER,
+ SSAO_GATHER_BASE,
+ SSAO_GATHER_ADAPTIVE,
+ SSAO_GENERATE_IMPORTANCE_MAP,
+ SSAO_PROCESS_IMPORTANCE_MAPA,
+ SSAO_PROCESS_IMPORTANCE_MAPB,
+ SSAO_BLUR_PASS,
+ SSAO_BLUR_PASS_SMART,
+ SSAO_BLUR_PASS_WIDE,
+ SSAO_INTERLEAVE,
+ SSAO_INTERLEAVE_SMART,
+ SSAO_INTERLEAVE_HALF,
+ SSAO_MAX
+ };
+
+ struct SSAOGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ int size_multiplier;
+ float detail_intensity;
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad[2];
+ float half_screen_pixel_size_x025[2];
+
+ float radius;
+ float intensity;
+ float shadow_power;
+ float shadow_clamp;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float horizon_angle_threshold;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSAOImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float power;
+ };
+
+ struct SSAOBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSAOInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSAO {
+ SSAOGatherPushConstant gather_push_constant;
+ SsaoShaderRD gather_shader;
+ RID gather_shader_version;
+
+ SSAOImportanceMapPushConstant importance_map_push_constant;
+ SsaoImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSAOBlurPushConstant blur_push_constant;
+ SsaoBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSAOInterleavePushConstant interleave_push_constant;
+ SsaoInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSAO_MAX];
+ } ssao;
+
+ void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
+
+ /* Screen Space Reflection */
+
+ enum SSRShaderSpecializations {
+ SSR_MULTIVIEW = 1 << 0,
+ SSR_VARIATIONS = 2,
+ };
+
+ struct ScreenSpaceReflectionSceneData {
+ float projection[2][16];
+ float inv_projection[2][16];
+ float eye_offset[2][4];
+ };
+
+ // SSR Scale
+
+ struct ScreenSpaceReflectionScalePushConstant {
+ int32_t screen_size[2];
+ float camera_z_near;
+ float camera_z_far;
+
+ uint32_t orthogonal;
+ uint32_t filter;
+ uint32_t view_index;
+ uint32_t pad1;
+ };
+
+ struct ScreenSpaceReflectionScale {
+ ScreenSpaceReflectionScaleShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS];
+ } ssr_scale;
+
+ // SSR main
+
+ enum ScreenSpaceReflectionMode {
+ SCREEN_SPACE_REFLECTION_NORMAL,
+ SCREEN_SPACE_REFLECTION_ROUGH,
+ SCREEN_SPACE_REFLECTION_MAX,
+ };
+
+ struct ScreenSpaceReflectionPushConstant {
+ float proj_info[4]; // 16 - 16
+
+ int32_t screen_size[2]; // 8 - 24
+ float camera_z_near; // 4 - 28
+ float camera_z_far; // 4 - 32
+
+ int32_t num_steps; // 4 - 36
+ float depth_tolerance; // 4 - 40
+ float distance_fade; // 4 - 44
+ float curve_fade_in; // 4 - 48
+
+ uint32_t orthogonal; // 4 - 52
+ float filter_mipmap_levels; // 4 - 56
+ uint32_t use_half_res; // 4 - 60
+ uint8_t metallic_mask[4]; // 4 - 64
+
+ uint32_t view_index; // 4 - 68
+ uint32_t pad[3]; // 12 - 80
+
+ // float projection[16]; // this is in our ScreenSpaceReflectionSceneData now
+ };
+
+ struct ScreenSpaceReflection {
+ ScreenSpaceReflectionShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX];
+
+ RID ubo;
+ } ssr;
+
+ // SSR Filter
+
+ struct ScreenSpaceReflectionFilterPushConstant {
+ float proj_info[4]; // 16 - 16
+
+ uint32_t orthogonal; // 4 - 20
+ float edge_tolerance; // 4 - 24
+ int32_t increment; // 4 - 28
+ uint32_t view_index; // 4 - 32
+
+ int32_t screen_size[2]; // 8 - 40
+ uint32_t vertical; // 4 - 44
+ uint32_t steps; // 4 - 48
+ };
+
+ enum SSRReflectionMode {
+ SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
+ SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
+ SCREEN_SPACE_REFLECTION_FILTER_MAX,
+ };
+
+ struct ScreenSpaceReflectionFilter {
+ ScreenSpaceReflectionFilterShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
+ } ssr_filter;
+};
+
+} // namespace RendererRD
+
+#endif // SS_EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index a90849dbeb..05db4a0cbe 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -149,4 +149,4 @@ public:
} // namespace RendererRD
-#endif // !TONE_MAPPER_RD_H
+#endif // TONE_MAPPER_RD_H
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 505a35a269..fa0b99fef9 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -95,7 +95,7 @@ void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, co
// TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
// TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
- // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistantly set when creating
+ // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
// our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
// of the VRS buffer to supply.
Size2i texel_size = Size2i(16, 16);
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
index 0f2bdd31b6..dd15df615e 100644
--- a/servers/rendering/renderer_rd/effects/vrs.h
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -72,4 +72,4 @@ public:
} // namespace RendererRD
-#endif // !VRS_RD_H
+#endif // VRS_RD_H
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index f731a0007a..8d59b24f3f 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -41,14 +41,6 @@ bool EffectsRD::get_prefer_raster_effects() {
return prefer_raster_effects;
}
-static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
-}
-
RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
if (image_to_uniform_set_cache.has(p_image)) {
RID uniform_set = image_to_uniform_set_cache[p_image];
@@ -86,7 +78,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
u.append_id(p_texture);
uniforms.push_back(u);
// anything with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, specular_merge.shader.version_get_shader(specular_merge.shader_version, 0), 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
@@ -116,105 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
return uniform_set;
}
-RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler) {
- TextureSamplerPair tsp;
- tsp.texture = p_texture;
- tsp.sampler = p_sampler;
-
- if (texture_sampler_to_compute_uniform_set_cache.has(tsp)) {
- RID uniform_set = texture_sampler_to_compute_uniform_set_cache[tsp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_sampler);
- u.append_id(p_texture);
- uniforms.push_back(u);
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0);
-
- texture_sampler_to_compute_uniform_set_cache[tsp] = uniform_set;
-
- return uniform_set;
-}
-
-RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) {
- TexturePair tp;
- tp.texture1 = p_texture1;
- tp.texture2 = p_texture2;
-
- if (texture_pair_to_compute_uniform_set_cache.has(tp)) {
- RID uniform_set = texture_pair_to_compute_uniform_set_cache[tp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture2);
- uniforms.push_back(u);
- }
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 1);
-
- texture_pair_to_compute_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
-RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) {
- TexturePair tp;
- tp.texture1 = p_texture1;
- tp.texture2 = p_texture2;
-
- if (image_pair_to_compute_uniform_set_cache.has(tp)) {
- RID uniform_set = image_pair_to_compute_uniform_set_cache[tp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_texture2);
- uniforms.push_back(u);
- }
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 3);
-
- image_pair_to_compute_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
@@ -281,126 +174,7 @@ void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- { //scale color and depth to half
- ssr_scale.push_constant.camera_z_far = p_camera.get_z_far();
- ssr_scale.push_constant.camera_z_near = p_camera.get_z_near();
- ssr_scale.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr_scale.push_constant.filter = false; //enabling causes arctifacts
- ssr_scale.push_constant.screen_size[0] = p_screen_size.x;
- ssr_scale.push_constant.screen_size[1] = p_screen_size.y;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
-
- {
- ssr.push_constant.camera_z_far = p_camera.get_z_far();
- ssr.push_constant.camera_z_near = p_camera.get_z_near();
- ssr.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr.push_constant.screen_size[0] = p_screen_size.x;
- ssr.push_constant.screen_size[1] = p_screen_size.y;
- ssr.push_constant.curve_fade_in = p_fade_in;
- ssr.push_constant.distance_fade = p_fade_out;
- ssr.push_constant.num_steps = p_max_steps;
- ssr.push_constant.depth_tolerance = p_tolerance;
- ssr.push_constant.use_half_res = true;
- ssr.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
- ssr.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
- ssr.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
- ssr.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
- ssr.push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
- store_camera(p_camera, ssr.push_constant.projection);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant));
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0);
-
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2);
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
- }
-
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- //blur
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- ssr_filter.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr_filter.push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
- ssr_filter.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
- ssr_filter.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
- ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
- ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
- ssr_filter.push_constant.vertical = 0;
- if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
- ssr_filter.push_constant.steps = p_max_steps / 3;
- ssr_filter.push_constant.increment = 3;
- } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
- ssr_filter.push_constant.steps = p_max_steps / 2;
- ssr_filter.push_constant.increment = 2;
- } else {
- ssr_filter.push_constant.steps = p_max_steps;
- ssr_filter.push_constant.increment = 1;
- }
-
- ssr_filter.push_constant.screen_size[0] = p_screen_size.width;
- ssr_filter.push_constant.screen_size[1] = p_screen_size.height;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_VERTICAL]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
-
- ssr_filter.push_constant.vertical = 1;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
+void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
@@ -443,36 +217,6 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept
}
}
-void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) {
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>());
-
- if (p_reflection.is_valid()) {
- if (p_base.is_valid()) {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
- } else {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- }
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_reflection), 1);
-
- } else {
- if (p_base.is_valid()) {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
- } else {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- }
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
- }
-
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
@@ -546,674 +290,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
}
}
-void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) {
- // Downsample and deinterleave the depth buffer for SSAO and SSIL
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- int downsample_pipeline = SS_EFFECTS_DOWNSAMPLE;
- bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
-
- if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_HALF;
- } else if (use_mips) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
- }
-
- bool use_half_size = false;
- bool use_full_mips = false;
-
- if (p_ssao_half_size && p_ssil_half_size) {
- downsample_pipeline++;
- use_half_size = true;
- } else if (p_ssao_half_size != p_ssil_half_size) {
- if (use_mips) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
- use_full_mips = true;
- } else {
- // Only need the first two mipmaps, but the cost to generate the next two is trivial
- // TODO investigate the benefit of a shader version to generate only 2 mips
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
- use_mips = true;
- }
- }
-
- int depth_index = use_half_size ? 1 : 0;
-
- RD::get_singleton()->draw_command_begin_label("Downsample Depth");
- if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_depth_mipmaps[depth_index + 1]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_depth_mipmaps[depth_index + 2]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.append_id(p_depth_mipmaps[depth_index + 3]);
- uniforms.push_back(u);
- }
- if (use_full_mips) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.append_id(p_depth_mipmaps[4]);
- uniforms.push_back(u);
- }
- ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
- }
-
- float depth_linearize_mul = -p_projection.matrix[3][2];
- float depth_linearize_add = p_projection.matrix[2][2];
- if (depth_linearize_mul * depth_linearize_add < 0) {
- depth_linearize_add = -depth_linearize_add;
- }
-
- ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
- ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
- ss_effects.downsample_push_constant.z_far = depth_linearize_add;
- if (ss_effects.downsample_push_constant.orthogonal) {
- ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
- ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
- }
- ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
- ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
- ss_effects.downsample_push_constant.radius_sq = 1.0;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[depth_index + 0]), 1);
- if (use_mips) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
-
- Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label();
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
-
- ss_effects.used_full_mips_last_frame = use_full_mips;
- ss_effects.used_half_size_last_frame = use_half_size;
-}
-
-void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
- ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
- ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
- ssao.gather_push_constant.pass = i;
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2);
- RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
-
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
- }
- RD::get_singleton()->compute_list_add_barrier(p_compute_list);
-}
-
-void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
- /* FIRST PASS */
-
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
- /* SECOND PASS */
- // Sample SSAO
- {
- RD::get_singleton()->draw_command_begin_label("Gather Samples");
- ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
- ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
-
- ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
- ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
- ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
- ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
- ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
- ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
-
- ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
- ssao.gather_push_constant.radius = p_settings.radius;
- float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
- radius_near_limit *= 1.50f;
-
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- ssao.gather_push_constant.radius *= 0.8f;
- }
- }
- radius_near_limit /= tan_half_fov_y;
- ssao.gather_push_constant.intensity = p_settings.intensity;
- ssao.gather_push_constant.shadow_power = p_settings.power;
- ssao.gather_push_constant.shadow_clamp = 0.98;
- ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
- ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
- ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
- ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
-
- ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
- ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
-
- ssao.gather_push_constant.detail_intensity = p_settings.detail;
- ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_depth_mipmaps_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ao_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_importance_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
- }
-
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
- RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
- ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- ssao.importance_map_push_constant.intensity = p_settings.intensity;
- ssao.importance_map_push_constant.power = p_settings.power;
- //base pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
- gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID());
- //generate importance map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- //process importance map A
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- //process Importance Map B
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
- RD::get_singleton()->draw_command_end_label(); // Importance Map
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
- }
-
- gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set);
- RD::get_singleton()->draw_command_end_label(); // Gather SSAO
- }
-
- // /* THIRD PASS */
- // // Blur
- //
- {
- RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
- ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
- ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
-
- int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
-
- for (int pass = 0; pass < blur_passes; pass++) {
- int blur_pipeline = SSAO_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
- if (pass < blur_passes - 2) {
- blur_pipeline = SSAO_BLUR_PASS_WIDE;
- } else {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
- if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ss_effects.mirror_sampler), 0);
- }
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1);
- } else {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
-
- Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- }
-
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- }
- RD::get_singleton()->draw_command_end_label(); // Blur
- }
-
- /* FOURTH PASS */
- // Interleave buffers
- // back to full size
- {
- RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
- ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
-
- int interleave_pipeline = SSAO_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) {
- interleave_pipeline = SSAO_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
- interleave_pipeline = SSAO_INTERLEAVE_SMART;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 0);
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Interleave
- }
- RD::get_singleton()->draw_command_end_label(); //SSAO
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
-
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
-}
-
-void EffectsRD::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
- ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
- ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
- ssil.gather_push_constant.pass = i;
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_compute_uniform_set_from_image_pair(p_ssil_slices[i], p_edges_slices[i]), 2);
- RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
-
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
- }
- RD::get_singleton()->compute_list_add_barrier(p_compute_list);
-}
-
-void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ssil, const Vector<RID> p_ssil_slices, RID p_ssil_pong, const Vector<RID> p_ssil_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set) {
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
- //Store projection info before starting the compute list
- SSILProjectionUniforms projection_uniforms;
- store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
-
- RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
-
- memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- {
- RD::get_singleton()->draw_command_begin_label("Gather Samples");
- ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
- ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
-
- ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
- ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
- ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
- ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
- ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
- ssil.gather_push_constant.z_near = p_projection.get_z_near();
- ssil.gather_push_constant.z_far = p_projection.get_z_far();
- ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
-
- ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
- ssil.gather_push_constant.radius = p_settings.radius;
- float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
- radius_near_limit *= 1.50f;
-
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- ssil.gather_push_constant.radius *= 0.8f;
- }
- }
- radius_near_limit /= tan_half_fov_y;
- ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
- ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
- ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
- ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
- ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
-
- ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
- ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
-
- ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_mipmap_sampler);
- u.append_id(p_diffuse);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 1;
- u.append_id(ssil.projection_uniform_buffer);
- uniforms.push_back(u);
- }
- r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_depth_mipmaps_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ssil_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_importance_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
- }
-
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
- RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
- ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
- //base pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
- gather_ssil(compute_list, p_ssil_pong_slices, p_edges_slices, p_settings, true, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
- //generate importance map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- // process Importance Map A
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- // process Importance Map B
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->draw_command_end_label(); // Importance Map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
- }
-
- gather_ssil(compute_list, p_ssil_slices, p_edges_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
- RD::get_singleton()->draw_command_end_label(); //Gather
- }
-
- {
- RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
- ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
- ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
-
- int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
-
- for (int pass = 0; pass < blur_passes; pass++) {
- int blur_pipeline = SSIL_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
- blur_pipeline = SSIL_BLUR_PASS_SMART;
- if (pass < blur_passes - 2) {
- blur_pipeline = SSIL_BLUR_PASS_WIDE;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
- if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_pong_slices[i]), 1);
- } else {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_pong_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_slices[i]), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges_slices[i]), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
-
- int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
- int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- }
- }
-
- RD::get_singleton()->draw_command_end_label(); // Blur
- }
-
- {
- RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
- ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
-
- int interleave_pipeline = SSIL_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
- interleave_pipeline = SSIL_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
- interleave_pipeline = SSIL_INTERLEAVE_SMART;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination), 0);
-
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Interleave
- }
-
- RD::get_singleton()->draw_command_end_label(); // SSIL
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
-
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
-}
-
void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
roughness_limiter.push_constant.screen_size[0] = p_size.x;
roughness_limiter.push_constant.screen_size[1] = p_size.y;
@@ -1304,7 +380,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
{
Vector<String> FSR_upscale_modes;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
#else
@@ -1358,154 +434,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
if (!prefer_raster_effects) {
- {
- // Initialize depth buffer for screen space effects
- Vector<String> downsampler_modes;
- downsampler_modes.push_back("\n");
- downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
- downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
-
- ss_effects.downsample_shader.initialize(downsampler_modes);
-
- ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
-
- for (int i = 0; i < SS_EFFECTS_MAX; i++) {
- ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
- }
-
- ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
- SSEffectsGatherConstants gather_constants;
-
- const int sub_pass_count = 5;
- for (int pass = 0; pass < 4; pass++) {
- for (int subPass = 0; subPass < sub_pass_count; subPass++) {
- int a = pass;
- int b = subPass;
-
- int spmap[5]{ 0, 1, 4, 3, 2 };
- b = spmap[subPass];
-
- float ca, sa;
- float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
-
- ca = Math::cos(angle0);
- sa = Math::sin(angle0);
-
- float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
-
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
- }
- }
-
- RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
- }
-
- {
- // Initialize ssao
-
- RD::SamplerState sampler;
- sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.max_lod = 4;
-
- ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
-
- uint32_t pipeline = 0;
- {
- Vector<String> ssao_modes;
-
- ssao_modes.push_back("\n");
- ssao_modes.push_back("\n#define SSAO_BASE\n");
- ssao_modes.push_back("\n#define ADAPTIVE\n");
-
- ssao.gather_shader.initialize(ssao_modes);
-
- ssao.gather_shader_version = ssao.gather_shader.version_create();
-
- for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
- pipeline++;
- }
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define GENERATE_MAP\n");
- ssao_modes.push_back("\n#define PROCESS_MAPA\n");
- ssao_modes.push_back("\n#define PROCESS_MAPB\n");
-
- ssao.importance_map_shader.initialize(ssao_modes);
-
- ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
-
- for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
-
- pipeline++;
- }
- ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_WIDE\n");
-
- ssao.blur_shader.initialize(ssao_modes);
-
- ssao.blur_shader_version = ssao.blur_shader.version_create();
-
- for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
-
- pipeline++;
- }
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_HALF\n");
-
- ssao.interleave_shader.initialize(ssao_modes);
-
- ssao.interleave_shader_version = ssao.interleave_shader.version_create();
- for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
- RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
- pipeline++;
- }
- }
-
- ERR_FAIL_COND(pipeline != SSAO_MAX);
- }
- }
-
- if (!prefer_raster_effects) {
// Initialize roughness limiter
Vector<String> shader_modes;
shader_modes.push_back("");
@@ -1518,81 +446,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
if (!prefer_raster_effects) {
- Vector<String> specular_modes;
- specular_modes.push_back("\n#define MODE_MERGE\n");
- specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n");
- specular_modes.push_back("\n");
- specular_modes.push_back("\n#define MODE_SSR\n");
-
- specular_merge.shader.initialize(specular_modes);
-
- specular_merge.shader_version = specular_merge.shader.version_create();
-
- //use additive
-
- RD::PipelineColorBlendState::Attachment ba;
- ba.enable_blend = true;
- ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.color_blend_op = RD::BLEND_OP_ADD;
- ba.alpha_blend_op = RD::BLEND_OP_ADD;
-
- RD::PipelineColorBlendState blend_additive;
- blend_additive.attachments.push_back(ba);
-
- for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
- RD::PipelineColorBlendState blend_state;
- if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR) {
- blend_state = blend_additive;
- } else {
- blend_state = RD::PipelineColorBlendState::create_disabled();
- }
- specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- }
-
- if (!prefer_raster_effects) {
- {
- Vector<String> ssr_modes;
- ssr_modes.push_back("\n");
- ssr_modes.push_back("\n#define MODE_ROUGH\n");
-
- ssr.shader.initialize(ssr_modes);
-
- ssr.shader_version = ssr.shader.version_create();
-
- for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
- ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i));
- }
- }
-
- {
- Vector<String> ssr_filter_modes;
- ssr_filter_modes.push_back("\n");
- ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n");
-
- ssr_filter.shader.initialize(ssr_filter_modes);
-
- ssr_filter.shader_version = ssr_filter.shader.version_create();
-
- for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
- ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i));
- }
- }
-
- {
- Vector<String> ssr_scale_modes;
- ssr_scale_modes.push_back("\n");
-
- ssr_scale.shader.initialize(ssr_scale_modes);
-
- ssr_scale.shader_version = ssr_scale.shader.version_create();
-
- ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0));
- }
-
{
Vector<String> sss_modes;
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
@@ -1607,79 +460,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
}
}
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n");
- ssil_modes.push_back("\n#define SSIL_BASE\n");
- ssil_modes.push_back("\n#define ADAPTIVE\n");
-
- ssil.gather_shader.initialize(ssil_modes);
-
- ssil.gather_shader_version = ssil.gather_shader.version_create();
-
- for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
- }
- ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define GENERATE_MAP\n");
- ssil_modes.push_back("\n#define PROCESS_MAPA\n");
- ssil_modes.push_back("\n#define PROCESS_MAPB\n");
-
- ssil.importance_map_shader.initialize(ssil_modes);
-
- ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
-
- for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
- }
- ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define MODE_NON_SMART\n");
- ssil_modes.push_back("\n#define MODE_SMART\n");
- ssil_modes.push_back("\n#define MODE_WIDE\n");
-
- ssil.blur_shader.initialize(ssil_modes);
-
- ssil.blur_shader_version = ssil.blur_shader.version_create();
- for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
- }
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define MODE_NON_SMART\n");
- ssil_modes.push_back("\n#define MODE_SMART\n");
- ssil_modes.push_back("\n#define MODE_HALF\n");
-
- ssil.interleave_shader.initialize(ssil_modes);
-
- ssil.interleave_shader_version = ssil.interleave_shader.version_create();
- for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
- }
- }
}
{
@@ -1751,27 +531,8 @@ EffectsRD::~EffectsRD() {
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
}
if (!prefer_raster_effects) {
- specular_merge.shader.version_free(specular_merge.shader_version);
- ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
- ssao.blur_shader.version_free(ssao.blur_shader_version);
- ssao.gather_shader.version_free(ssao.gather_shader_version);
- ssao.interleave_shader.version_free(ssao.interleave_shader_version);
- ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
- ssil.blur_shader.version_free(ssil.blur_shader_version);
- ssil.gather_shader.version_free(ssil.gather_shader_version);
- ssil.interleave_shader.version_free(ssil.interleave_shader_version);
- ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
- ssr.shader.version_free(ssr.shader_version);
- ssr_filter.shader.version_free(ssr_filter.shader_version);
- ssr_scale.shader.version_free(ssr_scale.shader_version);
sss.shader.version_free(sss.shader_version);
-
- RD::get_singleton()->free(ss_effects.mirror_sampler);
- RD::get_singleton()->free(ss_effects.gather_constants_buffer);
- RD::get_singleton()->free(ssao.importance_map_load_counter);
- RD::get_singleton()->free(ssil.importance_map_load_counter);
- RD::get_singleton()->free(ssil.projection_uniform_buffer);
}
sort.shader.version_free(sort.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 76627a8d7d..94cd26fae9 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -31,26 +31,13 @@
#ifndef EFFECTS_RD_H
#define EFFECTS_RD_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -142,231 +129,6 @@ private:
PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
} luminance_reduce_raster;
- struct SSEffectsDownsamplePushConstant {
- float pixel_size[2];
- float z_far;
- float z_near;
- uint32_t orthogonal;
- float radius_sq;
- uint32_t pad[2];
- };
-
- enum SSEffectsMode {
- SS_EFFECTS_DOWNSAMPLE,
- SS_EFFECTS_DOWNSAMPLE_HALF_RES,
- SS_EFFECTS_DOWNSAMPLE_MIPMAP,
- SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
- SS_EFFECTS_DOWNSAMPLE_HALF,
- SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
- SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
- SS_EFFECTS_MAX
- };
-
- struct SSEffectsGatherConstants {
- float rotation_matrices[80]; //5 vec4s * 4
- };
-
- struct SSEffects {
- SSEffectsDownsamplePushConstant downsample_push_constant;
- SsEffectsDownsampleShaderRD downsample_shader;
- RID downsample_shader_version;
- RID downsample_uniform_set;
- bool used_half_size_last_frame = false;
- bool used_mips_last_frame = false;
- bool used_full_mips_last_frame = false;
-
- RID gather_constants_buffer;
-
- RID mirror_sampler;
-
- RID pipelines[SS_EFFECTS_MAX];
- } ss_effects;
-
- enum SSAOMode {
- SSAO_GATHER,
- SSAO_GATHER_BASE,
- SSAO_GATHER_ADAPTIVE,
- SSAO_GENERATE_IMPORTANCE_MAP,
- SSAO_PROCESS_IMPORTANCE_MAPA,
- SSAO_PROCESS_IMPORTANCE_MAPB,
- SSAO_BLUR_PASS,
- SSAO_BLUR_PASS_SMART,
- SSAO_BLUR_PASS_WIDE,
- SSAO_INTERLEAVE,
- SSAO_INTERLEAVE_SMART,
- SSAO_INTERLEAVE_HALF,
- SSAO_MAX
- };
-
- struct SSAOGatherPushConstant {
- int32_t screen_size[2];
- int pass;
- int quality;
-
- float half_screen_pixel_size[2];
- int size_multiplier;
- float detail_intensity;
-
- float NDC_to_view_mul[2];
- float NDC_to_view_add[2];
-
- float pad[2];
- float half_screen_pixel_size_x025[2];
-
- float radius;
- float intensity;
- float shadow_power;
- float shadow_clamp;
-
- float fade_out_mul;
- float fade_out_add;
- float horizon_angle_threshold;
- float inv_radius_near_limit;
-
- uint32_t is_orthogonal;
- float neg_inv_radius;
- float load_counter_avg_div;
- float adaptive_sample_limit;
-
- int32_t pass_coord_offset[2];
- float pass_uv_offset[2];
- };
-
- struct SSAOImportanceMapPushConstant {
- float half_screen_pixel_size[2];
- float intensity;
- float power;
- };
-
- struct SSAOBlurPushConstant {
- float edge_sharpness;
- float pad;
- float half_screen_pixel_size[2];
- };
-
- struct SSAOInterleavePushConstant {
- float inv_sharpness;
- uint32_t size_modifier;
- float pixel_size[2];
- };
-
- struct SSAO {
- SSAOGatherPushConstant gather_push_constant;
- SsaoShaderRD gather_shader;
- RID gather_shader_version;
-
- SSAOImportanceMapPushConstant importance_map_push_constant;
- SsaoImportanceMapShaderRD importance_map_shader;
- RID importance_map_shader_version;
- RID importance_map_load_counter;
- RID counter_uniform_set;
-
- SSAOBlurPushConstant blur_push_constant;
- SsaoBlurShaderRD blur_shader;
- RID blur_shader_version;
-
- SSAOInterleavePushConstant interleave_push_constant;
- SsaoInterleaveShaderRD interleave_shader;
- RID interleave_shader_version;
-
- RID pipelines[SSAO_MAX];
- } ssao;
-
- enum SSILMode {
- SSIL_GATHER,
- SSIL_GATHER_BASE,
- SSIL_GATHER_ADAPTIVE,
- SSIL_GENERATE_IMPORTANCE_MAP,
- SSIL_PROCESS_IMPORTANCE_MAPA,
- SSIL_PROCESS_IMPORTANCE_MAPB,
- SSIL_BLUR_PASS,
- SSIL_BLUR_PASS_SMART,
- SSIL_BLUR_PASS_WIDE,
- SSIL_INTERLEAVE,
- SSIL_INTERLEAVE_SMART,
- SSIL_INTERLEAVE_HALF,
- SSIL_MAX
- };
-
- struct SSILGatherPushConstant {
- int32_t screen_size[2];
- int pass;
- int quality;
-
- float half_screen_pixel_size[2];
- float half_screen_pixel_size_x025[2];
-
- float NDC_to_view_mul[2];
- float NDC_to_view_add[2];
-
- float pad2[2];
- float z_near;
- float z_far;
-
- float radius;
- float intensity;
- int size_multiplier;
- int pad;
-
- float fade_out_mul;
- float fade_out_add;
- float normal_rejection_amount;
- float inv_radius_near_limit;
-
- uint32_t is_orthogonal;
- float neg_inv_radius;
- float load_counter_avg_div;
- float adaptive_sample_limit;
-
- int32_t pass_coord_offset[2];
- float pass_uv_offset[2];
- };
-
- struct SSILImportanceMapPushConstant {
- float half_screen_pixel_size[2];
- float intensity;
- float pad;
- };
-
- struct SSILBlurPushConstant {
- float edge_sharpness;
- float pad;
- float half_screen_pixel_size[2];
- };
-
- struct SSILInterleavePushConstant {
- float inv_sharpness;
- uint32_t size_modifier;
- float pixel_size[2];
- };
-
- struct SSILProjectionUniforms {
- float inv_last_frame_projection_matrix[16];
- };
-
- struct SSIL {
- SSILGatherPushConstant gather_push_constant;
- SsilShaderRD gather_shader;
- RID gather_shader_version;
- RID projection_uniform_buffer;
-
- SSILImportanceMapPushConstant importance_map_push_constant;
- SsilImportanceMapShaderRD importance_map_shader;
- RID importance_map_shader_version;
- RID importance_map_load_counter;
- RID counter_uniform_set;
-
- SSILBlurPushConstant blur_push_constant;
- SsilBlurShaderRD blur_shader;
- RID blur_shader_version;
-
- SSILInterleavePushConstant interleave_push_constant;
- SsilInterleaveShaderRD interleave_shader;
- RID interleave_shader_version;
-
- RID pipelines[SSIL_MAX];
- } ssil;
-
struct RoughnessLimiterPushConstant {
int32_t screen_size[2];
float curve;
@@ -381,101 +143,6 @@ private:
} roughness_limiter;
- enum SpecularMergeMode {
- SPECULAR_MERGE_ADD,
- SPECULAR_MERGE_SSR,
- SPECULAR_MERGE_ADDITIVE_ADD,
- SPECULAR_MERGE_ADDITIVE_SSR,
- SPECULAR_MERGE_MAX
- };
-
- /* Specular merge must be done using raster, rather than compute
- * because it must continue the existing color buffer
- */
-
- struct SpecularMerge {
- SpecularMergeShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[SPECULAR_MERGE_MAX];
-
- } specular_merge;
-
- enum ScreenSpaceReflectionMode {
- SCREEN_SPACE_REFLECTION_NORMAL,
- SCREEN_SPACE_REFLECTION_ROUGH,
- SCREEN_SPACE_REFLECTION_MAX,
- };
-
- struct ScreenSpaceReflectionPushConstant {
- float proj_info[4];
-
- int32_t screen_size[2];
- float camera_z_near;
- float camera_z_far;
-
- int32_t num_steps;
- float depth_tolerance;
- float distance_fade;
- float curve_fade_in;
-
- uint32_t orthogonal;
- float filter_mipmap_levels;
- uint32_t use_half_res;
- uint8_t metallic_mask[4];
-
- float projection[16];
- };
-
- struct ScreenSpaceReflection {
- ScreenSpaceReflectionPushConstant push_constant;
- ScreenSpaceReflectionShaderRD shader;
- RID shader_version;
- RID pipelines[SCREEN_SPACE_REFLECTION_MAX];
-
- } ssr;
-
- struct ScreenSpaceReflectionFilterPushConstant {
- float proj_info[4];
-
- uint32_t orthogonal;
- float edge_tolerance;
- int32_t increment;
- uint32_t pad;
-
- int32_t screen_size[2];
- uint32_t vertical;
- uint32_t steps;
- };
- enum {
- SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
- SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
- SCREEN_SPACE_REFLECTION_FILTER_MAX,
- };
-
- struct ScreenSpaceReflectionFilter {
- ScreenSpaceReflectionFilterPushConstant push_constant;
- ScreenSpaceReflectionFilterShaderRD shader;
- RID shader_version;
- RID pipelines[SCREEN_SPACE_REFLECTION_FILTER_MAX];
- } ssr_filter;
-
- struct ScreenSpaceReflectionScalePushConstant {
- int32_t screen_size[2];
- float camera_z_near;
- float camera_z_far;
-
- uint32_t orthogonal;
- uint32_t filter;
- uint32_t pad[2];
- };
-
- struct ScreenSpaceReflectionScale {
- ScreenSpaceReflectionScalePushConstant push_constant;
- ScreenSpaceReflectionScaleShaderRD shader;
- RID shader_version;
- RID pipeline;
- } ssr_scale;
-
struct SubSurfaceScatteringPushConstant {
int32_t screen_size[2];
float camera_z_far;
@@ -559,9 +226,6 @@ private:
RID _get_uniform_set_from_image(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
- RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
- RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
- RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
public:
bool get_prefer_raster_effects();
@@ -572,57 +236,9 @@ public:
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- struct SSAOSettings {
- float radius = 1.0;
- float intensity = 2.0;
- float power = 1.5;
- float detail = 0.5;
- float horizon = 0.06;
- float sharpness = 0.98;
-
- RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM;
- bool half_size = false;
- float adaptive_target = 0.5;
- int blur_passes = 2;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
- Size2i half_screen_size = Size2i();
- Size2i quarter_screen_size = Size2i();
- };
-
- struct SSILSettings {
- float radius = 1.0;
- float intensity = 2.0;
- float sharpness = 0.98;
- float normal_rejection = 1.0;
-
- RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
- bool half_size = true;
- float adaptive_target = 0.5;
- int blur_passes = 4;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
- Size2i half_screen_size = Size2i();
- Size2i quarter_screen_size = Size2i();
- };
-
- void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
-
- void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
- void generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
-
- void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
- void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set);
-
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
- void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
- void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
- void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
+ void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
void sort_buffer(RID p_uniform_set, int p_size);
@@ -630,4 +246,4 @@ public:
~EffectsRD();
};
-#endif // !RASTERIZER_EFFECTS_RD_H
+#endif // EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 2a6c96480e..987c1dbb52 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -30,6 +30,11 @@
#include "fog.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/rendering_server_default.h"
+
using namespace RendererRD;
Fog *Fog::singleton = nullptr;
@@ -126,3 +131,1074 @@ Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const {
ERR_FAIL_COND_V(!fog_volume, Vector3());
return fog_volume->extents;
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Fog material
+
+bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ uniform_set_updated = true;
+
+ 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, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+}
+
+Fog::FogMaterialData::~FogMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+RendererRD::ShaderData *Fog::_create_fog_shader_func() {
+ FogShaderData *shader_data = memnew(FogShaderData);
+ return shader_data;
+}
+
+RendererRD::ShaderData *Fog::_create_fog_shader_funcs() {
+ return Fog::get_singleton()->_create_fog_shader_func();
+};
+
+RendererRD::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) {
+ FogMaterialData *material_data = memnew(FogMaterialData);
+ material_data->shader_data = p_shader;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RendererRD::MaterialData *Fog::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
+ return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// FOG VOLUMES INSTANCE
+
+RID Fog::fog_volume_instance_create(RID p_fog_volume) {
+ FogVolumeInstance fvi;
+ fvi.volume = p_fog_volume;
+ return fog_volume_instance_owner.make_rid(fvi);
+}
+
+void Fog::fog_instance_free(RID p_rid) {
+ fog_volume_instance_owner.free(p_rid);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog Shader
+
+void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ {
+ // Initialize local fog shader
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("");
+ volumetric_fog.shader.initialize(volumetric_fog_modes);
+
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
+ }
+
+ {
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["TIME"] = "scene_params.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["WORLD_POSITION"] = "world.xyz";
+ actions.renames["OBJECT_POSITION"] = "params.position";
+ actions.renames["UVW"] = "uvw";
+ actions.renames["EXTENTS"] = "params.extents";
+ actions.renames["ALBEDO"] = "albedo";
+ actions.renames["DENSITY"] = "density";
+ actions.renames["EMISSION"] = "emission";
+ actions.renames["SDF"] = "sdf";
+
+ actions.usage_defines["SDF"] = "#define SDF_USED\n";
+ actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
+ actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
+ actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
+ actions.base_uniform_string = "material.";
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ volumetric_fog.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for fog shader
+ volumetric_fog.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(volumetric_fog.default_shader);
+ material_storage->shader_set_code(volumetric_fog.default_shader, R"(
+// Default fog shader.
+
+shader_type fog;
+
+void fog() {
+DENSITY = 1.0;
+ALBEDO = vec3(1.0);
+}
+)");
+ volumetric_fog.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(volumetric_fog.default_material);
+ material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+
+ FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG));
+ volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ }
+ {
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(p_max_directional_lights) + "\n";
+ defines += "\n#define MAX_SKY_LOD " + itos(p_roughness_layers - 1) + ".0\n";
+ if (p_is_using_radiance_cubemap_array) {
+ defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
+ }
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
+ volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
+
+ volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
+ volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
+ for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
+ volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
+ }
+ volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
+ }
+}
+
+void Fog::free_fog_shader() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
+ RD::get_singleton()->free(volumetric_fog.volume_ubo);
+ RD::get_singleton()->free(volumetric_fog.params_ubo);
+ material_storage->shader_free(volumetric_fog.default_shader);
+ material_storage->material_free(volumetric_fog.default_material);
+}
+
+void Fog::FogShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void Fog::FogShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
+
+ uses_time = false;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+
+ actions.uniforms = &uniforms;
+
+ Fog *fog_singleton = Fog::get_singleton();
+
+ Error err = fog_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
+
+ if (version.is_null()) {
+ version = fog_singleton->volumetric_fog.shader.version_create();
+ }
+
+ fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!fog_singleton->volumetric_fog.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void Fog::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ RBMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ String last_group;
+ for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool Fog::FogShaderData::is_animated() const {
+ return false;
+}
+
+bool Fog::FogShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const {
+ Fog *fog_singleton = Fog::get_singleton();
+
+ return fog_singleton->volumetric_fog.shader.version_get_native_source_code(version);
+}
+
+Fog::FogShaderData::~FogShaderData() {
+ Fog *fog_singleton = Fog::get_singleton();
+ ERR_FAIL_COND(!fog_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ fog_singleton->volumetric_fog.shader.version_free(version);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog
+
+Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) {
+ width = fog_size.x;
+ height = fog_size.y;
+ depth = fog_size.z;
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = fog_size.x;
+ tf.height = fog_size.y;
+ tf.depth = fog_size.z;
+ tf.texture_type = RD::TEXTURE_TYPE_3D;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(light_density_map, "Fog light-density map");
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+ prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(prev_light_density_map, "Fog previous light-density map");
+ RD::get_singleton()->texture_clear(prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ 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)
+ Vector<uint8_t> dm;
+ dm.resize(fog_size.x * fog_size.y * fog_size.z * 4);
+ dm.fill(0);
+
+ density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(density_map, "Fog density map");
+ light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(light_map, "Fog light map");
+ emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map");
+#else
+ tf.format = RD::DATA_FORMAT_R32_UINT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(density_map, "Fog density map");
+ RD::get_singleton()->texture_clear(density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(light_map, "Fog light map");
+ RD::get_singleton()->texture_clear(light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map");
+ RD::get_singleton()->texture_clear(emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+#endif
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.append_id(fog_map);
+ uniforms.push_back(u);
+ }
+
+ sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_sky_shader, RendererRD::SkyRD::SKY_SET_FOG);
+}
+
+Fog::VolumetricFog::~VolumetricFog() {
+ RD::get_singleton()->free(prev_light_density_map);
+ RD::get_singleton()->free(light_density_map);
+ RD::get_singleton()->free(fog_map);
+ RD::get_singleton()->free(density_map);
+ RD::get_singleton()->free(light_map);
+ RD::get_singleton()->free(emissive_map);
+
+ if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) {
+ RD::get_singleton()->free(fog_uniform_set);
+ }
+ if (process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density)) {
+ RD::get_singleton()->free(process_uniform_set_density);
+ }
+ if (process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set)) {
+ RD::get_singleton()->free(process_uniform_set);
+ }
+ if (process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set2)) {
+ RD::get_singleton()->free(process_uniform_set2);
+ }
+ if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) {
+ RD::get_singleton()->free(sdfgi_uniform_set);
+ }
+ if (sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_uniform_set)) {
+ RD::get_singleton()->free(sky_uniform_set);
+ }
+}
+
+Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
+ Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
+ view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
+ Vector3 fog_position = Vector3(0, 0, 0);
+
+ view_position.y = -view_position.y;
+ fog_position.z = -view_position.z / fog_end;
+ fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
+ fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
+ fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
+ fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
+
+ fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
+ fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
+ fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
+
+ return Vector3i(fog_position);
+}
+
+void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ RENDER_TIMESTAMP("> Volumetric Fog");
+ RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
+
+ if (p_fog_volumes.size() > 0) {
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
+
+ RENDER_TIMESTAMP("Render FogVolumes");
+
+ VolumetricFogShader::VolumeUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = p_settings.env->volumetric_fog_length;
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.fog_frustum_end = fog_end;
+ params.z_near = z_near;
+ params.z_far = z_far;
+ params.time = p_settings.time;
+
+ params.fog_volume_size[0] = p_settings.vfog->width;
+ params.fog_volume_size[1] = p_settings.vfog->height;
+ params.fog_volume_size[2] = p_settings.vfog->depth;
+
+ params.use_temporal_reprojection = p_settings.env->volumetric_fog_temporal_reprojection;
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+ params.detail_spread = p_settings.env->volumetric_fog_detail_spread;
+ params.temporal_blend = p_settings.env->volumetric_fog_temporal_reprojection_amount;
+
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
+ RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform);
+
+ RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 1;
+ u.append_id(p_settings.vfog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(volumetric_fog.volume_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 3;
+ u.append_id(p_settings.vfog->density_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 4;
+ u.append_id(p_settings.vfog->light_map);
+ uniforms.push_back(u);
+ }
+
+ p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ bool any_uses_time = false;
+
+ 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]);
+ ERR_FAIL_COND(!fog_volume_instance);
+ RID fog_volume = fog_volume_instance->volume;
+
+ RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume);
+
+ FogMaterialData *material = nullptr;
+
+ if (fog_material.is_valid()) {
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ fog_material = volumetric_fog.default_material;
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
+ }
+
+ ERR_FAIL_COND(!material);
+
+ FogShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ any_uses_time |= shader_data->uses_time;
+
+ Vector3i min = Vector3i();
+ Vector3i max = Vector3i();
+ Vector3i kernel_size = Vector3i();
+
+ Vector3 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_extents(fog_volume);
+
+ if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
+ // Local fog volume.
+ Vector3i points[8];
+ Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ 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, p_settings.env->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, p_settings.env->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, p_settings.env->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, p_settings.env->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, p_settings.env->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, p_settings.env->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, p_settings.env->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, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform);
+
+ min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1);
+ max = Vector3i(1, 1, 1);
+
+ for (int j = 0; j < 8; j++) {
+ min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
+ max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
+ }
+
+ kernel_size = max - min;
+ } else {
+ // Volume type global runs on all cells
+ extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ min = Vector3i(0, 0, 0);
+ kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth));
+ }
+
+ if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
+ continue;
+ }
+
+ VolumetricFogShader::FogPushConstant push_constant;
+ push_constant.position[0] = position.x;
+ push_constant.position[1] = position.y;
+ push_constant.position[2] = position.z;
+ push_constant.extents[0] = extents.x;
+ push_constant.extents[1] = extents.y;
+ push_constant.extents[2] = extents.z;
+ push_constant.corner[0] = min.x;
+ push_constant.corner[1] = min.y;
+ push_constant.corner[2] = 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);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+ }
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
+ }
+ if (any_uses_time || p_settings.env->volumetric_fog_temporal_reprojection) {
+ RenderingServerDefault::redraw_request();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) {
+ //re create uniform set if needed
+ Vector<RD::Uniform> uniforms;
+ Vector<RD::Uniform> copy_uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ if (p_settings.shadow_atlas_depth.is_null()) {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
+ } else {
+ u.append_id(p_settings.shadow_atlas_depth);
+ }
+
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ if (p_settings.directional_shadow_depth.is_valid()) {
+ u.append_id(p_settings.directional_shadow_depth);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
+ }
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ u.append_id(p_settings.omni_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 4;
+ u.append_id(p_settings.spot_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 5;
+ u.append_id(p_settings.directional_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 6;
+ u.append_id(p_settings.cluster_builder->get_cluster_buffer());
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 7;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 8;
+ u.append_id(p_settings.vfog->light_density_map);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(p_settings.vfog->fog_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(p_settings.vfog->prev_light_density_map);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 10;
+ u.append_id(p_settings.shadow_sampler);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 11;
+ u.append_id(p_settings.voxel_gl_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 12;
+ for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) {
+ u.append_id(p_settings.rbgi->voxel_gi_textures[i]);
+ }
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 13;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 14;
+ u.append_id(volumetric_fog.params_ubo);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 15;
+ u.append_id(p_settings.vfog->prev_light_density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 16;
+ u.append_id(p_settings.vfog->density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 17;
+ u.append_id(p_settings.vfog->light_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 18;
+ u.append_id(p_settings.vfog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 19;
+ RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID sky_texture = p_settings.env->sky.is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(p_settings.env->sky) : RID();
+ u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
+ uniforms.push_back(u);
+ }
+
+ p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
+
+ p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+
+ RID aux7 = uniforms.write[7].get_id(0);
+ RID aux8 = uniforms.write[8].get_id(0);
+
+ uniforms.write[7].set_id(0, aux8);
+ uniforms.write[8].set_id(0, aux7);
+
+ p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+
+ uniforms.remove_at(8);
+ uniforms.write[7].set_id(0, aux7);
+ p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
+ }
+
+ bool using_sdfgi = p_settings.env->volumetric_fog_gi_inject > 0.0001 && p_settings.env->sdfgi_enabled && (p_settings.sdfgi != nullptr);
+
+ if (using_sdfgi) {
+ if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.append_id(p_settings.gi->sdfgi_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ u.append_id(p_settings.sdfgi->ambient_texture);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ u.append_id(p_settings.sdfgi->occlusion_texture);
+ uniforms.push_back(u);
+ }
+
+ p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
+ }
+ }
+
+ p_settings.vfog->length = p_settings.env->volumetric_fog_length;
+ p_settings.vfog->spread = p_settings.env->volumetric_fog_detail_spread;
+
+ VolumetricFogShader::ParamsUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = p_settings.env->volumetric_fog_length;
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.ambient_inject = p_settings.env->volumetric_fog_ambient_inject * p_settings.env->ambient_light_energy;
+ params.z_far = z_far;
+
+ params.fog_frustum_end = fog_end;
+
+ Color ambient_color = p_settings.env->ambient_light.srgb_to_linear();
+ params.ambient_color[0] = ambient_color.r;
+ params.ambient_color[1] = ambient_color.g;
+ params.ambient_color[2] = ambient_color.b;
+ params.sky_contribution = p_settings.env->ambient_sky_contribution;
+
+ params.fog_volume_size[0] = p_settings.vfog->width;
+ params.fog_volume_size[1] = p_settings.vfog->height;
+ params.fog_volume_size[2] = p_settings.vfog->depth;
+
+ params.directional_light_count = p_directional_light_count;
+
+ Color emission = p_settings.env->volumetric_fog_emission.srgb_to_linear();
+ params.base_emission[0] = emission.r * p_settings.env->volumetric_fog_emission_energy;
+ params.base_emission[1] = emission.g * p_settings.env->volumetric_fog_emission_energy;
+ params.base_emission[2] = emission.b * p_settings.env->volumetric_fog_emission_energy;
+ params.base_density = p_settings.env->volumetric_fog_density;
+
+ Color base_scattering = p_settings.env->volumetric_fog_scattering.srgb_to_linear();
+ params.base_scattering[0] = base_scattering.r;
+ params.base_scattering[1] = base_scattering.g;
+ params.base_scattering[2] = base_scattering.b;
+ params.phase_g = p_settings.env->volumetric_fog_anisotropy;
+
+ params.detail_spread = p_settings.env->volumetric_fog_detail_spread;
+ params.gi_inject = p_settings.env->volumetric_fog_gi_inject;
+
+ params.cam_rotation[0] = p_cam_transform.basis[0][0];
+ params.cam_rotation[1] = p_cam_transform.basis[1][0];
+ params.cam_rotation[2] = p_cam_transform.basis[2][0];
+ params.cam_rotation[3] = 0;
+ params.cam_rotation[4] = p_cam_transform.basis[0][1];
+ params.cam_rotation[5] = p_cam_transform.basis[1][1];
+ params.cam_rotation[6] = p_cam_transform.basis[2][1];
+ params.cam_rotation[7] = 0;
+ params.cam_rotation[8] = p_cam_transform.basis[0][2];
+ params.cam_rotation[9] = p_cam_transform.basis[1][2];
+ params.cam_rotation[10] = p_cam_transform.basis[2][2];
+ params.cam_rotation[11] = 0;
+ params.filter_axis = 0;
+ params.max_voxel_gi_instances = p_settings.env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0;
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
+
+ params.use_temporal_reprojection = p_settings.env->volumetric_fog_temporal_reprojection;
+ params.temporal_blend = p_settings.env->volumetric_fog_temporal_reprojection_amount;
+
+ {
+ uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size();
+ params.cluster_shift = get_shift_from_power_of_2(cluster_size);
+
+ uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1;
+ uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1;
+ params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32;
+ params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
+ params.cluster_width = cluster_screen_width;
+
+ params.screen_size[0] = p_settings.rb_size.x;
+ params.screen_size[1] = p_settings.rb_size.y;
+ }
+
+ Basis sky_transform = p_settings.env->sky_orientation;
+ sky_transform = sky_transform.inverse() * p_cam_transform.basis;
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
+
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
+
+ RENDER_TIMESTAMP("Render Fog");
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0);
+
+ if (using_sdfgi) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // Copy fog to history buffer
+ if (p_settings.env->volumetric_fog_temporal_reprojection) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ RD::get_singleton()->draw_command_end_label();
+
+ if (p_settings.volumetric_fog_filter_active) {
+ RD::get_singleton()->draw_command_begin_label("Filter Fog");
+
+ RENDER_TIMESTAMP("Filter Fog");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+
+ RD::get_singleton()->compute_list_end();
+ //need restart for buffer update
+
+ params.filter_axis = 1;
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
+
+ compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RENDER_TIMESTAMP("Integrate Fog");
+ RD::get_singleton()->draw_command_begin_label("Integrate Fog");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1);
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
+
+ RENDER_TIMESTAMP("< Volumetric Fog");
+ RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
index 55a01c3616..61a5d80d20 100644
--- a/servers/rendering/renderer_rd/environment/fog.h
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -34,12 +34,19 @@
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/environment/renderer_fog.h"
+#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/environment/gi.h"
+#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
+#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
class Fog : public RendererFog {
public:
+ /* FOG VOLUMES */
+
struct FogVolume {
RID material;
Vector3 extents = Vector3(1, 1, 1);
@@ -49,10 +56,179 @@ public:
Dependency dependency;
};
+ struct FogVolumeInstance {
+ RID volume;
+ Transform3D transform;
+ bool active = false;
+ };
+
private:
static Fog *singleton;
mutable RID_Owner<FogVolume, true> fog_volume_owner;
+ mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
+
+ /* Volumetric Fog */
+ struct VolumetricFogShader {
+ enum FogSet {
+ FOG_SET_BASE,
+ FOG_SET_UNIFORMS,
+ FOG_SET_MATERIAL,
+ FOG_SET_MAX,
+ };
+
+ struct FogPushConstant {
+ float position[3];
+ float pad;
+
+ float extents[3];
+ float pad2;
+
+ int32_t corner[3];
+ uint32_t shape;
+
+ float transform[16];
+ };
+
+ struct VolumeUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float z_near;
+ float z_far;
+ float time;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float detail_spread;
+ float temporal_blend;
+
+ float to_prev_view[16];
+ float transform[16];
+ };
+
+ ShaderCompiler compiler;
+ VolumetricFogShaderRD shader;
+ RID volume_ubo;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ RID params_ubo;
+
+ enum {
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
+ VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
+ };
+
+ struct ParamsUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
+ uint32_t filter_axis;
+
+ float ambient_color[3];
+ float sky_contribution;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ float base_emission[3];
+ float base_density;
+
+ float base_scattering[3];
+ float phase_g;
+
+ float detail_spread;
+ float gi_inject;
+ uint32_t max_voxel_gi_instances;
+ uint32_t cluster_type_size;
+
+ float screen_size[2];
+ uint32_t cluster_shift;
+ uint32_t cluster_width;
+
+ uint32_t max_cluster_element_count_div_32;
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float temporal_blend;
+
+ float cam_rotation[12];
+ float to_prev_view[16];
+ float radiance_inverse_xform[12];
+ };
+
+ VolumetricFogProcessShaderRD process_shader;
+
+ RID process_shader_version;
+ RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
+
+ } volumetric_fog;
+
+ Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
+
+ struct FogShaderData : public RendererRD::ShaderData {
+ bool valid = false;
+ RID version;
+
+ RID pipeline;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size = 0;
+
+ String path;
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ bool uses_time = false;
+
+ 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_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ FogShaderData() {}
+ virtual ~FogShaderData();
+ };
+
+ struct FogMaterialData : public RendererRD::MaterialData {
+ FogShaderData *shader_data = nullptr;
+ RID uniform_set;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~FogMaterialData();
+ };
+
+ RendererRD::ShaderData *_create_fog_shader_func();
+ static RendererRD::ShaderData *_create_fog_shader_funcs();
+
+ RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
public:
static Fog *get_singleton() { return singleton; }
@@ -76,8 +252,78 @@ public:
RID fog_volume_get_material(RID p_fog_volume) const;
virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
Vector3 fog_volume_get_extents(RID p_fog_volume) const;
+
+ /* FOG VOLUMES INSTANCE */
+
+ FogVolumeInstance *get_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.get_or_null(p_rid); };
+ bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
+
+ RID fog_volume_instance_create(RID p_fog_volume);
+ void fog_instance_free(RID p_rid);
+
+ /* Volumetric FOG */
+ struct VolumetricFog {
+ enum {
+ MAX_TEMPORAL_FRAMES = 16
+ };
+
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t depth = 0;
+
+ float length;
+ float spread;
+
+ RID light_density_map;
+ RID prev_light_density_map;
+ RID fog_map;
+ RID density_map;
+ RID light_map;
+ RID emissive_map;
+
+ RID fog_uniform_set;
+ RID copy_uniform_set;
+ RID process_uniform_set_density;
+ RID process_uniform_set;
+ RID process_uniform_set2;
+ RID sdfgi_uniform_set;
+ RID sky_uniform_set;
+
+ int last_shadow_filter = -1;
+
+ VolumetricFog(const Vector3i &fog_size, RID p_sky_shader);
+ ~VolumetricFog();
+ };
+
+ void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array);
+ void free_fog_shader();
+
+ struct VolumetricFogSettings {
+ Vector2i rb_size;
+ double time;
+ bool is_using_radiance_cubemap_array;
+ uint32_t max_cluster_elements;
+ bool volumetric_fog_filter_active;
+ RID shadow_sampler;
+ RID voxel_gl_buffer;
+ RID shadow_atlas_depth;
+ RID omni_light_buffer;
+ RID spot_light_buffer;
+ RID directional_shadow_depth;
+ RID directional_light_buffer;
+
+ // Objects related to our render buffer
+ VolumetricFog *vfog;
+ ClusterBuilderRD *cluster_builder;
+ GI *gi;
+ GI::SDFGI *sdfgi;
+ GI::RenderBuffersGI *rbgi;
+ RendererSceneEnvironmentRD *env;
+ SkyRD *sky;
+ };
+ void volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
};
} // namespace RendererRD
-#endif // !FOG_RD_H
+#endif // FOG_RD_H
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 3275aea13c..cb120a1b49 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -1268,7 +1268,7 @@ void GI::SDFGI::update_light() {
RD::get_singleton()->draw_command_end_label();
}
-void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) {
+void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, SkyRD::Sky *p_sky) {
RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes");
SDFGIShader::IntegratePushConstant push_constant;
@@ -1482,7 +1482,7 @@ void GI::SDFGI::update_cascades() {
RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE);
}
-void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) {
+void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
@@ -1615,7 +1615,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
push_constant.cam_transform[15] = 1;
// need to properly unproject for asymmetric projection matrices in stereo..
- CameraMatrix inv_projection = p_projections[v].inverse();
+ 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];
@@ -1632,7 +1632,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1);
}
-void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
+void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
// setup scene data
@@ -1947,7 +1947,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
}
}
-void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
+void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
//print_line("rendering region " + itos(p_region));
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
@@ -2428,7 +2428,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
////////////////////////////////////////////////////////////////////////////////
// VoxelGIInstance
-void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
uint32_t data_version = gi->voxel_gi_get_data_version(probe);
@@ -2951,10 +2951,10 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
//this could probably be better parallelized in compute..
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i];
+ RenderGeometryInstance *instance = p_dynamic_objects[i];
//transform aabb to voxel_gi
- AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance));
+ AABB aabb = (to_probe_xform * instance->get_transform()).xform(instance->get_aabb());
//this needs to wrap to grid resolution to avoid jitter
//also extend margin a bit just in case
@@ -3015,7 +3015,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0);
bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0);
- CameraMatrix cm;
+ Projection cm;
cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
if (p_scene_render->cull_argument.size() == 0) {
@@ -3140,14 +3140,14 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
last_probe_version = gi->voxel_gi_get_version(probe);
}
-void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+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();
if (mipmaps.size() == 0) {
return;
}
- CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
+ Projection cam_transform = (p_camera_with_transform * Projection(transform)) * Projection(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
int level = 0;
Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
@@ -3233,7 +3233,7 @@ GI::~GI() {
singleton = nullptr;
}
-void GI::init(RendererSceneSkyRD *p_sky) {
+void GI::init(SkyRD *p_sky) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -3621,7 +3621,7 @@ void GI::RenderBuffersGI::free() {
}
}
-void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
+void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -3710,7 +3710,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
// Now compute the contents of our buffers.
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
- // Render each eye seperately.
+ // Render each eye separately.
// We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
// setup our push constant
@@ -3960,14 +3960,14 @@ bool GI::voxel_gi_needs_update(RID p_probe) const {
return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);
}
-void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
}
-void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index ac41ad20e1..30e695120e 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -35,8 +35,8 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/environment/sky.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
#include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h"
@@ -471,8 +471,8 @@ public:
Transform3D transform;
- void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ 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);
};
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
@@ -618,16 +618,16 @@ public:
void erase();
void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position);
void update_light();
- void update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky);
+ void update_probes(RendererSceneEnvironmentRD *p_env, RendererRD::SkyRD::Sky *p_sky);
void store_probes();
int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
void update_cascades();
- void debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views);
- void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
+ void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views);
+ void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
- void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
+ void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
};
@@ -756,7 +756,7 @@ public:
SHADER_SPECIALIZATION_HALF_RES = 1 << 0,
SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1,
SHADER_SPECIALIZATION_USE_VRS = 1 << 2,
- SHADER_SPECIALIZATION_VARIATIONS = 0x07,
+ SHADER_SPECIALIZATION_VARIATIONS = 8,
};
RID default_voxel_gi_buffer;
@@ -769,21 +769,21 @@ public:
GI();
~GI();
- void init(RendererSceneSkyRD *p_sky);
+ void init(RendererRD::SkyRD *p_sky);
void free();
SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
- void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
+ void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
RID voxel_gi_instance_create(RID p_base);
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
bool voxel_gi_needs_update(RID p_probe) const;
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+ void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
};
} // namespace RendererRD
-#endif /* !GI_RD_H */
+#endif // GI_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 73175d3cf3..2b140696b4 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_sky_rd.cpp */
+/* sky.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,27 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_scene_sky_rd.h"
+#include "sky.h"
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
-#include "renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_globals.h"
+using namespace RendererRD;
+
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
-void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
+void SkyRD::SkyShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void SkyRD::SkyShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -141,7 +147,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -158,7 +164,7 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa
}
}
-void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -172,15 +178,29 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
order[E.value.order] = E.key;
}
}
-
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
}
}
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
@@ -195,7 +215,7 @@ void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMat
}
}
-bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
+bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -203,15 +223,15 @@ bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_par
return uniforms[p_param].texture_order >= 0;
}
-bool RendererSceneSkyRD::SkyShaderData::is_animated() const {
+bool SkyRD::SkyShaderData::is_animated() const {
return false;
}
-bool RendererSceneSkyRD::SkyShaderData::casts_shadows() const {
+bool SkyRD::SkyShaderData::casts_shadows() const {
return false;
}
-Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -220,13 +240,13 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam
return Variant();
}
-RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const {
+RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
}
-RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
+SkyRD::SkyShaderData::~SkyShaderData() {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
@@ -238,7 +258,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Sky material
-bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
@@ -246,7 +266,7 @@ bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<String
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, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
}
-RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
+SkyRD::SkyMaterialData::~SkyMaterialData() {
free_parameters_uniform_set(uniform_set);
}
@@ -268,7 +288,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
-void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
+void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@@ -319,7 +339,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
////////////////////////////////////////////////////////////////////////////////
// ReflectionData
-void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
+void SkyRD::ReflectionData::clear_reflection_data() {
layers.clear();
radiance_base_cubemap = RID();
if (downsampled_radiance_cubemap.is_valid()) {
@@ -330,7 +350,7 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
coefficient_buffer = RID();
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
+void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
//recreate radiance and all data
int mipmaps = p_mipmaps;
@@ -399,21 +419,22 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, 1, RD::TEXTURE_SLICE_CUBEMAP);
RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
+
RD::TextureFormat tf;
tf.format = p_texture_format;
- tf.width = 64; // Always 64x64
- tf.height = 64;
+ tf.width = p_low_quality ? 64 : p_size >> 1; // Always 64x64 when using REALTIME.
+ tf.height = p_low_quality ? 64 : p_size >> 1;
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
tf.array_layers = 6;
- tf.mipmaps = 7;
+ tf.mipmaps = p_low_quality ? 7 : mipmaps - 1;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
{
- uint32_t mmw = 64;
- uint32_t mmh = 64;
- downsampled_layer.mipmaps.resize(7);
+ uint32_t mmw = tf.width;
+ uint32_t mmh = tf.height;
+ downsampled_layer.mipmaps.resize(tf.mipmaps);
for (int j = 0; j < downsampled_layer.mipmaps.size(); j++) {
ReflectionData::DownsampleLayer::Mipmap &mm = downsampled_layer.mipmaps.write[j];
mm.size.width = mmw;
@@ -438,7 +459,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {
+void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised");
bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
@@ -496,7 +517,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_us
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
+void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised");
bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
@@ -565,7 +586,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(boo
RD::get_singleton()->draw_command_end_label(); // Filter radiance
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {
+void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised");
bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
@@ -590,9 +611,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start,
}
////////////////////////////////////////////////////////////////////////////////
-// RendererSceneSkyRD::Sky
+// SkyRD::Sky
-void RendererSceneSkyRD::Sky::free() {
+void SkyRD::Sky::free() {
if (radiance.is_valid()) {
RD::get_singleton()->free(radiance);
radiance = RID();
@@ -620,7 +641,7 @@ void RendererSceneSkyRD::Sky::free() {
}
}
-RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) {
@@ -681,7 +702,7 @@ RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_
return texture_uniform_sets[p_version];
}
-bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
+bool SkyRD::Sky::set_radiance_size(int p_radiance_size) {
ERR_FAIL_COND_V(p_radiance_size < 32 || p_radiance_size > 2048, false);
if (radiance_size == p_radiance_size) {
return false;
@@ -702,7 +723,7 @@ bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
return true;
}
-bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
+bool SkyRD::Sky::set_mode(RS::SkyMode p_mode) {
if (mode == p_mode) {
return false;
}
@@ -723,7 +744,7 @@ bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
return true;
}
-bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
+bool SkyRD::Sky::set_material(RID p_material) {
if (material == p_material) {
return false;
}
@@ -732,7 +753,7 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
return true;
}
-Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
+Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
if (radiance.is_valid()) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
@@ -766,37 +787,37 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughnes
}
////////////////////////////////////////////////////////////////////////////////
-// RendererSceneSkyRD
+// SkyRD
-RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::ShaderData *SkyRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
-RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::ShaderData *SkyRD::_create_sky_shader_funcs() {
// !BAS! Why isn't _create_sky_shader_func not just static too?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
};
-RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
+RendererRD::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
// !BAS! same here, we could just make _create_sky_material_func static?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
-RendererSceneSkyRD::RendererSceneSkyRD() {
+SkyRD::SkyRD() {
roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
sky_ggx_samples_quality = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections");
}
-void RendererSceneSkyRD::init() {
+void SkyRD::init() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -1051,11 +1072,11 @@ void sky() {
}
}
-void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
+void SkyRD::set_texture_format(RD::DataFormat p_texture_format) {
texture_format = p_texture_format;
}
-RendererSceneSkyRD::~RendererSceneSkyRD() {
+SkyRD::~SkyRD() {
// cleanup anything created in init...
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -1085,7 +1106,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
-void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+void SkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
@@ -1297,7 +1318,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update(RendererSceneEnvironmentRD *p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
@@ -1371,9 +1392,9 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
Vector3(0, -1, 0)
};
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, 10.0);
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
cm = correction * cm;
@@ -1466,7 +1487,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
}
-void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void SkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
@@ -1515,9 +1536,9 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
float custom_fov = p_env->sky_custom_fov;
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1573,7 +1594,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
RD::get_singleton()->draw_list_end();
}
-void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
@@ -1613,9 +1634,9 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
float custom_fov = p_env->sky_custom_fov;
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1658,7 +1679,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
}
}
-void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
@@ -1707,9 +1728,9 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
float custom_fov = p_env->sky_custom_fov;
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1737,7 +1758,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
}
-void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
+void SkyRD::invalidate_sky(Sky *p_sky) {
if (!p_sky->dirty) {
p_sky->dirty = true;
p_sky->dirty_list = dirty_sky_list;
@@ -1745,7 +1766,7 @@ void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
}
}
-void RendererSceneSkyRD::update_dirty_skys() {
+void SkyRD::update_dirty_skys() {
Sky *sky = dirty_sky_list;
while (sky) {
@@ -1849,26 +1870,26 @@ void RendererSceneSkyRD::update_dirty_skys() {
dirty_sky_list = nullptr;
}
-RID RendererSceneSkyRD::sky_get_material(RID p_sky) const {
+RID SkyRD::sky_get_material(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, RID());
return sky->material;
}
-RID RendererSceneSkyRD::allocate_sky_rid() {
+RID SkyRD::allocate_sky_rid() {
return sky_owner.allocate_rid();
}
-void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) {
+void SkyRD::initialize_sky_rid(RID p_rid) {
sky_owner.initialize_rid(p_rid, Sky());
}
-RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const {
+SkyRD::Sky *SkyRD::get_sky(RID p_sky) const {
return sky_owner.get_or_null(p_sky);
}
-void RendererSceneSkyRD::free_sky(RID p_sky) {
+void SkyRD::free_sky(RID p_sky) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1876,7 +1897,7 @@ void RendererSceneSkyRD::free_sky(RID p_sky) {
sky_owner.free(p_sky);
}
-void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
+void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1885,7 +1906,7 @@ void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
}
}
-void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
+void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1894,7 +1915,7 @@ void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
}
}
-void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
+void SkyRD::sky_set_material(RID p_sky, RID p_material) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1903,7 +1924,7 @@ void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
}
}
-Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
+Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, Ref<Image>());
@@ -1912,7 +1933,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool
return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
}
-RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
+RID SkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, RID());
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/environment/sky.h
index a8ee406abc..c3962f20b7 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_sky_rd.h */
+/* sky.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_SKY_RD_H
-#define RENDERING_SERVER_SCENE_SKY_RD_H
+#ifndef SKY_RD_H
+#define SKY_RD_H
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -44,7 +44,9 @@
// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
class RendererSceneRenderRD;
-class RendererSceneSkyRD {
+namespace RendererRD {
+
+class SkyRD {
public:
enum SkySet {
SKY_SET_UNIFORMS,
@@ -128,6 +130,7 @@ private:
bool uses_light = false;
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_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -141,7 +144,7 @@ private:
virtual ~SkyShaderData();
};
- void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
+ void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
@@ -289,16 +292,16 @@ public:
RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
- RendererSceneSkyRD();
+ SkyRD();
void init();
void set_texture_format(RD::DataFormat p_texture_format);
- ~RendererSceneSkyRD();
+ ~SkyRD();
- void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
- void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
- void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
- void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
- void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+ void update(RendererSceneEnvironmentRD *p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
+ void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
@@ -317,4 +320,6 @@ public:
RID sky_get_radiance_texture_rd(RID p_sky) const;
};
-#endif /* RENDERING_SERVER_SCENE_SKY_RD_H */
+} // namespace RendererRD
+
+#endif // SKY_RD_H
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 85652a041d..872a27fda1 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -66,6 +66,13 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
}
specular = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (view_count == 1) {
+ specular_views[0] = specular;
+ } else {
+ for (uint32_t v = 0; v < view_count; v++) {
+ specular_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular, v, 0);
+ }
+ }
if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
@@ -80,6 +87,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (view_count == 1) {
+ specular_msaa_views[0] = specular_msaa;
+ } else {
+ for (uint32_t v = 0; v < view_count; v++) {
+ specular_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular_msaa, v, 0);
+ }
+ }
+
{
Vector<RID> fb;
fb.push_back(specular_msaa);
@@ -175,6 +190,8 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
color_views[v] = RID();
depth_views[v] = RID();
+ specular_views[v] = RID();
+ specular_msaa_views[v] = RID();
color_msaa_views[v] = RID();
depth_msaa_views[v] = RID();
normal_roughness_views[v] = RID();
@@ -758,7 +775,7 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
void RenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
@@ -770,9 +787,10 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p
if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardClustered::_render_list_thread_function, p_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardClustered::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardClusteredRenderList"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
@@ -783,12 +801,12 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p
}
void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
- //CameraMatrix projection = p_render_data->cam_projection;
+ //Projection projection = p_render_data->cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
correction.add_jitter_offset(p_render_data->taa_jitter);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection projection = correction * p_render_data->cam_projection;
//store camera into ubo
RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix);
@@ -978,10 +996,10 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO));
- CameraMatrix prev_correction;
+ Projection prev_correction;
prev_correction.set_depth_correction(true);
prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter);
- CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection;
+ Projection prev_projection = prev_correction * p_render_data->prev_cam_projection;
//store camera into ubo
RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix);
@@ -1571,9 +1589,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ Projection projection = p_render_data->cam_projection;
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
projection = correction * p_render_data->cam_projection;
}
@@ -1702,9 +1720,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
- CameraMatrix dc;
+ Projection dc;
dc.set_depth_correction(true);
- CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
+ Projection cm = (dc * p_render_data->cam_projection) * Projection(p_render_data->cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
@@ -1719,11 +1737,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
- CameraMatrix dc;
+ Projection dc;
dc.set_depth_correction(true);
- CameraMatrix cms[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection cms[RendererSceneRender::MAX_RENDER_VIEWS];
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
- cms[v] = (dc * p_render_data->view_projection[v]) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
+ cms[v] = (dc * p_render_data->view_projection[v]) * Projection(p_render_data->cam_transform.affine_inverse());
}
_debug_sdfgi_probes(p_render_data->render_buffers, color_only_framebuffer, p_render_data->view_count, cms, will_continue_color, will_continue_depth);
}
@@ -1734,9 +1752,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Draw Sky");
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection projection = correction * p_render_data->cam_projection;
sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
} else {
sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
@@ -1749,9 +1767,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
for (uint32_t v = 0; v < render_buffer->view_count; v++) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]);
}
- // TODO mame this do multiview
if (using_separate_specular) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular);
+ for (uint32_t v = 0; v < render_buffer->view_count; v++) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa_views[v], render_buffer->specular_views[v]);
+ }
}
}
@@ -1772,12 +1791,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (using_ssr) {
RENDER_TIMESTAMP("Screen-Space Reflections");
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
- _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_views, render_buffer->specular, render_buffer->specular_views, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->view_projection, p_render_data->view_eye_offset, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- RendererCompositorRD::singleton->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ copy_effects->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID(), p_render_data->view_count);
}
}
@@ -1854,7 +1873,7 @@ void RenderForwardClustered::_render_shadow_begin() {
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -1944,7 +1963,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -1983,7 +2002,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@@ -2032,7 +2051,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
RD::get_singleton()->draw_command_begin_label("Render UV2");
@@ -2102,7 +2121,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
RENDER_TIMESTAMP("Render SDFGI");
RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel");
@@ -2773,24 +2792,23 @@ RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_bu
RenderForwardClustered *RenderForwardClustered::singleton = nullptr;
-void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ GeometryInstanceSurfaceDataCache *surf = surface_caches;
while (surf) {
GeometryInstanceSurfaceDataCache *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RenderForwardClustered::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RenderForwardClustered::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -2958,7 +2976,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
}
}
-void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
@@ -3117,7 +3135,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
case Dependency::DEPENDENCY_CHANGED_PARTICLES:
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
- static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} break;
case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
@@ -3131,10 +3149,10 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
}
}
void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
- static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
-RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
+RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
@@ -3147,155 +3165,47 @@ RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance
ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) {
uint64_t frame = RSG::rasterizer->get_frame_number();
- if (frame != ginstance->prev_transform_change_frame) {
- ginstance->prev_transform = ginstance->transform;
- ginstance->prev_transform_change_frame = frame;
- ginstance->prev_transform_dirty = true;
+ if (frame != prev_transform_change_frame) {
+ prev_transform = transform;
+ prev_transform_change_frame = frame;
+ prev_transform_dirty = true;
}
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
-
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
-
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
- ginstance->lod_model_scale = max_scale;
-}
-void RenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-void RenderForwardClustered::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->fade_near = p_enable_near;
- ginstance->fade_near_begin = p_near_begin;
- ginstance->fade_near_end = p_near_end;
- ginstance->fade_far = p_enable_far;
- ginstance->fade_far_begin = p_far_begin;
- ginstance->fade_far_end = p_far_end;
+ RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabbb);
}
-void RenderForwardClustered::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->parent_fade_alpha = p_alpha;
-}
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ lightmap_instance = p_lightmap_instance;
+ lightmap_uv_scale = p_lightmap_uv_scale;
+ lightmap_slice_index = p_lightmap_slice_index;
-void RenderForwardClustered::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+ _mark_dirty();
}
-void RenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_dynamic_gi = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_lightmap_capture(const Color *p_sh9) {
if (p_sh9) {
- if (ginstance->lightmap_sh == nullptr) {
- ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ if (lightmap_sh == nullptr) {
+ lightmap_sh = RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.alloc();
}
- memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
} else {
- if (ginstance->lightmap_sh != nullptr) {
- geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
- ginstance->lightmap_sh = nullptr;
+ if (lightmap_sh != nullptr) {
+ RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh);
+ lightmap_sh = nullptr;
}
}
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
+ _mark_dirty();
}
-void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RenderForwardClustered::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
@@ -3314,47 +3224,25 @@ void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry
uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() {
return (1 << RS::INSTANCE_VOXEL_GI);
}
-void RenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
-}
-void RenderForwardClustered::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
-}
-void RenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
-}
-
-Transform3D RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform3D());
- return ginstance->transform;
-}
-
-AABB RenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, AABB());
- return ginstance->data->aabb;
-}
-void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
if (p_voxel_gi_instance_count > 0) {
- ginstance->voxel_gi_instances[0] = p_voxel_gi_instances[0];
+ voxel_gi_instances[0] = p_voxel_gi_instances[0];
} else {
- ginstance->voxel_gi_instances[0] = RID();
+ voxel_gi_instances[0] = RID();
}
if (p_voxel_gi_instance_count > 1) {
- ginstance->voxel_gi_instances[1] = p_voxel_gi_instances[1];
+ voxel_gi_instances[1] = p_voxel_gi_instances[1];
} else {
- ginstance->voxel_gi_instances[1] = RID();
+ voxel_gi_instances[1] = RID();
}
}
-void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->using_projectors = p_projector;
- ginstance->using_softshadows = p_softshadow;
- _geometry_instance_mark_dirty(ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) {
+ using_projectors = p_projector;
+ using_softshadows = p_softshadow;
+ _mark_dirty();
}
void RenderForwardClustered::_update_shader_quality_settings() {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index ff712a20a1..7e71406af8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+#ifndef RENDER_FORWARD_CLUSTERED_H
+#define RENDER_FORWARD_CLUSTERED_H
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/effects/resolve.h"
@@ -117,6 +117,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t view_count = 1;
RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
+ RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS];
@@ -425,7 +427,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
HashMap<Size2i, RID> sdfgi_framebuffer_size_cache;
struct GeometryInstanceData;
- struct GeometryInstanceForwardClustered;
+ class GeometryInstanceForwardClustered;
struct GeometryInstanceLightmapSH {
Color sh[9];
@@ -485,73 +487,48 @@ class RenderForwardClustered : public RendererSceneRenderRD {
GeometryInstanceForwardClustered *owner = nullptr;
};
- struct GeometryInstanceForwardClustered : public GeometryInstance {
+ class GeometryInstanceForwardClustered : public RenderGeometryInstanceBase {
+ public:
+ // lightmap
+ RID lightmap_instance;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index;
+ GeometryInstanceLightmapSH *lightmap_sh = nullptr;
+
//used during rendering
- bool mirror = false;
- bool non_uniform_scale = false;
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- AABB transformed_aabb; //needed for LOD
- float depth = 0;
+
uint32_t gi_offset_cache = 0;
- uint32_t flags_cache = 0;
bool store_transform_cache = true;
- int32_t shader_parameters_offset = -1;
- uint32_t lightmap_slice_index;
- Rect2 lightmap_uv_scale;
- uint32_t layer_mask = 1;
RID transforms_uniform_set;
uint32_t instance_count = 0;
uint32_t trail_steps = 1;
- RID mesh_instance;
bool can_sdfgi = false;
bool using_projectors = false;
bool using_softshadows = false;
- bool fade_near = false;
- float fade_near_begin = 0;
- float fade_near_end = 0;
- bool fade_far = false;
- float fade_far_begin = 0;
- float fade_far_end = 0;
- float force_alpha = 1.0;
- float parent_fade_alpha = 1.0;
//used during setup
- uint32_t base_flags = 0;
uint64_t prev_transform_change_frame = 0xFFFFFFFF;
bool prev_transform_dirty = true;
- Transform3D transform;
Transform3D prev_transform;
RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE];
- RID lightmap_instance;
- GeometryInstanceLightmapSH *lightmap_sh = nullptr;
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
SelfList<GeometryInstanceForwardClustered> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
+ GeometryInstanceForwardClustered() :
+ dirty_list_element(this) {}
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
+ virtual void _mark_dirty() override;
- bool use_dynamic_gi = false;
- bool use_baked_light = true;
- bool cast_double_sided_shadows = false;
- bool mirror = false;
- bool dirty_dependencies = false;
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) 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;
- DependencyTracker dependency_tracker;
- };
+ 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;
- Data *data = nullptr;
-
- GeometryInstanceForwardClustered() :
- dirty_list_element(this) {}
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override;
};
static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
@@ -566,8 +543,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
/* Render List */
@@ -638,52 +614,27 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
public:
+ static RenderForwardClustered *get_singleton() { return singleton; }
+
_FORCE_INLINE_ virtual void update_uniform_sets() override {
base_uniform_set_updated = true;
_update_render_base_uniform_set();
}
- virtual GeometryInstance *geometry_instance_create(RID p_base) override;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
virtual bool free(RID p_rid) override;
@@ -691,4 +642,5 @@ public:
~RenderForwardClustered();
};
} // namespace RendererSceneRenderImplementation
-#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+
+#endif // RENDER_FORWARD_CLUSTERED_H
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 1951bfe915..6f4a7f6a84 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
@@ -37,6 +37,10 @@
using namespace RendererSceneRenderImplementation;
+void SceneShaderForwardClustered::ShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
//compile
@@ -403,7 +407,22 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -663,7 +682,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
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 1cfe723174..fb001d6933 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
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RSSR_SCENE_SHADER_FC_H
-#define RSSR_SCENE_SHADER_FC_H
+#ifndef SCENE_SHADER_FORWARD_CLUSTERED_H
+#define SCENE_SHADER_FORWARD_CLUSTERED_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
@@ -180,6 +180,7 @@ public:
uint32_t index = 0;
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;
void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -251,4 +252,5 @@ public:
};
} // namespace RendererSceneRenderImplementation
-#endif // !RSSR_SCENE_SHADER_FM_H
+
+#endif // SCENE_SHADER_FORWARD_CLUSTERED_H
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 966621c93e..67c7d12517 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -648,9 +648,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ Projection projection = p_render_data->cam_projection;
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
projection = correction * p_render_data->cam_projection;
}
@@ -680,9 +680,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers");
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection projection = correction * p_render_data->cam_projection;
sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time);
} else {
sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
@@ -758,9 +758,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderList"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
@@ -776,9 +779,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection projection = correction * p_render_data->cam_projection;
sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
} else {
sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
@@ -822,10 +825,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr());
render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
@@ -859,9 +864,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
} else {
//single threaded
@@ -900,7 +907,7 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -994,7 +1001,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
-void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@@ -1040,7 +1047,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
RD::get_singleton()->draw_command_begin_label("Render UV2");
@@ -1107,11 +1114,11 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
// we don't do GI in low end..
}
-void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -1543,11 +1550,11 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
// This populates our UBO with main scene data that is pushed into set 1
- //CameraMatrix projection = p_render_data->cam_projection;
+ //Projection projection = p_render_data->cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection projection = correction * p_render_data->cam_projection;
//store camera into ubo
RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix);
@@ -1771,7 +1778,7 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list,
void RenderForwardMobile::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
@@ -1783,9 +1790,11 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para
if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, p_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
@@ -2047,7 +2056,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
/* Geometry instance */
-RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) {
+RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) {
RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
@@ -2057,165 +2066,36 @@ RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_cr
ginstance->data->base = p_base;
ginstance->data->base_type = type;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RenderForwardMobile::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
-
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
-
- ginstance->lod_model_scale = max_scale;
-}
-
-void RenderForwardMobile::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
-}
-
-void RenderForwardMobile::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-
-void RenderForwardMobile::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
-}
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ lightmap_instance = p_lightmap_instance;
+ lightmap_uv_scale = p_lightmap_uv_scale;
+ lightmap_slice_index = p_lightmap_slice_index;
-void RenderForwardMobile::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
+ _mark_dirty();
}
-void RenderForwardMobile::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
-}
-
-void RenderForwardMobile::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- // !BAS! do we support this in mobile?
- // GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- // ERR_FAIL_COND(!ginstance);
- // ginstance->data->use_dynamic_gi = p_enable;
- // _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_lightmap_capture(const Color *p_sh9) {
if (p_sh9) {
- if (ginstance->lightmap_sh == nullptr) {
- ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ if (lightmap_sh == nullptr) {
+ lightmap_sh = RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.alloc();
}
- memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
} else {
- if (ginstance->lightmap_sh != nullptr) {
- geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
- ginstance->lightmap_sh = nullptr;
+ if (lightmap_sh != nullptr) {
+ RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh);
+ lightmap_sh = nullptr;
}
}
- _geometry_instance_mark_dirty(ginstance);
+ _mark_dirty();
}
-void RenderForwardMobile::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-Transform3D RenderForwardMobile::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform3D());
- return ginstance->transform;
-}
-
-AABB RenderForwardMobile::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, AABB());
- return ginstance->data->aabb;
-}
-
-void RenderForwardMobile::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RenderForwardMobile::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
@@ -2235,26 +2115,23 @@ uint32_t RenderForwardMobile::geometry_instance_get_pair_mask() {
return ((1 << RS::INSTANCE_LIGHT) + (1 << RS::INSTANCE_REFLECTION_PROBE) + (1 << RS::INSTANCE_DECAL));
}
-void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->omni_light_count = 0;
- ginstance->spot_light_count = 0;
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) {
+ omni_light_count = 0;
+ spot_light_count = 0;
for (uint32_t i = 0; i < p_light_instance_count; i++) {
- RS::LightType type = light_instance_get_type(p_light_instances[i]);
+ RS::LightType type = RenderForwardMobile::get_singleton()->light_instance_get_type(p_light_instances[i]);
switch (type) {
case RS::LIGHT_OMNI: {
- if (ginstance->omni_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->omni_lights[ginstance->omni_light_count] = light_instance_get_forward_id(p_light_instances[i]);
- ginstance->omni_light_count++;
+ if (omni_light_count < (uint32_t)MAX_RDL_CULL) {
+ omni_lights[omni_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]);
+ omni_light_count++;
}
} break;
case RS::LIGHT_SPOT: {
- if (ginstance->spot_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->spot_lights[ginstance->spot_light_count] = light_instance_get_forward_id(p_light_instances[i]);
- ginstance->spot_light_count++;
+ if (spot_light_count < (uint32_t)MAX_RDL_CULL) {
+ spot_lights[spot_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]);
+ spot_light_count++;
}
} break;
default:
@@ -2263,56 +2140,42 @@ void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstanc
}
}
-void RenderForwardMobile::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
- for (uint32_t i = 0; i < ginstance->reflection_probe_count; i++) {
- ginstance->reflection_probes[i] = reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+ reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
+ for (uint32_t i = 0; i < reflection_probe_count; i++) {
+ reflection_probes[i] = RenderForwardMobile::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
}
}
-void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
- for (uint32_t i = 0; i < ginstance->decals_count; i++) {
- ginstance->decals[i] = decal_instance_get_forward_id(p_decal_instances[i]);
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+ decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
+ for (uint32_t i = 0; i < decals_count; i++) {
+ decals[i] = RenderForwardMobile::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]);
}
}
-void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
- // We do not have this here!
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) {
+ use_projector = p_projector;
+ use_soft_shadow = p_softshadow;
}
-void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->use_projector = p_projector;
- ginstance->use_soft_shadow = p_softshadow;
-}
-
-void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RenderForwardMobile::GeometryInstanceForwardMobile::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ GeometryInstanceSurfaceDataCache *surf = surface_caches;
while (surf) {
GeometryInstanceSurfaceDataCache *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RenderForwardMobile::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RenderForwardMobile::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -2478,7 +2341,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
}
}
-void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
@@ -2632,7 +2495,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe
case Dependency::DEPENDENCY_CHANGED_PARTICLES:
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
- static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} break;
case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
@@ -2646,7 +2509,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe
}
}
void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
- static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
/* misc */
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index bf4a52d466..4a7112eb81 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
+#ifndef RENDER_FORWARD_MOBILE_H
+#define RENDER_FORWARD_MOBILE_H
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h"
@@ -160,7 +160,7 @@ protected:
// PASS_MODE_SDF,
};
- struct GeometryInstanceForwardMobile;
+ class GeometryInstanceForwardMobile;
struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
@@ -212,14 +212,14 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
@@ -518,14 +518,8 @@ protected:
GeometryInstanceForwardMobile *owner = nullptr;
};
- // !BAS! GeometryInstanceForwardClustered and GeometryInstanceForwardMobile will likely have a lot of overlap
- // may need to think about making this its own class like GeometryInstanceRD?
-
- struct GeometryInstanceForwardMobile : public GeometryInstance {
- // setup
- uint32_t base_flags = 0;
- uint32_t flags_cache = 0;
-
+ class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase {
+ public:
// this structure maps to our push constant in our shader and is populated right before our draw call
struct PushConstant {
float transform[16];
@@ -543,28 +537,18 @@ protected:
// PushConstant push_constant; // we populate this from our instance data
//used during rendering
- uint32_t layer_mask = 1;
RID transforms_uniform_set;
- float depth = 0;
- bool mirror = false;
bool use_projector = false;
bool use_soft_shadow = false;
- Transform3D transform;
bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform
- bool non_uniform_scale = false;
- AABB transformed_aabb; //needed for LOD
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- int32_t shader_parameters_offset = -1;
uint32_t instance_count = 0;
uint32_t trail_steps = 1;
- RID mesh_instance;
// lightmap
uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap
- uint32_t lightmap_slice_index;
- Rect2 lightmap_uv_scale;
RID lightmap_instance;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
// culled light info
@@ -582,30 +566,20 @@ protected:
// do we use this?
SelfList<GeometryInstanceForwardMobile> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
-
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
-
- bool use_baked_light = true;
- bool cast_double_sided_shadows = false;
- // bool mirror = false; // !BAS! Does not seem used, we already have this in the main struct
+ GeometryInstanceForwardMobile() :
+ dirty_list_element(this) {}
- bool dirty_dependencies = false;
+ virtual void _mark_dirty() override;
- DependencyTracker dependency_tracker;
- };
+ 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;
- Data *data = nullptr;
+ 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 {}
- GeometryInstanceForwardMobile() :
- dirty_list_element(this) {}
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override;
};
_FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance);
@@ -613,6 +587,8 @@ protected:
void _update_shader_quality_settings() override;
public:
+ static RenderForwardMobile *get_singleton() { return singleton; }
+
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
@@ -627,41 +603,13 @@ public:
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
- virtual GeometryInstance *geometry_instance_create(RID p_base) override;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
virtual bool free(RID p_rid) override;
@@ -674,4 +622,5 @@ public:
~RenderForwardMobile();
};
} // namespace RendererSceneRenderImplementation
-#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
+
+#endif // RENDER_FORWARD_MOBILE_H
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 dd00dc2bf9..ba8ee62b3f 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
@@ -39,6 +39,10 @@ using namespace RendererSceneRenderImplementation;
/* ShaderData */
+void SceneShaderForwardMobile::ShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
//compile
@@ -360,7 +364,22 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -565,7 +584,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
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 88c2143b09..0dbed0b07a 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
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RSSR_SCENE_SHADER_FM_H
-#define RSSR_SCENE_SHADER_FM_H
+#ifndef SCENE_SHADER_FORWARD_MOBILE_H
+#define SCENE_SHADER_FORWARD_MOBILE_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h"
@@ -139,6 +139,8 @@ public:
uint32_t index = 0;
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;
void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -210,4 +212,5 @@ public:
};
} // namespace RendererSceneRenderImplementation
-#endif // !RSSR_SCENE_SHADER_FM_H
+
+#endif // SCENE_SHADER_FORWARD_MOBILE_H
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index ad83fc76b7..882e459bcd 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -97,4 +97,4 @@ public:
~PipelineCacheRD();
};
-#endif // RENDER_PIPELINE_CACHE_RD_H
+#endif // PIPELINE_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 7d55be1216..a58cdd5066 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -528,7 +528,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
if (rect->flags & CANVAS_RECT_TRANSPOSE) {
- dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform
+ push_constant.flags |= FLAGS_TRANSPOSE_RECT;
}
if (rect->flags & CANVAS_RECT_CLIP_UV) {
@@ -1584,7 +1584,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
- CameraMatrix projection;
+ Projection projection;
{
real_t fov = 90;
real_t nearp = p_near;
@@ -1600,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
}
Vector3 cam_target = Basis(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
- projection = projection * CameraMatrix(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1673,9 +1673,9 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2);
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
- CameraMatrix projection;
+ Projection projection;
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
- projection = projection * CameraMatrix(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * Projection(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1743,7 +1743,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc);
- CameraMatrix projection;
+ Projection projection;
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1968,6 +1968,10 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
+void RendererCanvasRenderRD::CanvasShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
@@ -2181,7 +2185,22 @@ void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo>
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 2ab5a7c831..1c0567b677 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_CANVAS_RENDER_RD_H
-#define RENDERING_SERVER_CANVAS_RENDER_RD_H
+#ifndef RENDERER_CANVAS_RENDER_RD_H
+#define RENDERER_CANVAS_RENDER_RD_H
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
@@ -178,6 +178,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
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_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -464,4 +465,4 @@ public:
~RendererCanvasRenderRD();
};
-#endif // RASTERIZER_CANVAS_RD_H
+#endif // RENDERER_CANVAS_RENDER_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 2be55743fb..564c26bfe4 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -28,11 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_COMPOSITOR_RD_H
-#define RENDERING_SERVER_COMPOSITOR_RD_H
+#ifndef RENDERER_COMPOSITOR_RD_H
+#define RENDERER_COMPOSITOR_RD_H
#include "core/os/os.h"
-#include "core/templates/thread_work_pool.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/effects_rd.h"
#include "servers/rendering/renderer_rd/environment/fog.h"
@@ -148,4 +147,5 @@ public:
RendererCompositorRD();
~RendererCompositorRD();
};
-#endif // RASTERIZER_RD_H
+
+#endif // RENDERER_COMPOSITOR_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
index 4e170b8cfb..d9f78b3bc3 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
-#define RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
+#ifndef RENDERER_SCENE_ENVIRONMENT_RD_H
+#define RENDERER_SCENE_ENVIRONMENT_RD_H
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -164,4 +164,4 @@ public:
void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
};
-#endif /* !RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H */
+#endif // RENDERER_SCENE_ENVIRONMENT_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index a2a0538e04..4e43acaf57 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -558,29 +558,28 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
////////////////////////////////////////////////////////////
RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) {
- FogVolumeInstance fvi;
- fvi.volume = p_fog_volume;
- return fog_volume_instance_owner.make_rid(fvi);
+ return RendererRD::Fog::get_singleton()->fog_volume_instance_create(p_fog_volume);
}
+
void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND(!fvi);
fvi->transform = p_transform;
}
void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND(!fvi);
fvi->active = p_active;
}
RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND_V(!fvi, RID());
return fvi->volume;
}
Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND_V(!fvi, Vector3());
return fvi->transform.get_origin();
@@ -1430,7 +1429,7 @@ void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const
light_instance->aabb = p_aabb;
}
-void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
+void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -1526,7 +1525,7 @@ bool RendererSceneRenderRD::voxel_gi_needs_update(RID p_probe) const {
return gi.voxel_gi_needs_update(p_probe);
}
-void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
+void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) {
if (!is_dynamic_gi_supported()) {
return;
}
@@ -1534,7 +1533,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins
gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this);
}
-void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
+void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -1891,60 +1890,9 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->ss_effects.linear_depth_slices.clear();
}
- if (rb->ss_effects.ssao.ao_final.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
-
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
-
- rb->ss_effects.ssao.ao_deinterleaved = RID();
- rb->ss_effects.ssao.ao_pong = RID();
- rb->ss_effects.ssao.ao_final = RID();
- rb->ss_effects.ssao.importance_map[0] = RID();
- rb->ss_effects.ssao.importance_map[1] = RID();
-
- rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
- rb->ss_effects.ssao.ao_pong_slices.clear();
- }
-
- if (rb->ss_effects.ssil.ssil_final.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
- RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssil.pong);
- RD::get_singleton()->free(rb->ss_effects.ssil.edges);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
-
- rb->ss_effects.ssil.ssil_final = RID();
- rb->ss_effects.ssil.deinterleaved = RID();
- rb->ss_effects.ssil.pong = RID();
- rb->ss_effects.ssil.edges = RID();
- rb->ss_effects.ssil.deinterleaved_slices.clear();
- rb->ss_effects.ssil.pong_slices.clear();
- rb->ss_effects.ssil.edges_slices.clear();
- rb->ss_effects.ssil.importance_map[0] = RID();
- rb->ss_effects.ssil.importance_map[1] = RID();
-
- RD::get_singleton()->free(rb->ss_effects.last_frame);
- rb->ss_effects.last_frame = RID();
- rb->ss_effects.last_frame_slices.clear();
- }
-
- if (rb->ssr.blur_radius[0].is_valid()) {
- RD::get_singleton()->free(rb->ssr.blur_radius[0]);
- RD::get_singleton()->free(rb->ssr.blur_radius[1]);
- rb->ssr.blur_radius[0] = RID();
- rb->ssr.blur_radius[1] = RID();
- }
-
- if (rb->ssr.depth_scaled.is_valid()) {
- RD::get_singleton()->free(rb->ssr.depth_scaled);
- rb->ssr.depth_scaled = RID();
- RD::get_singleton()->free(rb->ssr.normal_scaled);
- rb->ssr.normal_scaled = RID();
- }
+ ss_effects->ssao_free(rb->ss_effects.ssao);
+ ss_effects->ssil_free(rb->ss_effects.ssil);
+ ss_effects->ssr_free(rb->ssr);
if (rb->taa.history.is_valid()) {
RD::get_singleton()->free(rb->taa.history);
@@ -1964,7 +1912,7 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->rbgi.free();
}
-void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
+void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const Projection &p_camera) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -1982,7 +1930,9 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
RendererCompositorRD::singleton->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
}
-void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
+void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) {
+ ERR_FAIL_NULL(ss_effects);
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -1990,7 +1940,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (!can_use_effects) {
//just copy
- RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID(), rb->view_count);
return;
}
@@ -1999,42 +1949,23 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
ERR_FAIL_COND(!env->ssr_enabled);
- if (rb->ssr.depth_scaled.is_null()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = rb->internal_width / 2;
- tf.height = rb->internal_height / 2;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
-
- rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Size2i half_size = Size2i(rb->internal_width / 2, rb->internal_height / 2);
+ if (rb->ssr.output.is_null()) {
+ ss_effects->ssr_allocate_buffers(rb->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, rb->view_count);
}
-
- if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->internal_width / 2;
- tf.height = rb->internal_height / 2;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->ssr.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- if (rb->blur[0].texture.is_null()) {
- _allocate_blur_textures(rb);
+ RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ for (uint32_t v = 0; v < rb->view_count; v++) {
+ texture_slices[v] = rb->views[v].view_texture;
+ depth_slices[v] = rb->views[v].view_depth;
}
-
- RendererCompositorRD::singleton->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture);
+ ss_effects->screen_space_reflection(rb->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, p_metallic_mask, depth_slices, half_size, env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, rb->view_count, p_projections, p_eye_offsets);
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->ssr.output, rb->view_count);
}
-void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
+void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) {
+ ERR_FAIL_NULL(ss_effects);
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -2043,102 +1974,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
RENDER_TIMESTAMP("Process SSAO");
- if (rb->ss_effects.ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) {
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
-
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
-
- rb->ss_effects.ssao.ao_deinterleaved = RID();
- rb->ss_effects.ssao.ao_pong = RID();
- rb->ss_effects.ssao.ao_final = RID();
- rb->ss_effects.ssao.importance_map[0] = RID();
- rb->ss_effects.ssao.importance_map[1] = RID();
- rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
- rb->ss_effects.ssao.ao_pong_slices.clear();
- }
-
- int buffer_width;
- int buffer_height;
- int half_width;
- int half_height;
- if (ssao_half_size) {
- buffer_width = (rb->internal_width + 3) / 4;
- buffer_height = (rb->internal_height + 3) / 4;
- half_width = (rb->internal_width + 7) / 8;
- half_height = (rb->internal_height + 7) / 8;
- } else {
- buffer_width = (rb->internal_width + 1) / 2;
- buffer_height = (rb->internal_height + 1) / 2;
- half_width = (rb->internal_width + 3) / 4;
- half_height = (rb->internal_height + 3) / 4;
- }
- bool uniform_sets_are_invalid = false;
- if (rb->ss_effects.ssao.ao_deinterleaved.is_null()) {
- {
- rb->ss_effects.ssao.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_deinterleaved, "SSAO De-interleaved Array");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_deinterleaved, i, 0);
- rb->ss_effects.ssao.ao_deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_pong, "SSAO De-interleaved Array Pong");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_pong, i, 0);
- rb->ss_effects.ssao.ao_pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = half_width;
- tf.height = half_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[0], "SSAO Importance Map");
- rb->ss_effects.ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[1], "SSAO Importance Map Pong");
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_final, "SSAO Final");
- }
- ssao_using_half_size = ssao_half_size;
- uniform_sets_are_invalid = true;
- }
-
- EffectsRD::SSAOSettings settings;
+ RendererRD::SSEffects::SSAOSettings settings;
settings.radius = env->ssao_radius;
settings.intensity = env->ssao_intensity;
settings.power = env->ssao_power;
@@ -2153,13 +1989,14 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.fadeout_from = ssao_fadeout_from;
settings.fadeout_to = ssao_fadeout_to;
settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
- settings.half_screen_size = Size2i(buffer_width, buffer_height);
- settings.quarter_screen_size = Size2i(half_width, half_height);
- RendererCompositorRD::singleton->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set);
+ ss_effects->ssao_allocate_buffers(rb->ss_effects.ssao, settings, rb->ss_effects.linear_depth);
+ ss_effects->generate_ssao(rb->ss_effects.ssao, p_normal_buffer, p_projection, settings);
}
-void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) {
+void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) {
+ ERR_FAIL_NULL(ss_effects);
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -2168,133 +2005,7 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen
RENDER_TIMESTAMP("Process SSIL");
- if (rb->ss_effects.ssil.ssil_final.is_valid() && ssil_using_half_size != ssil_half_size) {
- RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
- RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssil.pong);
- RD::get_singleton()->free(rb->ss_effects.ssil.edges);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
-
- rb->ss_effects.ssil.ssil_final = RID();
- rb->ss_effects.ssil.deinterleaved = RID();
- rb->ss_effects.ssil.pong = RID();
- rb->ss_effects.ssil.edges = RID();
- rb->ss_effects.ssil.deinterleaved_slices.clear();
- rb->ss_effects.ssil.pong_slices.clear();
- rb->ss_effects.ssil.edges_slices.clear();
- rb->ss_effects.ssil.importance_map[0] = RID();
- rb->ss_effects.ssil.importance_map[1] = RID();
- }
-
- int buffer_width;
- int buffer_height;
- int half_width;
- int half_height;
- if (ssil_half_size) {
- buffer_width = (rb->width + 3) / 4;
- buffer_height = (rb->height + 3) / 4;
- half_width = (rb->width + 7) / 8;
- half_height = (rb->height + 7) / 8;
- } else {
- buffer_width = (rb->width + 1) / 2;
- buffer_height = (rb->height + 1) / 2;
- half_width = (rb->width + 3) / 4;
- half_height = (rb->height + 3) / 4;
- }
- bool uniform_sets_are_invalid = false;
- if (rb->ss_effects.ssil.ssil_final.is_null()) {
- {
- rb->ss_effects.ssil.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- rb->ss_effects.ssil.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.ssil_final, "SSIL texture");
- RD::get_singleton()->texture_clear(rb->ss_effects.ssil.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
- if (rb->ss_effects.last_frame.is_null()) {
- tf.mipmaps = 6;
- rb->ss_effects.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.last_frame, "Last Frame Radiance");
- RD::get_singleton()->texture_clear(rb->ss_effects.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
- for (uint32_t i = 0; i < 6; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.last_frame, 0, i);
- rb->ss_effects.last_frame_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
- }
- }
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.deinterleaved, "SSIL deinterleaved buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.deinterleaved, i, 0);
- rb->ss_effects.ssil.deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.pong, "SSIL deinterleaved pong buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.pong, i, 0);
- rb->ss_effects.ssil.pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.edges, "SSIL edges buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.edges, i, 0);
- rb->ss_effects.ssil.edges_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = half_width;
- tf.height = half_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[0], "SSIL Importance Map");
- rb->ss_effects.ssil.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[1], "SSIL Importance Map Pong");
- }
- uniform_sets_are_invalid = true;
- ssil_using_half_size = ssil_half_size;
- }
-
- EffectsRD::SSILSettings settings;
+ RendererRD::SSEffects::SSILSettings settings;
settings.radius = env->ssil_radius;
settings.intensity = env->ssil_intensity;
settings.sharpness = env->ssil_sharpness;
@@ -2307,17 +2018,16 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen
settings.fadeout_from = ssil_fadeout_from;
settings.fadeout_to = ssil_fadeout_to;
settings.full_screen_size = Size2i(rb->width, rb->height);
- settings.half_screen_size = Size2i(buffer_width, buffer_height);
- settings.quarter_screen_size = Size2i(half_width, half_height);
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_projection;
+ Projection projection = correction * p_projection;
Transform3D transform = p_transform;
transform.set_origin(Vector3(0.0, 0.0, 0.0));
- CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse();
+ Projection last_frame_projection = rb->ss_effects.last_frame_projection * Projection(rb->ss_effects.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse();
- RendererCompositorRD::singleton->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set);
+ ss_effects->ssil_allocate_buffers(rb->ss_effects.ssil, settings, rb->ss_effects.linear_depth);
+ ss_effects->screen_space_indirect_lighting(rb->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings);
rb->ss_effects.last_frame_projection = projection;
rb->ss_effects.last_frame_transform = transform;
}
@@ -2326,15 +2036,15 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- if (rb->ss_effects.last_frame.is_valid()) {
- copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
+ if (rb->ss_effects.ssil.last_frame.is_valid()) {
+ copy_effects->copy_to_rect(rb->texture, rb->ss_effects.ssil.last_frame, Rect2i(0, 0, rb->width, rb->height));
int width = rb->width;
int height = rb->height;
- for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) {
+ for (int i = 0; i < rb->ss_effects.ssil.last_frame_slices.size() - 1; i++) {
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
- copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
+ copy_effects->make_mipmap(rb->ss_effects.ssil.last_frame_slices[i], rb->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height));
}
}
}
@@ -3480,17 +3190,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
- CameraMatrix matrix = li->shadow_transform[j].camera;
+ Projection matrix = li->shadow_transform[j].camera;
float split = li->shadow_transform[MIN(limit, j)].split;
- CameraMatrix bias;
+ Projection bias;
bias.set_light_bias();
- CameraMatrix rectm;
+ Projection rectm;
rectm.set_light_atlas_rect(atlas_rect);
Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
- CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
+ Projection shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
float bias_scale = li->shadow_transform[j].bias_scale;
light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
@@ -3758,16 +3468,16 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.direction[1] = omni_offset.y * float(rect.size.height);
} else if (type == RS::LIGHT_SPOT) {
Transform3D modelview = (inverse_transform * light_transform).inverse();
- CameraMatrix bias;
+ Projection bias;
bias.set_light_bias();
- CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
+ Projection shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix);
if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
// Only enable PCSS-like soft shadows if blurring is enabled.
// Otherwise, performance would decrease with no visual difference.
- CameraMatrix cm = li->shadow_transform[0].camera;
+ Projection cm = li->shadow_transform[0].camera;
float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
} else {
@@ -3978,238 +3688,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
////////////////////////////////////////////////////////////////////////////////
// FOG SHADER
-void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
- //compile
-
- code = p_code;
- valid = false;
- ubo_size = 0;
- uniforms.clear();
-
- if (code.is_empty()) {
- return; //just invalid, but no error
- }
-
- ShaderCompiler::GeneratedCode gen_code;
- ShaderCompiler::IdentifierActions actions;
- actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
-
- uses_time = false;
-
- actions.usage_flag_pointers["TIME"] = &uses_time;
-
- actions.uniforms = &uniforms;
-
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
- ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
-
- if (version.is_null()) {
- version = scene_singleton->volumetric_fog.shader.version_create();
- }
-
- scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
- ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version));
-
- ubo_size = gen_code.uniform_total_size;
- ubo_offsets = gen_code.uniform_offsets;
- texture_uniforms = gen_code.texture_uniforms;
-
- pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0));
-
- valid = true;
-}
-
-void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
- if (!p_texture.is_valid()) {
- if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
- default_texture_params[p_name].erase(p_index);
-
- if (default_texture_params[p_name].is_empty()) {
- default_texture_params.erase(p_name);
- }
- }
- } else {
- if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = HashMap<int, RID>();
- }
- default_texture_params[p_name][p_index] = p_texture;
- }
-}
-
-void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- RBMap<int, StringName> order;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- if (E.value.texture_order >= 0) {
- order[E.value.texture_order + 100000] = E.key;
- } else {
- order[E.value.order] = E.key;
- }
- }
-
- for (const KeyValue<int, StringName> &E : order) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
- pi.name = E.value;
- p_param_list->push_back(pi);
- }
-}
-
-void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- RendererMaterialStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E.value);
- p.info.name = E.key; //supply name
- p.index = E.value.instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
- p_param_list->push_back(p);
- }
-}
-
-bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
-bool RendererSceneRenderRD::FogShaderData::is_animated() const {
- return false;
-}
-
-bool RendererSceneRenderRD::FogShaderData::casts_shadows() const {
- return false;
-}
-
-Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
- if (uniforms.has(p_parameter)) {
- ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
- Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
-RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
-}
-
-RendererSceneRenderRD::FogShaderData::~FogShaderData() {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
- ERR_FAIL_COND(!scene_singleton);
- //pipeline variants will clear themselves if shader is gone
- if (version.is_valid()) {
- scene_singleton->volumetric_fog.shader.version_free(version);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Fog material
-
-bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- uniform_set_updated = true;
-
- 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, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
-}
-
-RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
- free_parameters_uniform_set(uniform_set);
-}
-
-RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
- FogShaderData *shader_data = memnew(FogShaderData);
- return shader_data;
-}
-
-RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
- return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
-};
-
-RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
- FogMaterialData *material_data = memnew(FogMaterialData);
- material_data->shader_data = p_shader;
- //update will happen later anyway so do nothing.
- return material_data;
-}
-
-RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
- return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Volumetric Fog
-
-void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
- ERR_FAIL_COND(!rb->volumetric_fog);
-
- RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
- RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
- RD::get_singleton()->free(rb->volumetric_fog->fog_map);
- RD::get_singleton()->free(rb->volumetric_fog->density_map);
- RD::get_singleton()->free(rb->volumetric_fog->light_map);
- RD::get_singleton()->free(rb->volumetric_fog->emissive_map);
-
- if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
- }
- if (rb->volumetric_fog->process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set_density);
- }
- if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
- }
- if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
- }
- if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set);
- }
- if (rb->volumetric_fog->sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sky_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->sky_uniform_set);
- }
-
- memdelete(rb->volumetric_fog);
-
- rb->volumetric_fog = nullptr;
-}
-
-Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
- Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
- view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
- Vector3 fog_position = Vector3(0, 0, 0);
-
- view_position.y = -view_position.y;
- fog_position.z = -view_position.z / fog_end;
- fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
- fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
- fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
- fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
-
- fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
- fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
- fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
-
- return Vector3i(fog_position);
-}
-
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
+void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -4222,7 +3701,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (rb->volumetric_fog) {
//validate
if (!env || !env->volumetric_fog_enabled || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) {
- _volumetric_fog_erase(rb);
+ memdelete(rb->volumetric_fog);
+ rb->volumetric_fog = nullptr;
}
}
@@ -4231,684 +3711,38 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
return;
}
- RENDER_TIMESTAMP("> Volumetric Fog");
- RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
-
if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
//required volumetric fog but not existing, create
- rb->volumetric_fog = memnew(VolumetricFog);
- rb->volumetric_fog->width = target_width;
- rb->volumetric_fog->height = target_height;
- rb->volumetric_fog->depth = volumetric_fog_depth;
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = target_width;
- tf.height = target_height;
- tf.depth = volumetric_fog_depth;
- tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
-
- rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map");
-
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
-
- rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
-
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
-
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- Vector<uint8_t> dm;
- dm.resize(target_width * target_height * volumetric_fog_depth * 4);
- dm.fill(0);
-
- rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
- rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
- rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
-#else
- tf.format = RD::DATA_FORMAT_R32_UINT;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
- rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
- rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
-#endif
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.append_id(rb->volumetric_fog->fog_map);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG);
+ rb->volumetric_fog = memnew(RendererRD::Fog::VolumetricFog(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd));
}
- if (p_fog_volumes.size() > 0) {
- RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
-
- RENDER_TIMESTAMP("Render FogVolumes");
-
- VolumetricFogShader::VolumeUBO params;
-
- Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
- Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
- float z_near = p_cam_projection.get_z_near();
- float z_far = p_cam_projection.get_z_far();
- float fog_end = env->volumetric_fog_length;
-
- Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
- Vector2 fog_near_size;
- if (p_cam_projection.is_orthogonal()) {
- fog_near_size = fog_far_size;
- } else {
- fog_near_size = Vector2();
- }
-
- params.fog_frustum_size_begin[0] = fog_near_size.x;
- params.fog_frustum_size_begin[1] = fog_near_size.y;
-
- params.fog_frustum_size_end[0] = fog_far_size.x;
- params.fog_frustum_size_end[1] = fog_far_size.y;
-
- params.fog_frustum_end = fog_end;
- params.z_near = z_near;
- params.z_far = z_far;
- params.time = time;
-
- params.fog_volume_size[0] = rb->volumetric_fog->width;
- params.fog_volume_size[1] = rb->volumetric_fog->height;
- params.fog_volume_size[2] = rb->volumetric_fog->depth;
-
- params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
- params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
- params.detail_spread = env->volumetric_fog_detail_spread;
- params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
-
- Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
- RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
- RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform);
-
- RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
-
- if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 1;
- u.append_id(rb->volumetric_fog->emissive_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(volumetric_fog.volume_ubo);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 3;
- u.append_id(rb->volumetric_fog->density_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 4;
- u.append_id(rb->volumetric_fog->light_map);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- bool any_uses_time = false;
-
- 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]);
- ERR_FAIL_COND(!fog_volume_instance);
- RID fog_volume = fog_volume_instance->volume;
-
- RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume);
-
- FogMaterialData *material = nullptr;
-
- if (fog_material.is_valid()) {
- material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- fog_material = volumetric_fog.default_material;
- material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
- }
-
- ERR_FAIL_COND(!material);
-
- FogShaderData *shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
-
- any_uses_time |= shader_data->uses_time;
-
- Vector3i min = Vector3i();
- Vector3i max = Vector3i();
- Vector3i kernel_size = Vector3i();
-
- Vector3 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_extents(fog_volume);
-
- if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
- // Local fog volume.
- Vector3i points[8];
- points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- 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, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 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, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 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, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 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, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 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, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 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, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
-
- min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1);
- max = Vector3i(1, 1, 1);
-
- for (int j = 0; j < 8; j++) {
- min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
- max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
- }
-
- kernel_size = max - min;
- } else {
- // Volume type global runs on all cells
- extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- min = Vector3i(0, 0, 0);
- kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth));
- }
-
- if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
- continue;
- }
-
- volumetric_fog.push_constant.position[0] = position.x;
- volumetric_fog.push_constant.position[1] = position.y;
- volumetric_fog.push_constant.position[2] = position.z;
- volumetric_fog.push_constant.extents[0] = extents.x;
- volumetric_fog.push_constant.extents[1] = extents.y;
- volumetric_fog.push_constant.extents[2] = extents.z;
- volumetric_fog.push_constant.corner[0] = min.x;
- volumetric_fog.push_constant.corner[1] = min.y;
- volumetric_fog.push_constant.corner[2] = min.z;
- volumetric_fog.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(), volumetric_fog.push_constant.transform);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
- if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
- }
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
- }
- if (any_uses_time || env->volumetric_fog_temporal_reprojection) {
- RenderingServerDefault::redraw_request();
- }
-
- RD::get_singleton()->draw_command_end_label();
-
- RD::get_singleton()->compute_list_end();
- }
-
- if (rb->volumetric_fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) {
- //re create uniform set if needed
- Vector<RD::Uniform> uniforms;
- Vector<RD::Uniform> copy_uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- } else {
- u.append_id(shadow_atlas->depth);
- }
-
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- if (directional_shadow.depth.is_valid()) {
- u.append_id(directional_shadow.depth);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- }
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 3;
- u.append_id(get_omni_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 4;
- u.append_id(get_spot_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 5;
- u.append_id(get_directional_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 6;
- u.append_id(rb->cluster_builder->get_cluster_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 7;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
- u.append_id(rb->volumetric_fog->light_density_map);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->volumetric_fog->fog_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->volumetric_fog->prev_light_density_map);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 10;
- u.append_id(shadow_sampler);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 11;
- u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 12;
- for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) {
- u.append_id(rb->rbgi.voxel_gi_textures[i]);
- }
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 13;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 14;
- u.append_id(volumetric_fog.params_ubo);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 15;
- u.append_id(rb->volumetric_fog->prev_light_density_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 16;
- u.append_id(rb->volumetric_fog->density_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 17;
- u.append_id(rb->volumetric_fog->light_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 18;
- u.append_id(rb->volumetric_fog->emissive_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 19;
- RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
- u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
-
- rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
-
- RID aux7 = uniforms.write[7].get_id(0);
- RID aux8 = uniforms.write[8].get_id(0);
-
- uniforms.write[7].set_id(0, aux8);
- uniforms.write[8].set_id(0, aux7);
-
- rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
-
- uniforms.remove_at(8);
- uniforms.write[7].set_id(0, aux7);
- rb->volumetric_fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
- }
-
- bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr);
-
- if (using_sdfgi) {
- if (rb->volumetric_fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.append_id(gi.sdfgi_ubo);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- u.append_id(rb->sdfgi->ambient_texture);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- u.append_id(rb->sdfgi->occlusion_texture);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
- }
- }
-
- rb->volumetric_fog->length = env->volumetric_fog_length;
- rb->volumetric_fog->spread = env->volumetric_fog_detail_spread;
-
- VolumetricFogShader::ParamsUBO params;
-
- Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
- Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
- float z_near = p_cam_projection.get_z_near();
- float z_far = p_cam_projection.get_z_far();
- float fog_end = env->volumetric_fog_length;
-
- Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
- Vector2 fog_near_size;
- if (p_cam_projection.is_orthogonal()) {
- fog_near_size = fog_far_size;
- } else {
- fog_near_size = Vector2();
- }
-
- params.fog_frustum_size_begin[0] = fog_near_size.x;
- params.fog_frustum_size_begin[1] = fog_near_size.y;
-
- params.fog_frustum_size_end[0] = fog_far_size.x;
- params.fog_frustum_size_end[1] = fog_far_size.y;
-
- params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy;
- params.z_far = z_far;
-
- params.fog_frustum_end = fog_end;
-
- Color ambient_color = env->ambient_light.srgb_to_linear();
- params.ambient_color[0] = ambient_color.r;
- params.ambient_color[1] = ambient_color.g;
- params.ambient_color[2] = ambient_color.b;
- params.sky_contribution = env->ambient_sky_contribution;
-
- params.fog_volume_size[0] = rb->volumetric_fog->width;
- params.fog_volume_size[1] = rb->volumetric_fog->height;
- params.fog_volume_size[2] = rb->volumetric_fog->depth;
-
- params.directional_light_count = p_directional_light_count;
-
- Color emission = env->volumetric_fog_emission.srgb_to_linear();
- params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
- params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
- params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
- params.base_density = env->volumetric_fog_density;
-
- Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear();
- params.base_scattering[0] = base_scattering.r;
- params.base_scattering[1] = base_scattering.g;
- params.base_scattering[2] = base_scattering.b;
- params.phase_g = env->volumetric_fog_anisotropy;
-
- params.detail_spread = env->volumetric_fog_detail_spread;
- params.gi_inject = env->volumetric_fog_gi_inject;
-
- params.cam_rotation[0] = p_cam_transform.basis[0][0];
- params.cam_rotation[1] = p_cam_transform.basis[1][0];
- params.cam_rotation[2] = p_cam_transform.basis[2][0];
- params.cam_rotation[3] = 0;
- params.cam_rotation[4] = p_cam_transform.basis[0][1];
- params.cam_rotation[5] = p_cam_transform.basis[1][1];
- params.cam_rotation[6] = p_cam_transform.basis[2][1];
- params.cam_rotation[7] = 0;
- params.cam_rotation[8] = p_cam_transform.basis[0][2];
- params.cam_rotation[9] = p_cam_transform.basis[1][2];
- params.cam_rotation[10] = p_cam_transform.basis[2][2];
- params.cam_rotation[11] = 0;
- params.filter_axis = 0;
- params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0;
- params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
-
- Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
- RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
-
- params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
- params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
-
- {
- uint32_t cluster_size = rb->cluster_builder->get_cluster_size();
- params.cluster_shift = get_shift_from_power_of_2(cluster_size);
-
- uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1;
- uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1;
- params.max_cluster_element_count_div_32 = max_cluster_elements / 32;
- params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
- params.cluster_width = cluster_screen_width;
-
- params.screen_size[0] = rb->width;
- params.screen_size[1] = rb->height;
- }
-
- Basis sky_transform = env->sky_orientation;
- sky_transform = sky_transform.inverse() * p_cam_transform.basis;
- RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
-
- RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
-
- RENDER_TIMESTAMP("Render Fog");
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set_density, 0);
-
- if (using_sdfgi) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- // Copy fog to history buffer
- if (env->volumetric_fog_temporal_reprojection) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- RD::get_singleton()->draw_command_end_label();
-
- if (volumetric_fog_filter_active) {
- RD::get_singleton()->draw_command_begin_label("Filter Fog");
-
- RENDER_TIMESTAMP("Filter Fog");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
-
- RD::get_singleton()->compute_list_end();
- //need restart for buffer update
-
- params.filter_axis = 1;
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
+ if (rb->volumetric_fog) {
+ RendererRD::Fog::VolumetricFogSettings settings;
+ settings.rb_size = Vector2i(rb->width, rb->height);
+ settings.time = time;
+ settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array();
+ settings.max_cluster_elements = max_cluster_elements;
+ settings.volumetric_fog_filter_active = volumetric_fog_filter_active;
+
+ settings.shadow_sampler = shadow_sampler;
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
+ settings.shadow_atlas_depth = shadow_atlas ? shadow_atlas->depth : RID();
+ settings.voxel_gl_buffer = render_buffers_get_voxel_gi_buffer(p_render_buffers);
+ settings.omni_light_buffer = get_omni_light_buffer();
+ settings.spot_light_buffer = get_spot_light_buffer();
+ settings.directional_shadow_depth = directional_shadow.depth;
+ settings.directional_light_buffer = get_directional_light_buffer();
- compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ settings.vfog = rb->volumetric_fog;
+ settings.cluster_builder = rb->cluster_builder;
+ settings.rbgi = &rb->rbgi;
+ settings.sdfgi = rb->sdfgi;
+ settings.env = env;
+ settings.sky = &sky;
+ settings.gi = &gi;
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label();
+ RendererRD::Fog::get_singleton()->volumetric_fog_update(settings, p_cam_projection, p_cam_transform, p_prev_cam_inv_transform, p_shadow_atlas, p_directional_light_count, p_use_directional_shadows, p_positional_light_count, p_voxel_gi_count, p_fog_volumes);
}
-
- RENDER_TIMESTAMP("Integrate Fog");
- RD::get_singleton()->draw_command_begin_label("Integrate Fog");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1);
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
-
- RENDER_TIMESTAMP("< Volumetric Fog");
- RD::get_singleton()->draw_command_end_label();
- RD::get_singleton()->draw_command_end_label();
}
bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
@@ -5031,7 +3865,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier
}
- if (p_render_data->render_buffers.is_valid()) {
+ if (p_render_data->render_buffers.is_valid() && ss_effects) {
if (p_use_ssao || p_use_ssil) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -5056,7 +3890,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
invalidate_uniform_set = true;
}
- RendererCompositorRD::singleton->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection);
+ ss_effects->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection);
}
if (p_use_ssao) {
@@ -5113,7 +3947,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
// getting this here now so we can direct call a bunch of things more easily
@@ -5308,7 +4142,7 @@ void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
}
}
-void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
+void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_light);
ERR_FAIL_COND(!light_instance);
@@ -5329,7 +4163,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
bool flip_y = false;
- CameraMatrix light_projection;
+ Projection light_projection;
Transform3D light_transform;
if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
@@ -5471,7 +4305,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true);
//restore transform so it can be properly used
- light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0);
+ light_instance_set_shadow_transform(p_light, Projection(), light_instance->transform, zfar, 0, 0, 0);
}
} else {
@@ -5480,16 +4314,16 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
}
}
-void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
_render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
- CameraMatrix cm;
+ Projection cm;
cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
Vector3 cam_pos = p_transform.origin;
@@ -5514,7 +4348,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
rb->sdfgi = nullptr;
}
if (rb->volumetric_fog) {
- _volumetric_fog_erase(rb);
+ memdelete(rb->volumetric_fog);
+ rb->volumetric_fog = nullptr;
}
if (rb->cluster_builder) {
memdelete(rb->cluster_builder);
@@ -5589,8 +4424,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
} else if (shadow_atlas_owner.owns(p_rid)) {
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);
- } else if (fog_volume_instance_owner.owns(p_rid)) {
- fog_volume_instance_owner.free(p_rid);
+ } else if (RendererRD::Fog::get_singleton()->owns_fog_volume_instance(p_rid)) {
+ RendererRD::Fog::get_singleton()->fog_instance_free(p_rid);
} else {
return false;
}
@@ -5662,7 +4497,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
//RID sampled_light;
- GeometryInstance *gi = geometry_instance_create(p_base);
+ RenderGeometryInstance *gi = geometry_instance_create(p_base);
uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base);
Vector<RID> materials;
@@ -5674,7 +4509,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
}
}
- geometry_instance_set_surface_materials(gi, materials);
+ gi->set_surface_materials(materials);
if (cull_argument.size() == 0) {
cull_argument.push_back(nullptr);
@@ -5784,8 +4619,6 @@ RendererSceneRenderRD::RendererSceneRenderRD() {
}
void RendererSceneRenderRD::init() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
max_cluster_elements = get_max_elements();
directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
@@ -5836,124 +4669,7 @@ void RendererSceneRenderRD::init() {
}
if (is_volumetric_supported()) {
- {
- // Initialize local fog shader
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("");
- volumetric_fog.shader.initialize(volumetric_fog_modes);
-
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
- volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
- }
-
- {
- ShaderCompiler::DefaultIdentifierActions actions;
-
- actions.renames["TIME"] = "scene_params.time";
- actions.renames["PI"] = _MKSTR(Math_PI);
- actions.renames["TAU"] = _MKSTR(Math_TAU);
- actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["WORLD_POSITION"] = "world.xyz";
- actions.renames["OBJECT_POSITION"] = "params.position";
- actions.renames["UVW"] = "uvw";
- actions.renames["EXTENTS"] = "params.extents";
- actions.renames["ALBEDO"] = "albedo";
- actions.renames["DENSITY"] = "density";
- actions.renames["EMISSION"] = "emission";
- actions.renames["SDF"] = "sdf";
-
- actions.usage_defines["SDF"] = "#define SDF_USED\n";
- actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
- actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
- actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
-
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
- actions.base_uniform_string = "material.";
-
- actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
- actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
- actions.global_buffer_array_variable = "global_variables.data";
-
- volumetric_fog.compiler.initialize(actions);
- }
-
- {
- // default material and shader for fog shader
- volumetric_fog.default_shader = material_storage->shader_allocate();
- material_storage->shader_initialize(volumetric_fog.default_shader);
- material_storage->shader_set_code(volumetric_fog.default_shader, R"(
-// Default fog shader.
-
-shader_type fog;
-
-void fog() {
- DENSITY = 1.0;
- ALBEDO = vec3(1.0);
-}
-)");
- volumetric_fog.default_material = material_storage->material_allocate();
- material_storage->material_initialize(volumetric_fog.default_material);
- material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
-
- FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG));
- volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
-
- Vector<RD::Uniform> uniforms;
-
- {
- Vector<RID> ids;
- ids.resize(12);
- RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-
- RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
- uniforms.push_back(u);
- }
-
- volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
- }
- {
- String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
- defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
- if (is_using_radiance_cubemap_array()) {
- defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
- }
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
- volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
- volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
- volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
-
- volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
- volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
- for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
- volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
- }
- volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
- }
+ RendererRD::Fog::get_singleton()->init_fog_shader(cluster.max_directional_lights, get_roughness_layers(), is_using_radiance_cubemap_array());
}
{
@@ -6000,11 +4716,12 @@ void fog() {
copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
tone_mapper = memnew(RendererRD::ToneMapper);
vrs = memnew(RendererRD::VRS);
+ if (can_use_storage) {
+ ss_effects = memnew(RendererRD::SSEffects);
+ }
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
if (bokeh_dof) {
memdelete(bokeh_dof);
}
@@ -6017,6 +4734,9 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
if (vrs) {
memdelete(vrs);
}
+ if (ss_effects) {
+ memdelete(ss_effects);
+ }
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
RD::get_singleton()->free(E.value.cubemap);
@@ -6031,11 +4751,7 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
}
if (is_volumetric_supported()) {
- volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
- RD::get_singleton()->free(volumetric_fog.volume_ubo);
- RD::get_singleton()->free(volumetric_fog.params_ubo);
- material_storage->shader_free(volumetric_fog.default_shader);
- material_storage->material_free(volumetric_fog.default_material);
+ RendererRD::Fog::get_singleton()->free_fog_shader();
}
memdelete_arr(directional_penumbra_shadow_kernel);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index d11bbd183e..8b2c159660 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_RD_H
-#define RENDERING_SERVER_SCENE_RENDER_RD_H
+#ifndef RENDERER_SCENE_RENDER_RD_H
+#define RENDERER_SCENE_RENDER_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
@@ -37,13 +37,13 @@
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/effects/ss_effects.h"
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
#include "servers/rendering/renderer_rd/effects/vrs.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/environment/gi.h"
+#include "servers/rendering/renderer_rd/environment/sky.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
-#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -52,24 +52,24 @@ struct RenderDataRD {
RID render_buffers;
Transform3D cam_transform;
- CameraMatrix cam_projection;
+ Projection cam_projection;
Vector2 taa_jitter;
bool cam_orthogonal = false;
// For stereo rendering
uint32_t view_count = 1;
Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Transform3D prev_cam_transform;
- CameraMatrix prev_cam_projection;
+ Projection prev_cam_projection;
Vector2 prev_taa_jitter;
- CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
float z_near = 0.0;
float z_far = 0.0;
- const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr;
+ const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
const PagedArray<RID> *voxel_gi_instances = nullptr;
@@ -98,7 +98,7 @@ struct RenderDataRD {
};
class RendererSceneRenderRD : public RendererSceneRender {
- friend RendererSceneSkyRD;
+ friend RendererRD::SkyRD;
friend RendererRD::GI;
protected:
@@ -122,16 +122,16 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
virtual void _render_shadow_begin() = 0;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
- void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
+ void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void _debug_draw_cluster(RID p_render_buffers);
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
@@ -140,10 +140,11 @@ protected:
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
- void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
- void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
- void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
- void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform);
+ void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
+ void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
+ void _process_sss(RID p_render_buffers, const Projection &p_camera);
+ void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
+
void _copy_framebuffer_to_ssil(RID p_render_buffers);
void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
@@ -160,11 +161,12 @@ protected:
void _disable_clear_request(const RenderDataRD *p_render_data);
// needed for a single argument calls (material and uv2)
- PagedArrayPool<GeometryInstance *> cull_argument_pool;
- PagedArray<GeometryInstance *> cull_argument; //need this to exist
+ PagedArrayPool<RenderGeometryInstance *> cull_argument_pool;
+ PagedArray<RenderGeometryInstance *> cull_argument; //need this to exist
+ RendererRD::SSEffects *ss_effects = nullptr;
RendererRD::GI gi;
- RendererSceneSkyRD sky;
+ RendererRD::SkyRD sky;
RendererSceneEnvironmentRD *get_environment(RID p_environment) {
if (p_environment.is_valid()) {
@@ -209,7 +211,7 @@ private:
struct Reflection {
RID owner;
- RendererSceneSkyRD::ReflectionData data;
+ RendererRD::SkyRD::ReflectionData data;
RID fbs[6];
};
@@ -362,7 +364,7 @@ private:
struct LightInstance {
struct ShadowTransform {
- CameraMatrix camera;
+ Projection camera;
Transform3D transform;
float farplane;
float split;
@@ -404,21 +406,10 @@ private:
mutable RID_Owner<LightInstance> light_instance_owner;
- /* FOG VOLUMES */
-
- struct FogVolumeInstance {
- RID volume;
- Transform3D transform;
- bool active = false;
- };
-
- mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
-
/* ENVIRONMENT */
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
bool ssao_half_size = false;
- bool ssao_using_half_size = false;
float ssao_adaptive_target = 0.5;
int ssao_blur_passes = 2;
float ssao_fadeout_from = 50.0;
@@ -469,8 +460,6 @@ private:
ClusterBuilderSharedDataRD cluster_builder_shared;
ClusterBuilderRD *current_cluster_builder = nullptr;
- struct VolumetricFog;
-
struct RenderBuffers {
RenderBufferData *data = nullptr;
int internal_width = 0;
@@ -506,8 +495,8 @@ private:
Vector<View> views;
RendererRD::GI::SDFGI *sdfgi = nullptr;
- VolumetricFog *volumetric_fog = nullptr;
RendererRD::GI::RenderBuffersGI rbgi;
+ RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr;
ClusterBuilderRD *cluster_builder = nullptr;
@@ -561,47 +550,14 @@ private:
RID downsample_uniform_set;
- RID last_frame;
- Vector<RID> last_frame_slices;
-
- CameraMatrix last_frame_projection;
+ Projection last_frame_projection;
Transform3D last_frame_transform;
- struct SSAO {
- RID ao_deinterleaved;
- Vector<RID> ao_deinterleaved_slices;
- RID ao_pong;
- Vector<RID> ao_pong_slices;
- RID ao_final;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- } ssao;
-
- struct SSIL {
- RID ssil_final;
- RID deinterleaved;
- Vector<RID> deinterleaved_slices;
- RID pong;
- Vector<RID> pong_slices;
- RID edges;
- Vector<RID> edges_slices;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- RID projection_uniform_set;
- } ssil;
+ RendererRD::SSEffects::SSAORenderBuffers ssao;
+ RendererRD::SSEffects::SSILRenderBuffers ssil;
} ss_effects;
- struct SSR {
- RID normal_scaled;
- RID depth_scaled;
- RID blur_radius[2];
- } ssr;
+ RendererRD::SSEffects::SSRRenderBuffers ssr;
struct TAA {
RID history;
@@ -780,203 +736,6 @@ private:
bool depth_prepass_used; // this does not seem used anywhere...
} render_state;
- struct VolumetricFog {
- enum {
- MAX_TEMPORAL_FRAMES = 16
- };
-
- uint32_t width = 0;
- uint32_t height = 0;
- uint32_t depth = 0;
-
- float length;
- float spread;
-
- RID light_density_map;
- RID prev_light_density_map;
- RID fog_map;
- RID density_map;
- RID light_map;
- RID emissive_map;
-
- RID fog_uniform_set;
- RID copy_uniform_set;
- RID process_uniform_set_density;
- RID process_uniform_set;
- RID process_uniform_set2;
- RID sdfgi_uniform_set;
- RID sky_uniform_set;
-
- int last_shadow_filter = -1;
- };
-
- struct VolumetricFogShader {
- enum FogSet {
- FOG_SET_BASE,
- FOG_SET_UNIFORMS,
- FOG_SET_MATERIAL,
- FOG_SET_MAX,
- };
-
- struct FogPushConstant {
- float position[3];
- float pad;
-
- float extents[3];
- float pad2;
-
- int32_t corner[3];
- uint32_t shape;
-
- float transform[16];
- };
-
- struct VolumeUBO {
- float fog_frustum_size_begin[2];
- float fog_frustum_size_end[2];
-
- float fog_frustum_end;
- float z_near;
- float z_far;
- float time;
-
- int32_t fog_volume_size[3];
- uint32_t directional_light_count;
-
- uint32_t use_temporal_reprojection;
- uint32_t temporal_frame;
- float detail_spread;
- float temporal_blend;
-
- float to_prev_view[16];
- float transform[16];
- };
-
- ShaderCompiler compiler;
- VolumetricFogShaderRD shader;
- FogPushConstant push_constant;
- RID volume_ubo;
-
- RID default_shader;
- RID default_material;
- RID default_shader_rd;
-
- RID base_uniform_set;
-
- RID params_ubo;
-
- enum {
- VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
- VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
- VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
- VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
- VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
- VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
- };
-
- struct ParamsUBO {
- float fog_frustum_size_begin[2];
- float fog_frustum_size_end[2];
-
- float fog_frustum_end;
- float ambient_inject;
- float z_far;
- uint32_t filter_axis;
-
- float ambient_color[3];
- float sky_contribution;
-
- int32_t fog_volume_size[3];
- uint32_t directional_light_count;
-
- float base_emission[3];
- float base_density;
-
- float base_scattering[3];
- float phase_g;
-
- float detail_spread;
- float gi_inject;
- uint32_t max_voxel_gi_instances;
- uint32_t cluster_type_size;
-
- float screen_size[2];
- uint32_t cluster_shift;
- uint32_t cluster_width;
-
- uint32_t max_cluster_element_count_div_32;
- uint32_t use_temporal_reprojection;
- uint32_t temporal_frame;
- float temporal_blend;
-
- float cam_rotation[12];
- float to_prev_view[16];
- float radiance_inverse_xform[12];
- };
-
- VolumetricFogProcessShaderRD process_shader;
-
- RID process_shader_version;
- RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
-
- } volumetric_fog;
-
- uint32_t volumetric_fog_depth = 128;
- uint32_t volumetric_fog_size = 128;
- bool volumetric_fog_filter_active = true;
-
- Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
- void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
-
- struct FogShaderData : public RendererRD::ShaderData {
- bool valid = false;
- RID version;
-
- RID pipeline;
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size = 0;
-
- String path;
- String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
-
- bool uses_time = false;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
- virtual bool is_animated() const;
- virtual bool casts_shadows() const;
- virtual Variant get_default_parameter(const StringName &p_parameter) const;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const;
-
- FogShaderData() {}
- virtual ~FogShaderData();
- };
-
- struct FogMaterialData : public RendererRD::MaterialData {
- FogShaderData *shader_data = nullptr;
- RID uniform_set;
- bool uniform_set_updated;
-
- virtual void set_render_priority(int p_priority) {}
- virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~FogMaterialData();
- };
-
- RendererRD::ShaderData *_create_fog_shader_func();
- static RendererRD::ShaderData *_create_fog_shader_funcs();
-
- RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
- static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
-
RID shadow_sampler;
uint64_t scene_pass = 0;
@@ -991,12 +750,17 @@ private:
uint32_t max_cluster_elements = 512;
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
-public:
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
+ /* Volumetric Fog */
+ uint32_t volumetric_fog_size = 128;
+ uint32_t volumetric_fog_depth = 128;
+ bool volumetric_fog_filter_active = true;
+
+ void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+
+public:
/* GI */
RendererRD::GI *get_gi() { return &gi; }
@@ -1150,7 +914,7 @@ public:
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
virtual void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
@@ -1199,7 +963,7 @@ public:
return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
}
- _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
+ _FORCE_INLINE_ Projection light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].camera;
}
@@ -1393,7 +1157,7 @@ public:
virtual RID voxel_gi_instance_create(RID p_base) override;
virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
virtual bool voxel_gi_needs_update(RID p_probe) const override;
- virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) override { gi.voxel_gi_quality = p_quality; }
/* render buffers */
@@ -1436,11 +1200,11 @@ public:
virtual void update_uniform_sets(){};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
virtual void set_scene_pass(uint64_t p_pass) override {
scene_pass = p_pass;
@@ -1519,4 +1283,4 @@ public:
~RendererSceneRenderRD();
};
-#endif // RASTERIZER_SCENE_RD_H
+#endif // RENDERER_SCENE_RENDER_RD_H
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 04e05380f1..c9b6d09d4c 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -177,7 +177,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
builder.append("#define MOLTENVK_USED\n");
#endif
} break;
@@ -476,7 +476,9 @@ void ShaderRD::_compile_version(Version *p_version) {
#if 1
- RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, p_version, variant_defines.size(), -1, true, SNAME("ShaderCompilation"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
#else
for (int i = 0; i < variant_defines.size(); i++) {
_compile_variant(i, p_version);
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
index a416891ff2..d85ab3af2e 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
@@ -32,12 +32,17 @@ layout(push_constant, std430) uniform Params {
bool use_half_res;
uint metallic_mask;
- mat4 projection;
+ uint view_index;
+ uint pad1;
+ uint pad2;
+ uint pad3;
}
params;
+#include "screen_space_reflection_inc.glsl"
+
vec2 view_to_screen(vec3 view_pos, out float w) {
- vec4 projected = params.projection * vec4(view_pos, 1.0);
+ vec4 projected = scene_data.projection[params.view_index] * vec4(view_pos, 1.0);
projected.xyz /= projected.w;
projected.xy = projected.xy * 0.5 + 0.5;
w = projected.w;
@@ -46,24 +51,16 @@ vec2 view_to_screen(vec3 view_pos, out float w) {
#define M_PI 3.14159265359
-vec3 reconstructCSPosition(vec2 S, float z) {
- if (params.orthogonal) {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
- } else {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
- }
-}
-
void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
vec2 pixel_size = 1.0 / vec2(params.screen_size);
- vec2 uv = vec2(ssC) * pixel_size;
+ vec2 uv = vec2(ssC.xy) * pixel_size;
uv += pixel_size * 0.5;
@@ -77,7 +74,12 @@ void main() {
normal = normalize(normal);
normal.y = -normal.y; //because this code reads flipped
- vec3 view_dir = normalize(vertex);
+ vec3 view_dir;
+ if (sc_multiview) {
+ view_dir = normalize(vertex + scene_data.eye_offset[params.view_index].xyz);
+ } else {
+ view_dir = normalize(vertex);
+ }
vec3 ray_dir = normalize(reflect(view_dir, normal));
if (dot(ray_dir, normal) < 0.001) {
@@ -154,6 +156,11 @@ void main() {
// convert to linear depth
depth = imageLoad(source_depth, ivec2(pos - 0.5)).r;
+ if (sc_multiview) {
+ depth = depth * 2.0 - 1.0;
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ depth = -depth;
+ }
z_from = z_to;
z_to = z / w;
@@ -222,13 +229,16 @@ void main() {
blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
}
}
+
+ // Isn't this going to be overwritten after our endif?
final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size));
imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8
-#endif
+#endif // MODE_ROUGH
final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend);
+
//change blend by metallic
vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask);
final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0));
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
index 20e1712496..a63d60e0b2 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
@@ -22,7 +22,7 @@ layout(push_constant, std430) uniform Params {
bool orthogonal;
float edge_tolerance;
int increment;
- uint pad;
+ uint view_index;
ivec2 screen_size;
bool vertical;
@@ -30,6 +30,8 @@ layout(push_constant, std430) uniform Params {
}
params;
+#include "screen_space_reflection_inc.glsl"
+
#define GAUSS_TABLE_SIZE 15
const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[](
@@ -64,14 +66,6 @@ float gauss_weight(float p_val) {
#define M_PI 3.14159265359
-vec3 reconstructCSPosition(vec2 S, float z) {
- if (params.orthogonal) {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
- } else {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
- }
-}
-
void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) {
for (int i = 1; i < params.steps; i++) {
float d = float(i * params.increment);
@@ -110,7 +104,7 @@ void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
@@ -130,13 +124,13 @@ void main() {
ivec2 direction = ivec2(params.increment, 0);
#endif
float depth = imageLoad(source_depth, ssC).r;
- vec3 pos = reconstructCSPosition(vec2(ssC) + 0.5, depth);
+ vec3 pos = reconstructCSPosition(vec2(ssC.xy) + 0.5, depth);
vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0;
normal = normalize(normal);
normal.y = -normal.y;
- do_filter(accum, accum_radius, divisor, ssC, direction, pos, normal, radius);
- do_filter(accum, accum_radius, divisor, ssC, -direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC.xy, direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC.xy, -direction, pos, normal, radius);
if (divisor > 0.0) {
accum /= divisor;
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl
new file mode 100644
index 0000000000..26405ab040
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl
@@ -0,0 +1,28 @@
+layout(constant_id = 0) const bool sc_multiview = false;
+
+layout(set = 4, binding = 0, std140) uniform SceneData {
+ mat4x4 projection[2];
+ mat4x4 inv_projection[2];
+ vec4 eye_offset[2];
+}
+scene_data;
+
+vec3 reconstructCSPosition(vec2 screen_pos, float z) {
+ if (sc_multiview) {
+ vec4 pos;
+ pos.xy = (2.0 * vec2(screen_pos) / vec2(params.screen_size)) - 1.0;
+ pos.z = z * 2.0 - 1.0;
+ pos.w = 1.0;
+
+ pos = scene_data.inv_projection[params.view_index] * pos;
+ pos.xyz /= pos.w;
+
+ return pos.xyz;
+ } else {
+ if (params.orthogonal) {
+ return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw), z);
+ } else {
+ return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
index 3f537e273a..a7da0812df 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
@@ -6,6 +6,11 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_multiview = false;
+
+/* inputs */
layout(set = 0, binding = 0) uniform sampler2D source_ssr;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
layout(set = 1, binding = 1) uniform sampler2D source_normal;
@@ -28,7 +33,7 @@ void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
//do not filter, SSR will generate arctifacts if this is done
@@ -57,13 +62,19 @@ void main() {
normal.xyz += nr.xyz * 2.0 - 1.0;
normal.w += nr.w;
- d = d * 2.0 - 1.0;
- if (params.orthogonal) {
- d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ if (sc_multiview) {
+ // we're doing a full unproject so we need the value as is.
+ depth += d;
} else {
- d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ // unproject our Z value so we can use it directly.
+ d = d * 2.0 - 1.0;
+ if (params.orthogonal) {
+ d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ }
+ depth += -d;
}
- depth += -d;
}
color /= 4.0;
@@ -71,17 +82,22 @@ void main() {
normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5;
normal.w /= 4.0;
} else {
- color = texelFetch(source_ssr, ssC << 1, 0);
- depth = texelFetch(source_depth, ssC << 1, 0).r;
- normal = texelFetch(source_normal, ssC << 1, 0);
-
- depth = depth * 2.0 - 1.0;
- if (params.orthogonal) {
- depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
- } else {
- depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ ivec2 ofs = ssC << 1;
+
+ color = texelFetch(source_ssr, ofs, 0);
+ depth = texelFetch(source_depth, ofs, 0).r;
+ normal = texelFetch(source_normal, ofs, 0);
+
+ if (!sc_multiview) {
+ // unproject our Z value so we can use it directly.
+ depth = depth * 2.0 - 1.0;
+ if (params.orthogonal) {
+ depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ }
+ depth = -depth;
}
- depth = -depth;
}
imageStore(dest_ssr, ssC, color);
diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
new file mode 100644
index 0000000000..c62144fdaf
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
@@ -0,0 +1,112 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(location = 0) out vec3 uv_interp;
+#else // USE_MULTIVIEW
+layout(location = 0) out vec2 uv_interp;
+#endif //USE_MULTIVIEW
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+
+#ifdef USE_MULTIVIEW
+ uv_interp = vec3(base_arr[gl_VertexIndex], ViewIndex);
+
+ gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
+#else
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+#endif
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(location = 0) in vec3 uv_interp;
+#else // USE_MULTIVIEW
+layout(location = 0) in vec2 uv_interp;
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2DArray specular;
+#else // USE_MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2D specular;
+#endif //USE_MULTIVIEW
+
+#ifdef MODE_SSR
+
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 0) uniform sampler2DArray ssr;
+#else // USE_MULTIVIEW
+layout(set = 1, binding = 0) uniform sampler2D ssr;
+#endif //USE_MULTIVIEW
+
+#endif
+
+#ifdef MODE_MERGE
+
+#ifdef USE_MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2DArray diffuse;
+#else // USE_MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2D diffuse;
+#endif //USE_MULTIVIEW
+
+#endif
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ frag_color.rgb = texture(specular, uv_interp).rgb;
+ frag_color.a = 0.0;
+#ifdef MODE_SSR
+
+ vec4 ssr_color = texture(ssr, uv_interp);
+ frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
+#endif
+
+#ifdef MODE_MERGE
+ frag_color += texture(diffuse, uv_interp);
+#endif
+ //added using additive blend
+}
diff --git a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
index 134aae5ce7..134aae5ce7 100644
--- a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
index 2a87e273bc..2a87e273bc 100644
--- a/servers/rendering/renderer_rd/shaders/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
index f42734c46d..f42734c46d 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
index 04f98964e8..04f98964e8 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
index f6a9a92fac..f6a9a92fac 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
index 513791dfbf..513791dfbf 100644
--- a/servers/rendering/renderer_rd/shaders/ssil.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
index 47c56571f6..47c56571f6 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
index 6b6b02739d..6b6b02739d 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
index 9e86ac0cf0..9e86ac0cf0 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
index 5f34e7112d..6ea8cb1377 100644
--- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
@@ -659,7 +659,7 @@ void main() {
if (sc_use_vrs) {
ivec2 vrs_pos;
- // Currenty we use a 16x16 texel, possibly some day make this configurable.
+ // Currently we use a 16x16 texel, possibly some day make this configurable.
if (sc_half_res) {
vrs_pos = pos >> 3;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index 5b4594da99..5b4594da99 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
index eee609fb48..fb3c725b1f 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
@@ -21,8 +21,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
#define DENSITY_SCALE 1024.0
-#include "cluster_data_inc.glsl"
-#include "light_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define M_PI 3.14159265359
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index fdbd7d3e35..e74cfad65c 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -19,8 +19,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#endif
-#include "cluster_data_inc.glsl"
-#include "light_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define M_PI 3.14159265359
diff --git a/servers/rendering/renderer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl
deleted file mode 100644
index 3579c35cce..0000000000
--- a/servers/rendering/renderer_rd/shaders/specular_merge.glsl
+++ /dev/null
@@ -1,53 +0,0 @@
-#[vertex]
-
-#version 450
-
-#VERSION_DEFINES
-
-layout(location = 0) out vec2 uv_interp;
-
-void main() {
- vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
-
-#[fragment]
-
-#version 450
-
-#VERSION_DEFINES
-
-layout(location = 0) in vec2 uv_interp;
-
-layout(set = 0, binding = 0) uniform sampler2D specular;
-
-#ifdef MODE_SSR
-
-layout(set = 1, binding = 0) uniform sampler2D ssr;
-
-#endif
-
-#ifdef MODE_MERGE
-
-layout(set = 2, binding = 0) uniform sampler2D diffuse;
-
-#endif
-
-layout(location = 0) out vec4 frag_color;
-
-void main() {
- frag_color.rgb = texture(specular, uv_interp).rgb;
- frag_color.a = 0.0;
-#ifdef MODE_SSR
-
- vec4 ssr_color = texture(ssr, uv_interp);
- frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
-#endif
-
-#ifdef MODE_MERGE
- frag_color += texture(diffuse, uv_interp);
-#endif
- //added using additive blend
-}
diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
index ddd984ad83..b0a0839836 100644
--- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
@@ -189,7 +189,7 @@ vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) {
// Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
// License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae
- // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
+ // We're going to sample a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
// down the sample location to get the exact center of our "starting" texel. The starting texel will be at
// location [1, 1] in the grid, where [0, 0] is the top left corner.
vec2 sample_pos = uv * resolution;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index fb25e4da7e..2fb8f92fff 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -368,4 +368,4 @@ public:
} // namespace RendererRD
-#endif // !LIGHT_STORAGE_RD_H
+#endif // LIGHT_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index fcd25852eb..23d05de942 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -172,75 +172,96 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ if (p_array_size <= 0) {
+ p_array_size = 1;
}
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_UINT: {
@@ -267,75 +288,96 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ if (p_array_size <= 0) {
+ p_array_size = 1;
}
- gui[j + 3] = 0; // ignored
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ if (p_array_size <= 0) {
+ p_array_size = 1;
}
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
@@ -514,13 +556,20 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[1] = v.y;
gui[2] = v.z;
gui[3] = v.w;
- } else {
+ } else if (value.get_type() == Variant::PLANE) {
Plane v = value;
gui[0] = v.normal.x;
gui[1] = v.normal.y;
gui[2] = v.normal.z;
gui[3] = v.d;
+ } else {
+ Vector4 v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
}
} break;
@@ -670,7 +719,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[i + 15] = 1;
}
}
- } else {
+ } else if (value.get_type() == Variant::TRANSFORM3D) {
Transform3D v = value;
gui[0] = v.basis.rows[0][0];
gui[1] = v.basis.rows[1][0];
@@ -691,6 +740,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[13] = v.origin.y;
gui[14] = v.origin.z;
gui[15] = 1;
+ } else {
+ Projection v = value;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ gui[i * 4 + j] = v.matrix[i][j];
+ }
+ }
}
} break;
default: {
@@ -2341,6 +2397,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
+ shader->data->set_path_hint(shader->path_hint);
shader->data->set_code(p_code);
}
@@ -2351,6 +2408,16 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
}
}
+void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->path_hint = p_path;
+ if (shader->data) {
+ shader->data->set_path_hint(p_path);
+ }
+}
+
String MaterialStorage::shader_get_code(RID p_shader) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, String());
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index e35d5e7669..d5c9980150 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -31,7 +31,7 @@
#ifndef MATERIAL_STORAGE_RD_H
#define MATERIAL_STORAGE_RD_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
@@ -57,6 +57,7 @@ enum ShaderType {
struct ShaderData {
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;
@@ -77,6 +78,7 @@ struct Material;
struct Shader {
ShaderData *data = nullptr;
String code;
+ String path_hint;
ShaderType type;
HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
HashSet<Material *> owners;
@@ -300,7 +302,7 @@ public:
p_array[11] = p_mtx.origin.z;
}
- static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
+ static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
p_array[i * 4 + j] = p_mtx.matrix[i][j];
@@ -364,6 +366,7 @@ public:
virtual void shader_free(RID p_rid) override;
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;
@@ -421,4 +424,4 @@ public:
} // namespace RendererRD
-#endif // !MATERIAL_STORAGE_RD_H
+#endif // MATERIAL_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 9cdda6bfca..396fe9b6a6 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -703,4 +703,4 @@ public:
} // namespace RendererRD
-#endif // !MESH_STORAGE_RD_H
+#endif // MESH_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 5200e0d318..75977c5bc9 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -1512,6 +1512,9 @@ bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
/* Particles SHADER */
+void ParticlesStorage::ParticlesShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
ParticlesStorage *particles_storage = ParticlesStorage::get_singleton();
//compile
@@ -1609,7 +1612,22 @@ void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 70ac6f0349..75f995deeb 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -363,6 +363,7 @@ private:
uint32_t userdata_count = 0;
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_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -561,4 +562,4 @@ public:
} // namespace RendererRD
-#endif // !PARTICLES_STORAGE_RD_H
+#endif // PARTICLES_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 8807f78f6e..1eb4a283ca 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -191,8 +191,8 @@ struct Decal {
float upper_fade = 0.3;
float lower_fade = 0.3;
bool distance_fade = false;
- float distance_fade_begin = 10;
- float distance_fade_length = 1;
+ float distance_fade_begin = 40.0;
+ float distance_fade_length = 10.0;
float normal_fade = 0.0;
Dependency dependency;
@@ -576,4 +576,4 @@ public:
} // namespace RendererRD
-#endif // !_TEXTURE_STORAGE_RD_H
+#endif // TEXTURE_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h
index 979e984546..a80eb8510e 100644
--- a/servers/rendering/renderer_rd/storage_rd/utilities.h
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.h
@@ -119,4 +119,4 @@ public:
} // namespace RendererRD
-#endif // !UTILITIES_RD_H
+#endif // UTILITIES_RD_H
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
index af22a48716..abf110730b 100644
--- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef UNIFORM_SET_CACHE_H
-#define UNIFORM_SET_CACHE_H
+#ifndef UNIFORM_SET_CACHE_RD_H
+#define UNIFORM_SET_CACHE_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/paged_allocator.h"
@@ -220,4 +220,4 @@ public:
~UniformSetCacheRD();
};
-#endif // UNIFORMSETCACHE_H
+#endif // UNIFORM_SET_CACHE_RD_H
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index d635c7065d..be57701017 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSCENE_H
-#define RENDERINGSERVERSCENE_H
+#ifndef RENDERER_SCENE_H
+#define RENDERER_SCENE_H
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
@@ -226,4 +226,4 @@ public:
virtual ~RendererScene();
};
-#endif // RENDERINGSERVERSCENE_H
+#endif // RENDERER_SCENE_H
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index ebb5849f85..7e9be504f8 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -475,7 +475,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance);
+ geom->geometry_instance->set_mesh_instance(p_instance->mesh_instance);
if (p_instance->scenario && p_instance->array_index >= 0) {
InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
@@ -637,20 +637,20 @@ 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);
- scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
- scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
- scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay);
- scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
- scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
- scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
- scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias);
- scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light);
- scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
- scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
- scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
- scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency);
+ 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);
+ geom->geometry_instance->set_surface_materials(instance->materials);
+ geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb);
+ geom->geometry_instance->set_layer_mask(instance->layer_mask);
+ geom->geometry_instance->set_lod_bias(instance->lod_bias);
+ geom->geometry_instance->set_transparency(instance->transparency);
+ geom->geometry_instance->set_use_baked_light(instance->baked_light);
+ geom->geometry_instance->set_use_dynamic_gi(instance->dynamic_gi);
+ geom->geometry_instance->set_use_lightmap(RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
if (instance->lightmap_sh.size() == 9) {
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
+ geom->geometry_instance->set_lightmap_capture(instance->lightmap_sh.ptr());
}
for (Instance *E : instance->visibility_dependencies) {
@@ -836,7 +836,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);
- scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask);
+ geom->geometry_instance->set_layer_mask(p_mask);
}
}
@@ -848,7 +848,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);
- scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency);
+ geom->geometry_instance->set_transparency(p_transparency);
}
}
@@ -1009,7 +1009,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);
- scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton);
+ geom->geometry_instance->set_skeleton(p_skeleton);
}
}
@@ -1129,7 +1129,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);
- scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled);
+ geom->geometry_instance->set_use_baked_light(p_enabled);
}
} break;
@@ -1149,7 +1149,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);
- scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled);
+ geom->geometry_instance->set_use_dynamic_gi(p_enabled);
}
} break;
@@ -1207,7 +1207,7 @@ 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);
- scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+ geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
}
_instance_queue_update(instance, false, true);
@@ -1222,7 +1222,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);
- scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material);
+ geom->geometry_instance->set_material_override(p_material);
}
}
@@ -1235,7 +1235,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);
- scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material);
+ geom->geometry_instance->set_material_overlay(p_material);
}
}
@@ -1358,9 +1358,9 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
bool end_enabled = p_instance->visibility_range_end > 0.0f;
float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;
float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;
- scene_render->geometry_instance_set_fade_range(idata.instance_geometry, begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
+ idata.instance_geometry->set_fade_range(begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
} else {
- scene_render->geometry_instance_set_fade_range(idata.instance_geometry, false, 0.0f, 0.0f, false, 0.0f, 0.0f);
+ idata.instance_geometry->set_fade_range(false, 0.0f, 0.0f, false, 0.0f, 0.0f);
}
}
@@ -1375,7 +1375,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
} else {
idata.parent_array_index = -1;
if (is_geometry_instance) {
- scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, 1.0f);
+ idata.instance_geometry->set_parent_fade_alpha(1.0f);
}
}
}
@@ -1407,7 +1407,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);
- scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
+ geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
}
}
@@ -1419,7 +1419,7 @@ 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);
- scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias);
+ geom->geometry_instance->set_lod_bias(p_lod_bias);
}
}
@@ -1587,11 +1587,11 @@ 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
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr);
+ geom->geometry_instance->set_lightmap_capture(nullptr);
}
}
- scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
+ geom->geometry_instance->set_transform(p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
}
// note: we had to remove is equal approx check here, it meant that det == 0.000004 won't work, which is the case for some of our scenes.
@@ -1818,10 +1818,10 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
// Clear these now because the InstanceData containing the dirty flags is gone
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+ geom->geometry_instance->pair_light_instances(nullptr, 0);
+ geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0);
+ geom->geometry_instance->pair_decal_instances(nullptr, 0);
+ geom->geometry_instance->pair_voxel_gi_instances(nullptr, 0);
}
for (Instance *E : p_instance->visibility_dependencies) {
@@ -1829,7 +1829,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
if (dep_instance->array_index != -1) {
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- scene_render->geometry_instance_set_parent_fade_alpha(dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry, 1.0f);
+ dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry->set_parent_fade_alpha(1.0f);
}
}
}
@@ -1990,10 +1990,10 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
}
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr());
+ geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr());
}
-void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
+void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2045,7 +2045,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
// setup a camera matrix for that range!
- CameraMatrix camera_matrix;
+ Projection camera_matrix;
real_t aspect = p_cam_projection.get_aspect();
@@ -2185,7 +2185,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
z_max = z_vec.dot(center) + radius + pancake_size;
{
- CameraMatrix ortho_camera;
+ Projection ortho_camera;
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
real_t half_y = (y_max_cam - y_min_cam) * 0.5;
@@ -2210,7 +2210,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
-bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
+bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2283,7 +2283,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::mesh_storage->update_mesh_instances();
- scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
+ scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0);
shadow_data.light = light->instance;
shadow_data.pass = i;
}
@@ -2294,7 +2294,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, radius * 0.005f, radius);
for (int i = 0; i < 6; i++) {
@@ -2366,7 +2366,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
//restore the regular DP matrix
- //scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
+ //scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0);
}
} break;
@@ -2380,7 +2380,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius);
Vector<Plane> planes = cm.get_projection_planes(light_transform);
@@ -2450,7 +2450,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
if (p_xr_interface.is_null()) {
// Normal camera
Transform3D transform = camera->transform;
- CameraMatrix projection;
+ Projection projection;
bool vaspect = camera->vaspect;
bool is_orthogonal = false;
@@ -2489,7 +2489,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix projections[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection projections[RendererSceneRender::MAX_RENDER_VIEWS];
uint32_t view_count = p_xr_interface->get_view_count();
ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");
@@ -2518,14 +2518,14 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
RENDER_TIMESTAMP("Update Occlusion Buffer")
// For now just cull on the first camera
- RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool);
+ RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal);
_render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);
#endif
}
void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;
uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);
@@ -2622,7 +2622,7 @@ bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, co
void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t cull_from = p_thread * cull_total / total_threads;
uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);
@@ -2742,7 +2742,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;
fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;
}
- scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, fade);
+ idata.instance_geometry->set_parent_fade_alpha(fade);
}
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
@@ -2757,14 +2757,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_light_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
}
if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- scene_render->geometry_instance_set_softshadow_projector_pairing(geom->geometry_instance, geom->softshadow_count > 0, geom->projector_count > 0);
+ 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,7 +2781,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
}
@@ -2797,7 +2797,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
break;
}
}
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
}
@@ -2813,7 +2813,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
@@ -2824,7 +2824,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));
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
+ geom->geometry_instance->set_lightmap_capture(sh);
idata.instance->last_frame_pass = frame_number;
}
@@ -2919,7 +2919,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
if (visibility_cull_data.cull_count > thread_cull_threshold) {
- RendererThreadPool::singleton->thread_work_pool.do_work(RendererThreadPool::singleton->thread_work_pool.get_thread_count(), this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data, WorkerThreadPool::get_singleton()->get_thread_count(), -1, true, SNAME("VisibilityCullInstances"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
} else {
_visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);
}
@@ -3024,7 +3025,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
scene_cull_result_threads[i].clear();
}
- RendererThreadPool::singleton->thread_work_pool.do_work(scene_cull_result_threads.size(), this, &RendererSceneCull::_scene_cull_threaded, &cull_data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
scene_cull_result.append_from(scene_cull_result_threads[i]);
@@ -3243,7 +3245,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
render_sdfgi_data[i].instances.clear();
}
- // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
+ // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -3280,9 +3282,9 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
RENDER_TIMESTAMP("Render Empty 3D Scene");
RendererSceneRender::CameraData camera_data;
- camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
+ camera_data.set_camera(Transform3D(), Projection(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3329,7 +3331,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
max_distance = MAX(max_distance, distance);
//render cubemap side
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, max_distance);
Transform3D local_view;
@@ -3586,7 +3588,7 @@ void RendererSceneCull::render_probes() {
}
}
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ 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);
}
@@ -3849,7 +3851,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
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_variables_instance_allocate(p_instance->self);
- scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
+ geom->geometry_instance->set_instance_shader_parameters_offset(p_instance->instance_allocated_shader_parameters_offset);
for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
if (E.value.value.get_type() != Variant::NIL) {
@@ -3859,7 +3861,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
} else {
RSG::material_storage->global_variables_instance_free(p_instance->self);
p_instance->instance_allocated_shader_parameters_offset = -1;
- scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
+ geom->geometry_instance->set_instance_shader_parameters_offset(-1);
}
}
}
@@ -3872,7 +3874,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);
- scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials);
+ geom->geometry_instance->set_surface_materials(p_instance->materials);
}
}
@@ -4030,14 +4032,14 @@ RendererSceneCull::RendererSceneCull() {
}
scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
- scene_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count());
for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");
- thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU
+ thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU
taa_jitter_array.resize(TAA_JITTER_COUNT);
for (int i = 0; i < TAA_JITTER_COUNT; i++) {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 8c722360ae..851c7b6567 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_CULL_H
-#define RENDERING_SERVER_SCENE_CULL_H
+#ifndef RENDERER_SCENE_CULL_H
+#define RENDERER_SCENE_CULL_H
#include "core/math/dynamic_bvh.h"
#include "core/templates/bin_sorted_array.h"
@@ -272,7 +272,7 @@ public:
RID base_rid;
union {
uint64_t instance_data_rid;
- RendererSceneRender::GeometryInstance *instance_geometry;
+ RenderGeometryInstance *instance_geometry;
InstanceVisibilityNotifierData *visibility_notifier = nullptr;
};
Instance *instance = nullptr;
@@ -578,7 +578,7 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
- RendererSceneRender::GeometryInstance *geometry_instance = nullptr;
+ RenderGeometryInstance *geometry_instance = nullptr;
HashSet<Instance *> lights;
bool can_cast_shadows;
bool material_is_animated;
@@ -782,14 +782,14 @@ public:
HashSet<Instance *> heightfield_particle_colliders_update_list;
PagedArrayPool<Instance *> instance_cull_page_pool;
- PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool;
+ PagedArrayPool<RenderGeometryInstance *> geometry_instance_cull_page_pool;
PagedArrayPool<RID> rid_cull_page_pool;
PagedArray<Instance *> instance_cull_result;
PagedArray<Instance *> instance_shadow_cull_result;
struct InstanceCullResult {
- PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
+ PagedArray<RenderGeometryInstance *> geometry_instances;
PagedArray<Instance *> lights;
PagedArray<RID> light_instances;
PagedArray<RID> lightmaps;
@@ -800,10 +800,10 @@ public:
PagedArray<RID> fog_volumes;
struct DirectionalShadow {
- PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
+ PagedArray<RenderGeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
} directional_shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS];
- PagedArray<RendererSceneRender::GeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
+ PagedArray<RenderGeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
void clear() {
@@ -882,7 +882,7 @@ public:
}
}
- void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RendererSceneRender::GeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
+ void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RenderGeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
geometry_instances.set_page_pool(p_geometry_instance_pool);
light_instances.set_page_pool(p_rid_pool);
lights.set_page_pool(p_instance_pool);
@@ -980,9 +980,9 @@ public:
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
void _unpair_instance(Instance *p_instance);
- void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
+ void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
- _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
RID _render_get_environment(RID p_camera, RID p_scenario);
@@ -992,7 +992,7 @@ public:
struct Cascade {
Frustum frustum;
- CameraMatrix projection;
+ Projection projection;
Transform3D transform;
real_t zfar;
real_t split;
@@ -1045,7 +1045,7 @@ public:
uint32_t visible_layers;
Instance *render_reflection_probe = nullptr;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
- const CameraMatrix *camera_matrix;
+ const Projection *camera_matrix;
uint64_t visibility_viewport_mask;
};
@@ -1183,4 +1183,4 @@ public:
virtual ~RendererSceneCull();
};
-#endif // RENDERING_SERVER_SCENE_CULL_H
+#endif // RENDERER_SCENE_CULL_H
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 7198379ade..0d466e8a32 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -31,7 +31,7 @@
#ifndef RENDERER_SCENE_OCCLUSION_CULL_H
#define RENDERER_SCENE_OCCLUSION_CULL_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "servers/rendering_server.h"
@@ -60,7 +60,7 @@ public:
void update_mips();
- _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, real_t p_near) const {
+ _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const {
if (is_empty()) {
return false;
}
@@ -183,7 +183,8 @@ public:
}
virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warning(); }
virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warning(); }
- virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {}
+ virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {}
+
virtual RID buffer_get_debug_texture(RID p_buffer) {
_print_warning();
return RID();
@@ -200,4 +201,4 @@ public:
};
};
-#endif //RENDERER_SCENE_OCCLUSION_CULL_H
+#endif // RENDERER_SCENE_OCCLUSION_CULL_H
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 600908cf16..1edff261dc 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -30,7 +30,10 @@
#include "renderer_scene_render.h"
-void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
+/////////////////////////////////////////////////////////////////////////////
+// CameraData
+
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
view_count = 1;
is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
@@ -43,7 +46,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
taa_jitter = p_taa_jitter;
}
-void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) {
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) {
ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
view_count = p_view_count;
@@ -60,8 +63,8 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
}
// 2. average and normalize plane normals to obtain z vector, cross them to obtain y vector, and from there the x vector for combined camera basis.
- Vector3 n0 = planes[0][CameraMatrix::PLANE_LEFT].normal;
- Vector3 n1 = planes[1][CameraMatrix::PLANE_RIGHT].normal;
+ Vector3 n0 = planes[0][Projection::PLANE_LEFT].normal;
+ Vector3 n1 = planes[1][Projection::PLANE_RIGHT].normal;
Vector3 z = (n0 + n1).normalized();
Vector3 y = n0.cross(n1).normalized();
Vector3 x = y.cross(z).normalized();
@@ -73,13 +76,13 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 4. Intersect horizon, left and right to obtain the combined camera origin.
ERR_FAIL_COND_MSG(
- !horizon.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
+ !horizon.intersect_3(planes[0][Projection::PLANE_LEFT], planes[1][Projection::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
// handy to have the inverse of the transform we just build
Transform3D main_transform_inv = main_transform.inverse();
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
- Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
+ Vector3 far_center = (planes[0][Projection::PLANE_FAR].center() + planes[1][Projection::PLANE_FAR].center()) * 0.5;
Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
@@ -88,9 +91,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 6. Intersect far and left planes with top planes from both eyes, save the point with highest y as top_left.
Vector3 top_left, other;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
+ !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
+ !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
if (y.dot(top_left) < y.dot(other)) {
top_left = other;
}
@@ -98,9 +101,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 7. Intersect far and left planes with bottom planes from both eyes, save the point with lowest y as bottom_left.
Vector3 bottom_left;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
+ !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
+ !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
if (y.dot(other) < y.dot(bottom_left)) {
bottom_left = other;
}
@@ -108,9 +111,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 8. Intersect far and right planes with top planes from both eyes, save the point with highest y as top_right.
Vector3 top_right;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
+ !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
+ !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
if (y.dot(top_right) < y.dot(other)) {
top_right = other;
}
@@ -118,9 +121,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 9. Intersect far and right planes with bottom planes from both eyes, save the point with lowest y as bottom_right.
Vector3 bottom_right;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
+ !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
+ !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
if (y.dot(other) < y.dot(bottom_right)) {
bottom_right = other;
}
@@ -146,18 +149,18 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
Vector3 min_vec;
ERR_FAIL_COND_MSG(
- !near.intersect_3(bottom, planes[0][CameraMatrix::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
+ !near.intersect_3(bottom, planes[0][Projection::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
ERR_FAIL_COND_MSG(
- !near.intersect_3(bottom, planes[1][CameraMatrix::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
+ !near.intersect_3(bottom, planes[1][Projection::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
if (x.dot(other) < x.dot(min_vec)) {
min_vec = other;
}
Vector3 max_vec;
ERR_FAIL_COND_MSG(
- !near.intersect_3(top, planes[0][CameraMatrix::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
+ !near.intersect_3(top, planes[0][Projection::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
ERR_FAIL_COND_MSG(
- !near.intersect_3(top, planes[1][CameraMatrix::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
+ !near.intersect_3(top, planes[1][Projection::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
if (x.dot(max_vec) < x.dot(other)) {
max_vec = other;
}
@@ -177,6 +180,6 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 3. Copy our view data
for (uint32_t v = 0; v < view_count; v++) {
view_offset[v] = main_transform_inv * p_transforms[v];
- view_projection[v] = p_projections[v] * CameraMatrix(view_offset[v].inverse());
+ view_projection[v] = p_projections[v] * Projection(view_offset[v].inverse());
}
}
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 74c7d55a57..dc328f3e11 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -28,12 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSCENERENDER_H
-#define RENDERINGSERVERSCENERENDER_H
+#ifndef RENDERER_SCENE_RENDER_H
+#define RENDERER_SCENE_RENDER_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/paged_array.h"
+#include "servers/rendering/renderer_geometry_instance.h"
#include "servers/rendering/renderer_scene.h"
+#include "storage/utilities.h"
class RendererSceneRender {
public:
@@ -43,38 +45,11 @@ public:
MAX_RENDER_VIEWS = 2
};
- struct GeometryInstance {
- virtual ~GeometryInstance() {}
- };
-
- virtual GeometryInstance *geometry_instance_create(RID p_base) = 0;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) = 0;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) = 0;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) = 0;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+ /* Geometry Instance */
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) = 0;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) = 0;
virtual uint32_t geometry_instance_get_pair_mask() = 0;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) = 0;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
/* SHADOW ATLAS API */
@@ -172,7 +147,7 @@ public:
virtual RID light_instance_create(RID p_light) = 0;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const {
return true;
@@ -205,19 +180,19 @@ public:
virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0;
virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0;
virtual bool voxel_gi_needs_update(RID p_probe) const = 0;
- virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) = 0;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0;
struct RenderShadowData {
RID light;
int pass = 0;
- PagedArray<GeometryInstance *> instances;
+ PagedArray<RenderGeometryInstance *> instances;
};
struct RenderSDFGIData {
int region = 0;
- PagedArray<GeometryInstance *> instances;
+ PagedArray<RenderGeometryInstance *> instances;
};
struct RenderSDFGIUpdateData {
@@ -239,20 +214,20 @@ public:
// Main/center projection
Transform3D main_transform;
- CameraMatrix main_projection;
+ Projection main_projection;
Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Vector2 taa_jitter;
- void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
- void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect);
+ void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time, double p_step) = 0;
@@ -281,4 +256,4 @@ public:
virtual ~RendererSceneRender() {}
};
-#endif // RENDERINGSERVERSCENERENDER_H
+#endif // RENDERER_SCENE_RENDER_H
diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_thread_pool.cpp
deleted file mode 100644
index ddf1d1bd00..0000000000
--- a/servers/rendering/renderer_thread_pool.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*************************************************************************/
-/* renderer_thread_pool.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 "renderer_thread_pool.h"
-
-RendererThreadPool *RendererThreadPool::singleton = nullptr;
-
-RendererThreadPool::RendererThreadPool() {
- singleton = this;
- thread_work_pool.init();
-}
-
-RendererThreadPool::~RendererThreadPool() {
- thread_work_pool.finish();
-}
diff --git a/servers/rendering/renderer_thread_pool.h b/servers/rendering/renderer_thread_pool.h
deleted file mode 100644
index 4626490d32..0000000000
--- a/servers/rendering/renderer_thread_pool.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************************************/
-/* renderer_thread_pool.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 RENDERERTHREADPOOL_H
-#define RENDERERTHREADPOOL_H
-
-#include "core/templates/thread_work_pool.h"
-
-class RendererThreadPool {
-public:
- ThreadWorkPool thread_work_pool;
-
- static RendererThreadPool *singleton;
- RendererThreadPool();
- ~RendererThreadPool();
-};
-
-#endif // RENDERERTHREADPOOL_H
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 7c9b2567d6..0e26de8bcb 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -154,7 +154,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
if (p_viewport->use_occlusion_culling) {
if (p_viewport->occlusion_buffer_dirty) {
float aspect = p_viewport->size.aspect();
- int max_size = occlusion_rays_per_thread * RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ int max_size = occlusion_rays_per_thread * WorkerThreadPool::get_singleton()->get_thread_count();
int viewport_size = p_viewport->size.width * p_viewport->size.height;
max_size = CLAMP(max_size, viewport_size / (32 * 32), viewport_size / (2 * 2)); // At least one depth pixel for every 16x16 region. At most one depth pixel for every 2x2 region.
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 027f2dfad6..4647fbd8c3 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -48,33 +48,34 @@ public:
RID self;
RID parent;
- bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
+ // use xr interface to override camera positioning and projection matrices and control output
+ bool use_xr = false;
Size2i internal_size;
Size2i size;
RID camera;
RID scenario;
- RS::ViewportScaling3DMode scaling_3d_mode;
+ RS::ViewportScaling3DMode scaling_3d_mode = RenderingServer::VIEWPORT_SCALING_3D_MODE_BILINEAR;
float scaling_3d_scale = 1.0;
float fsr_sharpness = 0.2f;
float fsr_mipmap_bias = 0.0f;
- bool fsr_enabled;
- RS::ViewportUpdateMode update_mode;
+ bool fsr_enabled = false;
+ RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
RID render_target;
RID render_target_texture;
RID render_buffers;
- RS::ViewportMSAA msaa;
- RS::ViewportScreenSpaceAA screen_space_aa;
- bool use_taa;
- bool use_debanding;
+ RS::ViewportMSAA msaa = RenderingServer::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+ bool use_taa = false;
+ bool use_debanding = false;
RendererSceneRender::CameraData prev_camera_data;
uint64_t prev_camera_data_frame = 0;
- bool use_occlusion_culling;
- bool occlusion_buffer_dirty;
+ bool use_occlusion_culling = false;
+ bool occlusion_buffer_dirty = false;
DisplayServer::WindowID viewport_to_screen;
Rect2 viewport_to_screen_rect;
@@ -83,10 +84,10 @@ public:
bool disable_2d = false;
bool disable_environment = false;
bool disable_3d = false;
- bool measure_render_time;
+ bool measure_render_time = false;
- bool snap_2d_transforms_to_pixel;
- bool snap_2d_vertices_to_pixel;
+ bool snap_2d_transforms_to_pixel = false;
+ bool snap_2d_vertices_to_pixel = false;
uint64_t time_cpu_begin;
uint64_t time_cpu_end;
@@ -95,23 +96,23 @@ public:
uint64_t time_gpu_end;
RID shadow_atlas;
- int shadow_atlas_size;
+ int shadow_atlas_size = 2048;
bool shadow_atlas_16_bits = true;
- bool sdf_active;
+ bool sdf_active = false;
float mesh_lod_threshold = 1.0;
uint64_t last_pass = 0;
- RS::ViewportDebugDraw debug_draw;
+ RS::ViewportDebugDraw debug_draw = RenderingServer::VIEWPORT_DEBUG_DRAW_DISABLED;
- RS::ViewportClearMode clear_mode;
+ RS::ViewportClearMode clear_mode = RenderingServer::VIEWPORT_CLEAR_ALWAYS;
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
- bool transparent_bg;
+ bool transparent_bg = false;
struct CanvasKey {
int64_t stacking;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 429b8a06e2..f093f43a82 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -224,6 +224,7 @@ public:
FUNCRIDSPLIT(shader)
FUNC2(shader_set_code, RID, const String &)
+ FUNC2(shader_set_path_hint, RID, const String &)
FUNC1RC(String, shader_get_code, RID)
FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
@@ -980,4 +981,4 @@ public:
~RenderingServerDefault();
};
-#endif
+#endif // RENDERING_SERVER_DEFAULT_H
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 463b67033d..e291246d01 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -1323,18 +1323,76 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
Error err = parser.compile(p_code, info);
if (err != OK) {
+ Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions();
+
+ String current;
+ HashMap<String, Vector<String>> includes;
+ includes[""] = Vector<String>();
+ Vector<String> include_stack;
Vector<String> shader = p_code.split("\n");
+
+ // Reconstruct the files.
for (int i = 0; i < shader.size(); i++) {
- if (i + 1 == parser.get_error_line()) {
- // Mark the error line to be visible without having to look at
- // the trace at the end.
- print_line(vformat("E%4d-> %s", i + 1, shader[i]));
+ String l = shader[i];
+ if (l.begins_with("@@>")) {
+ String inc_path = l.replace_first("@@>", "");
+
+ l = "#include \"" + inc_path + "\"";
+ includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive
+ include_stack.push_back(current);
+ current = inc_path;
+ includes[inc_path] = Vector<String>();
+
+ } else if (l.begins_with("@@<")) {
+ if (include_stack.size()) {
+ current = include_stack[include_stack.size() - 1];
+ include_stack.resize(include_stack.size() - 1);
+ }
+ } else {
+ includes[current].push_back(l);
+ }
+ }
+
+ // Print the files.
+ for (const KeyValue<String, Vector<String>> &E : includes) {
+ if (E.key.is_empty()) {
+ if (p_path == "") {
+ print_line("--Main Shader--");
+ } else {
+ print_line("--" + p_path + "--");
+ }
} else {
- print_line(vformat("%5d | %s", i + 1, shader[i]));
+ print_line("--" + E.key + "--");
}
+ int err_line = -1;
+ for (int i = 0; i < include_positions.size(); i++) {
+ if (include_positions[i].file == E.key) {
+ err_line = include_positions[i].line;
+ }
+ }
+ const Vector<String> &V = E.value;
+ for (int i = 0; i < V.size(); i++) {
+ if (i == err_line - 1) {
+ // Mark the error line to be visible without having to look at
+ // the trace at the end.
+ print_line(vformat("E%4d-> %s", i + 1, V[i]));
+ } else {
+ print_line(vformat("%5d | %s", i + 1, V[i]));
+ }
+ }
+ }
+
+ String file;
+ int line;
+ if (include_positions.size() > 1) {
+ file = include_positions[include_positions.size() - 1].file;
+ line = include_positions[include_positions.size() - 1].line;
+ } else {
+ file = p_path;
+ line = parser.get_error_line();
}
- _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
+ _err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
return err;
}
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index ad9b51ac0c..bb41b06189 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -32,7 +32,9 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "core/templates/local_vector.h"
#include "servers/rendering_server.h"
+#include "shader_types.h"
#define HAS_WARNING(flag) (warning_flags & flag)
@@ -308,6 +310,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
// global space keywords
{ TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} },
+ { TK_UNIFORM_GROUP, "group_uniforms", CF_GLOBAL_SPACE, {}, {} },
{ TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} },
{ TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} },
{ TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
@@ -574,6 +577,37 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_MOD);
} break;
+ case '@': {
+ if (GETCHAR(0) == '@' && GETCHAR(1) == '>') {
+ char_idx += 2;
+
+ LocalVector<char32_t> incp;
+ while (GETCHAR(0) != '\n') {
+ incp.push_back(GETCHAR(0));
+ char_idx++;
+ }
+ incp.push_back(0); // Zero end it.
+ String include_path(incp.ptr());
+ include_positions.write[include_positions.size() - 1].line = tk_line;
+ FilePosition fp;
+ fp.file = include_path;
+ fp.line = 0;
+ tk_line = 0;
+ include_positions.push_back(fp);
+
+ } else if (GETCHAR(0) == '@' && GETCHAR(1) == '<') {
+ if (include_positions.size() == 1) {
+ return _make_token(TK_ERROR, "Invalid include exit hint @@< without matching enter hint.");
+ }
+ char_idx += 2;
+
+ include_positions.resize(include_positions.size() - 1); // Pop back.
+ tk_line = include_positions[include_positions.size() - 1].line; // Restore line.
+
+ } else {
+ return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)");
+ }
+ } break;
default: {
char_idx--; //go back one, since we have no idea what this is
@@ -1113,6 +1147,8 @@ void ShaderLanguage::clear() {
current_function = StringName();
last_name = StringName();
last_type = IDENTIFIER_MAX;
+ current_uniform_group_name = "";
+ current_uniform_subgroup_name = "";
completion_type = COMPLETION_NONE;
completion_block = nullptr;
@@ -1122,6 +1158,9 @@ void ShaderLanguage::clear() {
completion_base = TYPE_VOID;
completion_base_array = false;
+ include_positions.clear();
+ include_positions.push_back(FilePosition());
+
#ifdef DEBUG_ENABLED
keyword_completion_context = CF_GLOBAL_SPACE;
used_constants.clear();
@@ -1183,17 +1222,36 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
#endif // DEBUG_ENABLED
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
- if (p_function_info.built_ins.has(p_identifier)) {
- if (r_data_type) {
- *r_data_type = p_function_info.built_ins[p_identifier].type;
- }
- if (r_is_const) {
- *r_is_const = p_function_info.built_ins[p_identifier].constant;
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ for (const KeyValue<StringName, FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) {
+ if ((current_function == E.key || E.key == "global") && E.value.built_ins.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = E.value.built_ins[p_identifier].type;
+ }
+ if (r_is_const) {
+ *r_is_const = E.value.built_ins[p_identifier].constant;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_BUILTIN_VAR;
+ }
+ return true;
+ }
+ }
}
- if (r_type) {
- *r_type = IDENTIFIER_BUILTIN_VAR;
+ } else {
+ if (p_function_info.built_ins.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = p_function_info.built_ins[p_identifier].type;
+ }
+ if (r_is_const) {
+ *r_is_const = p_function_info.built_ins[p_identifier].constant;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_BUILTIN_VAR;
+ }
+ return true;
}
- return true;
}
if (p_function_info.stage_functions.has(p_identifier)) {
@@ -3798,18 +3856,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[4].real;
- p[1][1] = p_value[5].real;
- p[1][2] = p_value[6].real;
- p[2][0] = p_value[8].real;
- p[2][1] = p_value[9].real;
- p[2][2] = p_value[10].real;
- Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
- value = Variant(t);
+ Projection p = Projection(Vector4(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real),
+ Vector4(p_value[4].real, p_value[5].real, p_value[6].real, p_value[7].real),
+ Vector4(p_value[8].real, p_value[9].real, p_value[10].real, p_value[11].real),
+ Vector4(p_value[12].real, p_value[13].real, p_value[14].real, p_value[15].real));
+ value = Variant(p);
}
break;
}
@@ -3891,13 +3942,29 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
}
}
} break;
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_IVEC2: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR2I;
+ }
+ } break;
case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_UVEC4: {
- pi.type = Variant::PACKED_INT32_ARRAY;
+ case ShaderLanguage::TYPE_IVEC3: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR3I;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_IVEC4: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR4I;
+ }
} break;
case ShaderLanguage::TYPE_FLOAT: {
if (p_uniform.array_size > 0) {
@@ -3945,7 +4012,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
pi.type = Variant::COLOR;
} else {
- pi.type = Variant::QUATERNION;
+ pi.type = Variant::VECTOR4;
}
}
} break;
@@ -3967,7 +4034,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_FLOAT32_ARRAY;
} else {
- pi.type = Variant::TRANSFORM3D;
+ pi.type = Variant::PROJECTION;
}
break;
case ShaderLanguage::TYPE_SAMPLER2D:
@@ -7678,34 +7745,38 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci
}
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
- Token tk = _get_token();
+ Token tk;
TkPos prev_pos;
Token next;
- if (tk.type != TK_SHADER_TYPE) {
- _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
+ if (!is_shader_inc) {
+ tk = _get_token();
+
+ if (tk.type != TK_SHADER_TYPE) {
+ _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_UNSPECIFIED;
+ keyword_completion_context = CF_UNSPECIFIED;
#endif // DEBUG_ENABLED
- _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
- if (shader_type_identifier == StringName()) {
- _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
- if (!p_shader_types.has(shader_type_identifier)) {
- _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
- prev_pos = _get_tkpos();
- tk = _get_token();
+ _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
+ if (shader_type_identifier == StringName()) {
+ _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+ if (!p_shader_types.has(shader_type_identifier)) {
+ _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+ prev_pos = _get_tkpos();
+ tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_tkpos(prev_pos);
- _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
- return ERR_PARSE_ERROR;
+ if (tk.type != TK_SEMICOLON) {
+ _set_tkpos(prev_pos);
+ _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
+ return ERR_PARSE_ERROR;
+ }
}
#ifdef DEBUG_ENABLED
@@ -7760,25 +7831,54 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
bool found = false;
- for (int i = 0; i < p_render_modes.size(); i++) {
- const ModeInfo &info = p_render_modes[i];
- const String name = String(info.name);
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
- if (smode.begins_with(name)) {
- if (!info.options.is_empty()) {
- if (info.options.has(smode.substr(name.length() + 1))) {
- found = true;
+ for (int j = 0; j < modes.size(); j++) {
+ const ModeInfo &info = modes[j];
+ const String name = String(info.name);
- if (defined_modes.has(name)) {
- _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
- return ERR_PARSE_ERROR;
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.has(smode.substr(name.length() + 1))) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
+ break;
}
- defined_modes.insert(name, smode);
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < p_render_modes.size(); i++) {
+ const ModeInfo &info = p_render_modes[i];
+ const String name = String(info.name);
+
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.has(smode.substr(name.length() + 1))) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
break;
}
- } else {
- found = true;
- break;
}
}
}
@@ -8194,6 +8294,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
uniform.scope = uniform_scope;
uniform.precision = precision;
uniform.array_size = array_size;
+ uniform.group = current_uniform_group_name;
+ uniform.subgroup = current_uniform_subgroup_name;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -8620,6 +8722,45 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
}
} break;
+ case TK_UNIFORM_GROUP: {
+ tk = _get_token();
+ if (tk.type == TK_IDENTIFIER) {
+ current_uniform_group_name = tk.text;
+ tk = _get_token();
+ if (tk.type == TK_PERIOD) {
+ tk = _get_token();
+ if (tk.type == TK_IDENTIFIER) {
+ current_uniform_subgroup_name = tk.text;
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_expected_error(";");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error(RTR("Expected an uniform subgroup identifier."));
+ return ERR_PARSE_ERROR;
+ }
+ } else if (tk.type != TK_SEMICOLON) {
+ _set_expected_error(";", ".");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ if (tk.type != TK_SEMICOLON) {
+ if (current_uniform_group_name.is_empty()) {
+ _set_error(RTR("Expected an uniform group identifier."));
+ } else {
+ _set_error(RTR("Expected an uniform group identifier or `;`."));
+ }
+ return ERR_PARSE_ERROR;
+ } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) {
+ _set_error(RTR("Group needs to be opened before."));
+ return ERR_PARSE_ERROR;
+ } else {
+ current_uniform_group_name = "";
+ current_uniform_subgroup_name = "";
+ }
+ }
+ } break;
case TK_SHADER_TYPE: {
_set_error(RTR("Shader type is already defined."));
return ERR_PARSE_ERROR;
@@ -9508,9 +9649,11 @@ uint32_t ShaderLanguage::get_warning_flags() const {
Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
clear();
+ is_shader_inc = p_info.is_include;
code = p_code;
global_var_get_type_func = p_info.global_variable_type_func;
+
varying_function_names = p_info.varying_function_names;
nodes = nullptr;
@@ -9532,6 +9675,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) {
clear();
+ is_shader_inc = p_info.is_include;
code = p_code;
varying_function_names = p_info.varying_function_names;
@@ -9577,30 +9721,64 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
return OK;
} break;
case COMPLETION_RENDER_MODE: {
- for (int i = 0; i < p_info.render_modes.size(); i++) {
- const ModeInfo &info = p_info.render_modes[i];
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
- if (!info.options.is_empty()) {
- bool found = false;
+ for (int j = 0; j < modes.size(); j++) {
+ const ModeInfo &info = modes[j];
- for (int j = 0; j < info.options.size(); j++) {
- if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
- found = true;
+ if (!info.options.is_empty()) {
+ bool found = false;
+
+ for (int k = 0; k < info.options.size(); k++) {
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[k]))) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (int k = 0; k < info.options.size(); k++) {
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[k]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
}
}
+ }
+ } else {
+ for (int i = 0; i < p_info.render_modes.size(); i++) {
+ const ModeInfo &info = p_info.render_modes[i];
+
+ if (!info.options.is_empty()) {
+ bool found = false;
- if (!found) {
for (int j = 0; j < info.options.size(); j++) {
- ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
+ found = true;
+ }
}
- }
- } else {
- const String name = String(info.name);
- if (!shader->render_modes.has(name)) {
- ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (!found) {
+ for (int j = 0; j < info.options.size(); j++) {
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
}
}
}
@@ -9668,33 +9846,69 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
}
if (comp_ident) {
- if (p_info.functions.has("global")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const HashMap<StringName, ShaderLanguage::FunctionInfo> info = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i));
+
+ if (info.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info["global"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (info.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info["constants"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (skip_function != StringName() && info.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info[skip_function].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+ }
+ } else {
+ if (p_info.functions.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
- }
- if (p_info.functions.has("constants")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (p_info.functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
- }
- if (skip_function != StringName() && p_info.functions.has(skip_function)) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
}
@@ -10066,6 +10280,10 @@ String ShaderLanguage::get_error_text() {
return error_str;
}
+Vector<ShaderLanguage::FilePosition> ShaderLanguage::get_include_positions() {
+ return include_positions;
+}
+
int ShaderLanguage::get_error_line() {
return error_line;
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 2b147fbeb1..42023f25d7 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -38,6 +38,7 @@
#include "core/templates/rb_map.h"
#include "core/typedefs.h"
#include "core/variant/variant.h"
+#include "scene/resources/shader_include.h"
#ifdef DEBUG_ENABLED
#include "shader_warnings.h"
@@ -153,6 +154,7 @@ public:
TK_SEMICOLON,
TK_PERIOD,
TK_UNIFORM,
+ TK_UNIFORM_GROUP,
TK_INSTANCE,
TK_GLOBAL,
TK_VARYING,
@@ -686,6 +688,8 @@ public:
TextureRepeat repeat = REPEAT_DEFAULT;
float hint_range[3];
int instance_index = 0;
+ String group;
+ String subgroup;
Uniform() {
hint_range[0] = 0.0f;
@@ -867,6 +871,11 @@ public:
typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
+ struct FilePosition {
+ String file;
+ int line = 0;
+ };
+
private:
struct KeyWord {
TokenType token;
@@ -884,6 +893,8 @@ private:
String error_str;
int error_line = 0;
+ Vector<FilePosition> include_positions;
+
#ifdef DEBUG_ENABLED
struct Usage {
int decl_line;
@@ -928,6 +939,10 @@ private:
StringName current_function;
bool last_const = false;
StringName last_name;
+ bool is_shader_inc = false;
+
+ String current_uniform_group_name;
+ String current_uniform_subgroup_name;
VaryingFunctionNames varying_function_names;
@@ -951,6 +966,7 @@ private:
error_line = tk_line;
error_set = true;
error_str = p_str;
+ include_positions.write[include_positions.size() - 1].line = tk_line;
}
void _set_expected_error(const String &p_what) {
@@ -1098,12 +1114,14 @@ public:
VaryingFunctionNames varying_function_names = VaryingFunctionNames();
HashSet<String> shader_types;
GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
+ bool is_include = false;
};
Error compile(const String &p_code, const ShaderCompileInfo &p_info);
Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
+ Vector<FilePosition> get_include_positions();
int get_error_line();
ShaderNode *get_shader();
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
new file mode 100644
index 0000000000..a7b274b3e2
--- /dev/null
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -0,0 +1,1048 @@
+/*************************************************************************/
+/* shader_preprocessor.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 "shader_preprocessor.h"
+#include "core/math/expression.h"
+
+const char32_t CURSOR = 0xFFFF;
+
+// Tokenizer
+
+void ShaderPreprocessor::Tokenizer::add_generated(const ShaderPreprocessor::Token &p_t) {
+ generated.push_back(p_t);
+}
+
+char32_t ShaderPreprocessor::Tokenizer::next() {
+ if (index < size) {
+ return code[index++];
+ }
+ return 0;
+}
+
+int ShaderPreprocessor::Tokenizer::get_line() const {
+ return line;
+}
+
+int ShaderPreprocessor::Tokenizer::get_index() const {
+ return index;
+}
+
+void ShaderPreprocessor::Tokenizer::get_and_clear_generated(Vector<ShaderPreprocessor::Token> *r_out) {
+ for (int i = 0; i < generated.size(); i++) {
+ r_out->push_back(generated[i]);
+ }
+ generated.clear();
+}
+
+void ShaderPreprocessor::Tokenizer::backtrack(char32_t p_what) {
+ while (index >= 0) {
+ char32_t c = code[index];
+ if (c == p_what) {
+ break;
+ }
+ index--;
+ }
+}
+
+char32_t ShaderPreprocessor::Tokenizer::peek() {
+ if (index < size) {
+ return code[index];
+ }
+ return 0;
+}
+
+LocalVector<ShaderPreprocessor::Token> ShaderPreprocessor::Tokenizer::advance(char32_t p_what) {
+ LocalVector<ShaderPreprocessor::Token> tokens;
+
+ while (index < size) {
+ char32_t c = code[index++];
+
+ tokens.push_back(ShaderPreprocessor::Token(c, line));
+
+ if (c == '\n') {
+ add_generated(ShaderPreprocessor::Token('\n', line));
+ line++;
+ }
+
+ if (c == p_what || c == 0) {
+ return tokens;
+ }
+ }
+ return LocalVector<ShaderPreprocessor::Token>();
+}
+
+void ShaderPreprocessor::Tokenizer::skip_whitespace() {
+ while (is_char_space(peek())) {
+ next();
+ }
+}
+
+String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_started) {
+ if (r_is_cursor != nullptr) {
+ *r_is_cursor = false;
+ }
+
+ LocalVector<char32_t> text;
+
+ while (true) {
+ char32_t c = peek();
+ if (is_char_end(c) || c == '(' || c == ')' || c == ',' || c == ';') {
+ break;
+ }
+
+ if (is_whitespace(c) && p_started) {
+ break;
+ }
+ if (!is_whitespace(c)) {
+ p_started = true;
+ }
+
+ char32_t n = next();
+ if (n == CURSOR) {
+ if (r_is_cursor != nullptr) {
+ *r_is_cursor = true;
+ }
+ } else {
+ if (p_started) {
+ text.push_back(n);
+ }
+ }
+ }
+
+ String id = vector_to_string(text);
+ if (!id.is_valid_identifier()) {
+ return "";
+ }
+
+ return id;
+}
+
+String ShaderPreprocessor::Tokenizer::peek_identifier() {
+ const int original = index;
+ String id = get_identifier();
+ index = original;
+ return id;
+}
+
+ShaderPreprocessor::Token ShaderPreprocessor::Tokenizer::get_token() {
+ while (index < size) {
+ const char32_t c = code[index++];
+ const Token t = ShaderPreprocessor::Token(c, line);
+
+ switch (c) {
+ case ' ':
+ case '\t':
+ skip_whitespace();
+ return ShaderPreprocessor::Token(' ', line);
+ case '\n':
+ line++;
+ return t;
+ default:
+ return t;
+ }
+ }
+ return ShaderPreprocessor::Token(char32_t(0), line);
+}
+
+ShaderPreprocessor::Tokenizer::Tokenizer(const String &p_code) {
+ code = p_code;
+ line = 0;
+ index = 0;
+ size = code.size();
+}
+
+// ShaderPreprocessor::CommentRemover
+
+String ShaderPreprocessor::CommentRemover::get_error() const {
+ if (comments_open != 0) {
+ return "Block comment mismatch";
+ }
+ return "";
+}
+
+int ShaderPreprocessor::CommentRemover::get_error_line() const {
+ if (comments_open != 0) {
+ return comment_line_open;
+ }
+ return -1;
+}
+
+char32_t ShaderPreprocessor::CommentRemover::peek() const {
+ if (index < code.size()) {
+ return code[index];
+ }
+ return 0;
+}
+
+bool ShaderPreprocessor::CommentRemover::advance(char32_t p_what) {
+ while (index < code.size()) {
+ char32_t c = code[index++];
+
+ if (c == '\n') {
+ line++;
+ stripped.push_back('\n');
+ }
+
+ if (c == p_what) {
+ return true;
+ }
+ }
+ return false;
+}
+
+String ShaderPreprocessor::CommentRemover::strip() {
+ stripped.clear();
+ index = 0;
+ line = 0;
+ comment_line_open = 0;
+ comments_open = 0;
+ strings_open = 0;
+
+ while (index < code.size()) {
+ char32_t c = code[index++];
+
+ if (c == CURSOR) {
+ // Cursor. Maintain.
+ stripped.push_back(c);
+ } else if (c == '"') {
+ if (strings_open <= 0) {
+ strings_open++;
+ } else {
+ strings_open--;
+ }
+ stripped.push_back(c);
+ } else if (c == '/' && strings_open == 0) {
+ char32_t p = peek();
+ if (p == '/') { // Single line comment.
+ advance('\n');
+ } else if (p == '*') { // Start of a block comment.
+ index++;
+ comment_line_open = line;
+ comments_open++;
+ while (advance('*')) {
+ if (peek() == '/') { // End of a block comment.
+ comments_open--;
+ index++;
+ break;
+ }
+ }
+ } else {
+ stripped.push_back(c);
+ }
+ } else if (c == '*' && strings_open == 0) {
+ if (peek() == '/') { // Unmatched end of a block comment.
+ comment_line_open = line;
+ comments_open--;
+ } else {
+ stripped.push_back(c);
+ }
+ } else if (c == '\n') {
+ line++;
+ stripped.push_back(c);
+ } else {
+ stripped.push_back(c);
+ }
+ }
+ return vector_to_string(stripped);
+}
+
+ShaderPreprocessor::CommentRemover::CommentRemover(const String &p_code) {
+ code = p_code;
+ index = 0;
+ line = 0;
+ comment_line_open = 0;
+ comments_open = 0;
+ strings_open = 0;
+}
+
+// ShaderPreprocessor::Token
+
+ShaderPreprocessor::Token::Token() {
+ text = 0;
+ line = -1;
+}
+
+ShaderPreprocessor::Token::Token(char32_t p_text, int p_line) {
+ text = p_text;
+ line = p_line;
+}
+
+// ShaderPreprocessor
+
+bool ShaderPreprocessor::is_char_word(char32_t p_char) {
+ if ((p_char >= '0' && p_char <= '9') ||
+ (p_char >= 'a' && p_char <= 'z') ||
+ (p_char >= 'A' && p_char <= 'Z') ||
+ p_char == '_') {
+ return true;
+ }
+
+ return false;
+}
+
+bool ShaderPreprocessor::is_char_space(char32_t p_char) {
+ return p_char == ' ' || p_char == '\t';
+}
+
+bool ShaderPreprocessor::is_char_end(char32_t p_char) {
+ return p_char == '\n' || p_char == 0;
+}
+
+String ShaderPreprocessor::vector_to_string(const LocalVector<char32_t> &p_v, int p_start, int p_end) {
+ const int stop = (p_end == -1) ? p_v.size() : p_end;
+ const int count = stop - p_start;
+
+ String result;
+ result.resize(count + 1);
+ for (int i = 0; i < count; i++) {
+ result[i] = p_v[p_start + i];
+ }
+ result[count] = 0; // Ensure string is null terminated for length() to work.
+ return result;
+}
+
+String ShaderPreprocessor::tokens_to_string(const LocalVector<Token> &p_tokens) {
+ LocalVector<char32_t> result;
+ for (uint32_t i = 0; i < p_tokens.size(); i++) {
+ result.push_back(p_tokens[i].text);
+ }
+ return vector_to_string(result);
+}
+
+void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) {
+ bool is_cursor;
+ String directive = p_tokenizer->get_identifier(&is_cursor, true);
+ if (is_cursor) {
+ state->completion_type = COMPLETION_TYPE_DIRECTIVE;
+ }
+
+ if (directive == "if") {
+ process_if(p_tokenizer);
+ } else if (directive == "ifdef") {
+ process_ifdef(p_tokenizer);
+ } else if (directive == "ifndef") {
+ process_ifndef(p_tokenizer);
+ } else if (directive == "else") {
+ process_else(p_tokenizer);
+ } else if (directive == "endif") {
+ process_endif(p_tokenizer);
+ } else if (directive == "define") {
+ process_define(p_tokenizer);
+ } else if (directive == "undef") {
+ process_undef(p_tokenizer);
+ } else if (directive == "include") {
+ process_include(p_tokenizer);
+ } else if (directive == "pragma") {
+ process_pragma(p_tokenizer);
+ } else {
+ set_error(RTR("Unknown directive."), p_tokenizer->get_line());
+ }
+}
+
+void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ if (state->defines.has(label)) {
+ set_error(RTR("Macro redefinition."), line);
+ return;
+ }
+
+ if (p_tokenizer->peek() == '(') {
+ // Macro has arguments.
+ p_tokenizer->get_token();
+
+ Vector<String> args;
+ while (true) {
+ String name = p_tokenizer->get_identifier();
+ if (name.is_empty()) {
+ set_error(RTR("Invalid argument name."), line);
+ return;
+ }
+ args.push_back(name);
+
+ p_tokenizer->skip_whitespace();
+ char32_t next = p_tokenizer->get_token().text;
+ if (next == ')') {
+ break;
+ } else if (next != ',') {
+ set_error(RTR("Expected a comma in the macro argument list."), line);
+ return;
+ }
+ }
+
+ Define *define = memnew(Define);
+ define->arguments = args;
+ define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ state->defines[label] = define;
+ } else {
+ // Simple substitution macro.
+ Define *define = memnew(Define);
+ define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ state->defines[label] = define;
+ }
+}
+
+void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
+ if (state->skip_stack_else.is_empty()) {
+ set_error(RTR("Unmatched else."), p_tokenizer->get_line());
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1];
+ state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1);
+
+ 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 (skip) {
+ Vector<String> ends;
+ ends.push_back("endif");
+ next_directive(p_tokenizer, ends);
+ }
+}
+
+void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
+ state->condition_depth--;
+ if (state->condition_depth < 0) {
+ 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();
+ }
+ }
+
+ p_tokenizer->advance('\n');
+}
+
+void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
+ int line = p_tokenizer->get_line();
+
+ 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_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 success = v.booleanize();
+ start_branch_condition(p_tokenizer, success);
+}
+
+void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid ifdef."), line);
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool success = state->defines.has(label);
+ start_branch_condition(p_tokenizer, success);
+}
+
+void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid ifndef."), line);
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool success = !state->defines.has(label);
+ start_branch_condition(p_tokenizer, success);
+}
+
+void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ p_tokenizer->advance('"');
+ String path = tokens_to_string(p_tokenizer->advance('"'));
+ for (int i = 0; i < path.length(); i++) {
+ if (path[i] == '\n') {
+ break; //stop parsing
+ }
+ if (path[i] == CURSOR) {
+ state->completion_type = COMPLETION_TYPE_INCLUDE_PATH;
+ break;
+ }
+ }
+ path = path.substr(0, path.length() - 1);
+ p_tokenizer->skip_whitespace();
+
+ if (path.is_empty() || !is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid path."), line);
+ return;
+ }
+
+ Ref<Resource> res = ResourceLoader::load(path);
+ if (res.is_null()) {
+ set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line);
+ return;
+ }
+
+ Ref<ShaderInclude> shader_inc = res;
+ if (shader_inc.is_null()) {
+ set_error(RTR("Shader include resource type is wrong."), line);
+ return;
+ }
+
+ String included = shader_inc->get_code();
+ if (!included.is_empty()) {
+ uint64_t code_hash = included.hash64();
+ if (state->cyclic_include_hashes.find(code_hash)) {
+ set_error(RTR("Cyclic include found."), line);
+ return;
+ }
+ }
+
+ state->shader_includes.insert(shader_inc);
+
+ const String real_path = shader_inc->get_path();
+ if (state->includes.has(real_path)) {
+ // Already included, skip.
+ // This is a valid check because 2 separate include paths could use some
+ // of the same shared functions from a common shader include.
+ return;
+ }
+
+ // Mark as included.
+ state->includes.insert(real_path);
+
+ state->include_depth++;
+ if (state->include_depth > 25) {
+ set_error(RTR("Shader max include depth exceeded."), line);
+ return;
+ }
+
+ String old_include = state->current_include;
+ state->current_include = real_path;
+ ShaderPreprocessor processor;
+
+ int prev_condition_depth = state->condition_depth;
+ state->condition_depth = 0;
+
+ FilePosition fp;
+ fp.file = state->current_include;
+ fp.line = line;
+ state->include_positions.push_back(fp);
+
+ String result;
+ processor.preprocess(state, included, result);
+ add_to_output("@@>" + real_path + "\n"); // Add token for enter include path
+ add_to_output(result);
+ add_to_output("\n@@<\n"); // Add token for exit include path
+
+ // 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->include_positions.pop_back();
+ } else {
+ return;
+ }
+
+ state->include_depth--;
+ state->condition_depth = prev_condition_depth;
+}
+
+void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ bool is_cursor;
+ const String label = p_tokenizer->get_identifier(&is_cursor);
+ if (is_cursor) {
+ state->completion_type = COMPLETION_TYPE_PRAGMA;
+ }
+
+ if (label.is_empty()) {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
+
+ // Rxplicitly handle pragma values here.
+ // If more pragma options are created, then refactor into a more defined structure.
+ if (label == "disable_preprocessor") {
+ state->disabled = true;
+ } else {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
+
+ p_tokenizer->advance('\n');
+}
+
+void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+ const String label = p_tokenizer->get_identifier();
+ if (label.is_empty() || !state->defines.has(label)) {
+ set_error(RTR("Invalid name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid undef."), line);
+ return;
+ }
+
+ memdelete(state->defines[label]);
+ state->defines.erase(label);
+}
+
+void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) {
+ state->condition_depth++;
+
+ if (p_success) {
+ state->skip_stack_else.push_back(true);
+ } else {
+ SkippedCondition *cond = memnew(SkippedCondition());
+ cond->start_line = p_tokenizer->get_line();
+ state->skipped_conditions[state->current_include].push_back(cond);
+
+ Vector<String> ends;
+ 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);
+ }
+ }
+}
+
+void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) {
+ String line = vector_to_string(output, p_start, output.size());
+
+ Error error = expand_macros(line, p_line_number - 1, line); // We are already on next line, so -1.
+ if (error != OK) {
+ return;
+ }
+
+ output.resize(p_start);
+
+ 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()));
+ }
+
+ return expand_macros(p_string, p_line, active_defines, r_expanded);
+}
+
+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;
+ }
+
+ // Remove expanded macro and recursively replace remaining.
+ p_defines.remove_at(i);
+ return expand_macros(r_expanded, p_line, p_defines, r_expanded);
+ }
+
+ return OK;
+}
+
+Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) {
+ String result = p_line;
+
+ const String &key = p_define_pair.first;
+ const Define *define = p_define_pair.second;
+
+ int index_start = 0;
+ int index = 0;
+ while (find_match(result, key, index, index_start)) {
+ String body = define->body;
+ if (define->arguments.size() > 0) {
+ // Complex macro with arguments.
+ int args_start = index + key.length();
+ 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;
+ }
+
+ 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;
+ }
+
+ // Insert macro arguments into the body.
+ for (int i = 0; i < args.size(); i++) {
+ String arg_name = define->arguments[i];
+ int arg_index_start = 0;
+ int arg_index = 0;
+ while (find_match(body, arg_name, arg_index, arg_index_start)) {
+ body = body.substr(0, arg_index) + args[i] + body.substr(arg_index + arg_name.length(), body.length() - (arg_index + arg_name.length()));
+ // Manually reset arg_index_start to where the arg value of the define finishes.
+ // This ensures we don't skip the other args of this macro in the string.
+ arg_index_start = arg_index + args[i].length() + 1;
+ }
+ }
+
+ result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length());
+ } else {
+ result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length()));
+ // 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 OK;
+}
+
+bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) {
+ // Looks for value in string and then determines if the boundaries
+ // are non-word characters. This method semi-emulates \b in regex.
+ r_index = p_string.find(p_value, r_index_start);
+ while (r_index > -1) {
+ if (r_index > 0) {
+ if (is_char_word(p_string[r_index - 1])) {
+ r_index_start = r_index + 1;
+ r_index = p_string.find(p_value, r_index_start);
+ continue;
+ }
+ }
+
+ if (r_index + p_value.length() < p_string.length()) {
+ if (is_char_word(p_string[r_index + p_value.length()])) {
+ r_index_start = r_index + p_value.length() + 1;
+ r_index = p_string.find(p_value, r_index_start);
+ continue;
+ }
+ }
+
+ // Return and shift index start automatically for next call.
+ r_index_start = r_index + p_value.length() + 1;
+ return true;
+ }
+
+ return false;
+}
+
+String ShaderPreprocessor::next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives) {
+ const int line = p_tokenizer->get_line();
+ int nesting = 0;
+
+ while (true) {
+ p_tokenizer->advance('#');
+
+ String id = p_tokenizer->peek_identifier();
+ if (id.is_empty()) {
+ break;
+ }
+
+ if (nesting == 0) {
+ for (int i = 0; i < p_directives.size(); i++) {
+ if (p_directives[i] == id) {
+ p_tokenizer->backtrack('#');
+ return id;
+ }
+ }
+ }
+
+ if (id == "ifdef" || id == "ifndef" || id == "if") {
+ nesting++;
+ } else if (id == "endif") {
+ nesting--;
+ }
+ }
+
+ set_error(RTR("Can't find matching branch directive."), line);
+ return "";
+}
+
+void ShaderPreprocessor::add_to_output(const String &p_str) {
+ for (int i = 0; i < p_str.length(); i++) {
+ output.push_back(p_str[i]);
+ }
+}
+
+void ShaderPreprocessor::set_error(const String &p_error, int p_line) {
+ if (state->error.is_empty()) {
+ state->error = p_error;
+ FilePosition fp;
+ fp.line = p_line + 1;
+ state->include_positions.push_back(fp);
+ }
+}
+
+ShaderPreprocessor::Define *ShaderPreprocessor::create_define(const String &p_body) {
+ ShaderPreprocessor::Define *define = memnew(Define);
+ define->body = p_body;
+ return define;
+}
+
+void ShaderPreprocessor::clear() {
+ if (state_owner && state != nullptr) {
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ 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;
+ state = nullptr;
+}
+
+Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, String &r_result) {
+ clear();
+
+ output.clear();
+
+ state = p_state;
+
+ CommentRemover remover(p_code);
+ String stripped = remover.strip();
+ String error = remover.get_error();
+ if (!error.is_empty()) {
+ set_error(error, remover.get_error_line());
+ return FAILED;
+ }
+
+ // Track code hashes to prevent cyclic include.
+ uint64_t code_hash = p_code.hash64();
+ state->cyclic_include_hashes.push_back(code_hash);
+
+ Tokenizer p_tokenizer(stripped);
+ int last_size = 0;
+ bool has_symbols_before_directive = false;
+
+ while (true) {
+ const Token &t = p_tokenizer.get_token();
+
+ if (t.text == 0) {
+ break;
+ }
+
+ if (state->disabled) {
+ // Preprocessor was disabled.
+ // Read the rest of the file into the output.
+ output.push_back(t.text);
+ continue;
+ } else {
+ // Add autogenerated tokens.
+ Vector<Token> generated;
+ p_tokenizer.get_and_clear_generated(&generated);
+ for (int i = 0; i < generated.size(); i++) {
+ output.push_back(generated[i].text);
+ }
+ }
+
+ if (t.text == '#') {
+ if (has_symbols_before_directive) {
+ set_error(RTR("Invalid symbols placed before directive."), p_tokenizer.get_line());
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+ return FAILED;
+ }
+ process_directive(&p_tokenizer);
+ } else {
+ if (is_char_end(t.text)) {
+ expand_output_macros(last_size, p_tokenizer.get_line());
+ last_size = output.size();
+ has_symbols_before_directive = false;
+ } else if (!is_char_space(t.text)) {
+ has_symbols_before_directive = true;
+ }
+ output.push_back(t.text);
+ }
+
+ if (!state->error.is_empty()) {
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+ return FAILED;
+ }
+ }
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+
+ if (!state->disabled) {
+ if (state->condition_depth != 0) {
+ set_error(RTR("Unmatched conditional statement."), p_tokenizer.line);
+ return FAILED;
+ }
+
+ expand_output_macros(last_size, p_tokenizer.get_line());
+ }
+
+ r_result = vector_to_string(output);
+
+ 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) {
+ State pp_state;
+ Error err = preprocess(&pp_state, p_code, r_result);
+ if (err != OK) {
+ if (r_error_text) {
+ *r_error_text = pp_state.error;
+ }
+ if (r_error_position) {
+ *r_error_position = pp_state.include_positions;
+ }
+ }
+ if (r_includes) {
+ *r_includes = pp_state.shader_includes;
+ }
+
+ if (r_completion_options) {
+ switch (pp_state.completion_type) {
+ case COMPLETION_TYPE_DIRECTIVE: {
+ List<String> options;
+ get_keyword_list(&options, true);
+
+ for (const String &E : options) {
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+ }
+
+ } break;
+ case COMPLETION_TYPE_PRAGMA: {
+ List<String> options;
+
+ ShaderPreprocessor::get_pragma_list(&options);
+
+ for (const String &E : options) {
+ ScriptLanguage::CodeCompletionOption option(E, 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);
+ }
+
+ } break;
+ default: {
+ }
+ }
+ }
+ return err;
+}
+
+void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) {
+ r_keywords->push_back("define");
+ if (p_include_shader_keywords) {
+ r_keywords->push_back("else");
+ }
+ r_keywords->push_back("endif");
+ if (p_include_shader_keywords) {
+ r_keywords->push_back("if");
+ }
+ r_keywords->push_back("ifdef");
+ r_keywords->push_back("ifndef");
+ r_keywords->push_back("include");
+ r_keywords->push_back("pragma");
+ r_keywords->push_back("undef");
+}
+
+void ShaderPreprocessor::get_pragma_list(List<String> *r_pragmas) {
+ r_pragmas->push_back("disable_preprocessor");
+}
+
+ShaderPreprocessor::ShaderPreprocessor() {
+}
+
+ShaderPreprocessor::~ShaderPreprocessor() {
+ clear();
+}
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
new file mode 100644
index 0000000000..a93fb680dd
--- /dev/null
+++ b/servers/rendering/shader_preprocessor.h
@@ -0,0 +1,200 @@
+/*************************************************************************/
+/* shader_preprocessor.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 SHADER_PREPROCESSOR_H
+#define SHADER_PREPROCESSOR_H
+
+#include "core/string/ustring.h"
+#include "core/templates/list.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/rb_map.h"
+#include "core/templates/rb_set.h"
+#include "core/typedefs.h"
+
+#include "core/io/resource_loader.h"
+#include "core/os/os.h"
+#include "scene/resources/shader.h"
+#include "scene/resources/shader_include.h"
+
+class ShaderPreprocessor {
+public:
+ enum CompletionType {
+ COMPLETION_TYPE_NONE,
+ COMPLETION_TYPE_DIRECTIVE,
+ COMPLETION_TYPE_PRAGMA_DIRECTIVE,
+ COMPLETION_TYPE_PRAGMA,
+ COMPLETION_TYPE_INCLUDE_PATH,
+ };
+
+ struct FilePosition {
+ String file;
+ int line = 0;
+ };
+
+private:
+ struct Token {
+ char32_t text;
+ int line;
+
+ Token();
+ Token(char32_t p_text, int p_line);
+ };
+
+ // The real preprocessor that understands basic shader and preprocessor language syntax.
+ class Tokenizer {
+ public:
+ String code;
+ int line;
+ int index;
+ int size;
+ Vector<Token> generated;
+
+ private:
+ void add_generated(const Token &p_t);
+ char32_t next();
+
+ public:
+ int get_line() const;
+ int get_index() const;
+ char32_t peek();
+
+ void get_and_clear_generated(Vector<Token> *r_out);
+ void backtrack(char32_t p_what);
+ LocalVector<Token> advance(char32_t p_what);
+ void skip_whitespace();
+ String get_identifier(bool *r_is_cursor = nullptr, bool p_started = false);
+ String peek_identifier();
+ Token get_token();
+
+ Tokenizer(const String &p_code);
+ };
+
+ class CommentRemover {
+ private:
+ LocalVector<char32_t> stripped;
+ String code;
+ int index;
+ int line;
+ int comment_line_open;
+ int comments_open;
+ int strings_open;
+
+ public:
+ String get_error() const;
+ int get_error_line() const;
+ char32_t peek() const;
+
+ bool advance(char32_t p_what);
+ String strip();
+
+ CommentRemover(const String &p_code);
+ };
+
+ struct Define {
+ Vector<String> arguments;
+ String body;
+ };
+
+ struct SkippedCondition {
+ int start_line = -1;
+ int end_line = -1;
+ };
+
+ struct State {
+ RBMap<String, Define *> defines;
+ Vector<bool> skip_stack_else;
+ 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_shader_type;
+ String error;
+ List<FilePosition> include_positions;
+ RBMap<String, Vector<SkippedCondition *>> skipped_conditions;
+ bool disabled = false;
+ CompletionType completion_type = COMPLETION_TYPE_NONE;
+ HashSet<Ref<ShaderInclude>> shader_includes;
+ };
+
+private:
+ LocalVector<char32_t> output;
+ State *state = nullptr;
+ bool state_owner = false;
+
+private:
+ static bool is_char_word(char32_t p_char);
+ static bool is_char_space(char32_t p_char);
+ static bool is_char_end(char32_t p_char);
+ 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 process_directive(Tokenizer *p_tokenizer);
+ void process_define(Tokenizer *p_tokenizer);
+ void process_else(Tokenizer *p_tokenizer);
+ void process_endif(Tokenizer *p_tokenizer);
+ void process_if(Tokenizer *p_tokenizer);
+ void process_ifdef(Tokenizer *p_tokenizer);
+ void process_ifndef(Tokenizer *p_tokenizer);
+ void process_include(Tokenizer *p_tokenizer);
+ void process_pragma(Tokenizer *p_tokenizer);
+ void process_undef(Tokenizer *p_tokenizer);
+
+ void start_branch_condition(Tokenizer *p_tokenizer, bool p_success);
+
+ 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 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);
+ void add_to_output(const String &p_str);
+ void set_error(const String &p_error, int p_line);
+
+ static Define *create_define(const String &p_body);
+
+ void clear();
+
+ Error preprocess(State *p_state, const String &p_code, String &r_result);
+
+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);
+
+ static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords);
+ static void get_pragma_list(List<String> *r_pragmas);
+
+ ShaderPreprocessor();
+ ~ShaderPreprocessor();
+};
+
+#endif // SHADER_PREPROCESSOR_H
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 107525cd15..dfec3a7111 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADERTYPES_H
-#define SHADERTYPES_H
+#ifndef SHADER_TYPES_H
+#define SHADER_TYPES_H
#include "core/templates/rb_map.h"
#include "servers/rendering_server.h"
@@ -59,4 +59,4 @@ public:
ShaderTypes();
};
-#endif // SHADERTYPES_H
+#endif // SHADER_TYPES_H
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index 8edf85842f..d5c6a4b1a6 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADER_WARNINGS
-#define SHADER_WARNINGS
+#ifndef SHADER_WARNINGS_H
+#define SHADER_WARNINGS_H
#ifdef DEBUG_ENABLED
@@ -90,4 +90,4 @@ public:
#endif // DEBUG_ENABLED
-#endif // SHADER_WARNINGS
+#endif // SHADER_WARNINGS_H
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index f627e46e52..087ea1a025 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -135,4 +135,4 @@ public:
virtual float lightmap_get_probe_capture_update_speed() const = 0;
};
-#endif // !LIGHT_STORAGE_H
+#endif // LIGHT_STORAGE_H
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
index 00790106af..3566502144 100644
--- a/servers/rendering/storage/material_storage.h
+++ b/servers/rendering/storage/material_storage.h
@@ -61,6 +61,7 @@ public:
virtual void shader_free(RID p_rid) = 0;
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;
@@ -98,4 +99,4 @@ public:
virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
};
-#endif // !MATERIAL_STORAGE_H
+#endif // MATERIAL_STORAGE_H
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
index 146f6fde40..5b3738dfd7 100644
--- a/servers/rendering/storage/mesh_storage.h
+++ b/servers/rendering/storage/mesh_storage.h
@@ -133,4 +133,4 @@ public:
virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
};
-#endif // !MESH_STORAGE_H
+#endif // MESH_STORAGE_H
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index eba68210a5..ee4b8679b3 100644
--- a/servers/rendering/storage/particles_storage.h
+++ b/servers/rendering/storage/particles_storage.h
@@ -125,4 +125,4 @@ public:
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
};
-#endif // !PARTICLES_STORAGE_H
+#endif // PARTICLES_STORAGE_H
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index 92238c19ee..982ab4a958 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -148,4 +148,4 @@ public:
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
};
-#endif // !TEXTURE_STORAGE_H
+#endif // TEXTURE_STORAGE_H
diff --git a/servers/rendering/storage/utilities.h b/servers/rendering/storage/utilities.h
index 4d7c34383c..d240d58917 100644
--- a/servers/rendering/storage/utilities.h
+++ b/servers/rendering/storage/utilities.h
@@ -183,4 +183,4 @@ public:
virtual String get_video_adapter_api_version() const = 0;
};
-#endif // !RENDERER_UTILITIES_H
+#endif // RENDERER_UTILITIES_H
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 5ee12d04d9..73405dcbed 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1709,6 +1709,8 @@ void RenderingServer::_bind_methods() {
/* SHADER */
ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create);
+ 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_param_default", "shader", "param"), &RenderingServer::shader_get_param_default);
@@ -2829,7 +2831,6 @@ void RenderingServer::set_render_loop_enabled(bool p_enabled) {
RenderingServer::RenderingServer() {
//ERR_FAIL_COND(singleton);
- thread_pool = memnew(RendererThreadPool);
singleton = this;
}
@@ -3030,6 +3031,5 @@ void RenderingServer::init() {
}
RenderingServer::~RenderingServer() {
- memdelete(thread_pool);
singleton = nullptr;
}
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 8d224f2832..dcb2683add 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -35,11 +35,11 @@
#include "core/math/geometry_3d.h"
#include "core/math/transform_2d.h"
#include "core/object/class_db.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/rid.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant.h"
#include "servers/display_server.h"
-#include "servers/rendering/renderer_thread_pool.h"
#include "servers/rendering/rendering_device.h"
class RenderingServer : public Object {
@@ -52,8 +52,6 @@ class RenderingServer : public Object {
Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const;
- RendererThreadPool *thread_pool = nullptr;
-
const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
@@ -170,6 +168,7 @@ public:
virtual RID shader_create() = 0;
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 Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0;
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 2c4aab0784..318c844a2f 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef SERVER_WRAP_MT_COMMON_H
+#define SERVER_WRAP_MT_COMMON_H
+
#define FUNC0R(m_r, m_type) \
virtual m_r m_type() override { \
if (Thread::get_caller_id() != server_thread) { \
@@ -762,3 +765,5 @@
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
} \
}
+
+#endif // SERVER_WRAP_MT_COMMON_H
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 0808b1fd7b..4b9ea40223 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -195,7 +195,7 @@ RID XRInterface::get_vrs_texture() {
uint8_t *data_ptr = data.ptrw();
// Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
- CameraMatrix cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
+ Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
Vector2i view_center;
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index b4eb4694f6..f11458f1cc 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -31,7 +31,7 @@
#ifndef XR_INTERFACE_H
#define XR_INTERFACE_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
@@ -119,7 +119,7 @@ public:
virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
virtual RID get_vrs_texture(); /* obtain VRS texture */
// note, external color/depth/vrs texture support will be added here soon.
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 94953c69a9..7395cd5ad4 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -258,12 +258,12 @@ Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const
return Transform3D();
}
-CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
- CameraMatrix cm;
+Projection XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+ Projection cm;
PackedFloat64Array arr;
if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) {
- ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats");
+ ERR_FAIL_COND_V_MSG(arr.size() != 16, Projection(), "Projection matrix must contain 16 floats");
real_t *m = (real_t *)cm.matrix;
for (int i = 0; i < 16; i++) {
m[i] = arr[i];
@@ -271,7 +271,7 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub
return cm;
}
- return CameraMatrix();
+ return Projection();
}
RID XRInterfaceExtension::get_vrs_texture() {
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 7174b412c5..65b474425e 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -100,7 +100,7 @@ public:
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual RID get_vrs_texture() override;
GDVIRTUAL0R(Size2, _get_render_target_size);
@@ -132,4 +132,4 @@ public:
// RID get_render_target_depth(RID p_render_target);
};
-#endif // !XR_INTERFACE_EXTENSION_H
+#endif // XR_INTERFACE_EXTENSION_H
diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h
index f306c22390..e7d363764b 100644
--- a/servers/xr/xr_pose.h
+++ b/servers/xr/xr_pose.h
@@ -78,4 +78,4 @@ public:
VARIANT_ENUM_CAST(XRPose::TrackingConfidence);
-#endif
+#endif // XR_POSE_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index ad61aa94bc..990281d96d 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -33,6 +33,16 @@
#include "xr/xr_interface.h"
#include "xr/xr_positional_tracker.h"
+XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT;
+
+XRServer::XRMode XRServer::get_xr_mode() {
+ return xr_mode;
+}
+
+void XRServer::set_xr_mode(XRServer::XRMode p_mode) {
+ xr_mode = p_mode;
+}
+
XRServer *XRServer::singleton = nullptr;
XRServer *XRServer::get_singleton() {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index d9188d2de1..74128bfb54 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -57,6 +57,12 @@ class XRServer : public Object {
_THREAD_SAFE_CLASS_
public:
+ enum XRMode {
+ XRMODE_DEFAULT, /* Default behaviour, means we check project settings */
+ XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */
+ XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */
+ };
+
enum TrackerType {
TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */
TRACKER_CONTROLLER = 0x02, /* tracks a controller */
@@ -75,6 +81,8 @@ public:
};
private:
+ static XRMode xr_mode;
+
Vector<Ref<XRInterface>> interfaces;
Dictionary trackers;
@@ -90,6 +98,9 @@ protected:
static void _bind_methods();
public:
+ static XRMode get_xr_mode();
+ static void set_xr_mode(XRMode p_mode);
+
static XRServer *get_singleton();
/*