diff options
33 files changed, 3540 insertions, 3119 deletions
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index b05c13a76d..1aa03f90dd 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -41,6 +41,7 @@  #include "storage/light_storage.h"  #include "storage/material_storage.h"  #include "storage/mesh_storage.h" +#include "storage/particles_storage.h"  #include "storage/texture_storage.h"  class RasterizerGLES3 : public RendererCompositor { @@ -55,6 +56,7 @@ protected:  	GLES3::TextureStorage texture_storage;  	GLES3::MaterialStorage material_storage;  	GLES3::MeshStorage mesh_storage; +	GLES3::ParticlesStorage particles_storage;  	GLES3::LightStorage light_storage;  	RasterizerStorageGLES3 storage;  	RasterizerCanvasGLES3 canvas; @@ -66,6 +68,7 @@ public:  	RendererLightStorage *get_light_storage() { return &light_storage; }  	RendererMaterialStorage *get_material_storage() { return &material_storage; }  	RendererMeshStorage *get_mesh_storage() { return &mesh_storage; } +	RendererParticlesStorage *get_particles_storage() { return &particles_storage; }  	RendererTextureStorage *get_texture_storage() { return &texture_storage; }  	RendererStorage *get_storage() { return &storage; }  	RendererCanvasRender *get_canvas() { return &canvas; } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 75009336f8..95d0a90ab1 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -164,198 +164,7 @@ uint32_t RasterizerStorageGLES3::voxel_gi_get_version(RID p_voxel_gi) {  void RasterizerStorageGLES3::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {  } -/* PARTICLES */ - -RID RasterizerStorageGLES3::particles_allocate() { -	return RID(); -} - -void RasterizerStorageGLES3::particles_initialize(RID p_rid) { -} - -void RasterizerStorageGLES3::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) { -} - -void RasterizerStorageGLES3::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { -} - -void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emitting) { -} - -void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) { -} - -void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles, double p_lifetime) { -} - -void RasterizerStorageGLES3::particles_set_one_shot(RID p_particles, bool p_one_shot) { -} - -void RasterizerStorageGLES3::particles_set_pre_process_time(RID p_particles, double p_time) { -} - -void RasterizerStorageGLES3::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) { -} - -void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) { -} - -void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { -} - -void RasterizerStorageGLES3::particles_set_speed_scale(RID p_particles, double p_scale) { -} - -void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { -} - -void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) { -} -RID RasterizerStorageGLES3::particles_get_process_material(RID p_particles) const { -	return RID(); -} - -void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) { -} - -void RasterizerStorageGLES3::particles_set_interpolate(RID p_particles, bool p_enable) { -} - -void RasterizerStorageGLES3::particles_set_fractional_delta(RID p_particles, bool p_enable) { -} - -void RasterizerStorageGLES3::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { -} - -void RasterizerStorageGLES3::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) { -} - -void RasterizerStorageGLES3::particles_set_collision_base_size(RID p_particles, real_t p_size) { -} - -void RasterizerStorageGLES3::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) { -} - -void RasterizerStorageGLES3::particles_set_trails(RID p_particles, bool p_enable, double p_length) { -} - -void RasterizerStorageGLES3::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) { -} - -void RasterizerStorageGLES3::particles_restart(RID p_particles) { -} - -void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { -} - -void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_count) { -} - -void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { -} - -void RasterizerStorageGLES3::particles_request_process(RID p_particles) { -} - -AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { -	return AABB(); -} - -AABB RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const { -	return AABB(); -} - -void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) { -} - -bool RasterizerStorageGLES3::particles_get_emitting(RID p_particles) { -	return false; -} - -int RasterizerStorageGLES3::particles_get_draw_passes(RID p_particles) const { -	return 0; -} - -RID RasterizerStorageGLES3::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { -	return RID(); -} - -void RasterizerStorageGLES3::particles_add_collision(RID p_particles, RID p_instance) { -} - -void RasterizerStorageGLES3::particles_remove_collision(RID p_particles, RID p_instance) { -} - -void RasterizerStorageGLES3::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) { -} - -void RasterizerStorageGLES3::update_particles() { -} - -bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const { -	return false; -} - -/* PARTICLES COLLISION */ - -RID RasterizerStorageGLES3::particles_collision_allocate() { -	return RID(); -} - -void RasterizerStorageGLES3::particles_collision_initialize(RID p_rid) { -} - -void RasterizerStorageGLES3::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { -} - -void RasterizerStorageGLES3::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { -} - -void RasterizerStorageGLES3::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) { -} - -void RasterizerStorageGLES3::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { -} - -void RasterizerStorageGLES3::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) { -} - -void RasterizerStorageGLES3::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) { -} - -void RasterizerStorageGLES3::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) { -} - -void RasterizerStorageGLES3::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { -} - -void RasterizerStorageGLES3::particles_collision_height_field_update(RID p_particles_collision) { -} - -void RasterizerStorageGLES3::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { -} - -AABB RasterizerStorageGLES3::particles_collision_get_aabb(RID p_particles_collision) const { -	return AABB(); -} - -bool RasterizerStorageGLES3::particles_collision_is_heightfield(RID p_particles_collision) const { -	return false; -} - -RID RasterizerStorageGLES3::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { -	return RID(); -} - -RID RasterizerStorageGLES3::particles_collision_instance_create(RID p_collision) { -	return RID(); -} - -void RasterizerStorageGLES3::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) { -} - -void RasterizerStorageGLES3::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { -} +/* FOG */  RID RasterizerStorageGLES3::fog_volume_allocate() {  	return RID(); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 01041825b6..da1dd0e66b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -175,83 +175,6 @@ public:  	void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices); -	/* PARTICLES */ - -	RID particles_allocate() override; -	void particles_initialize(RID p_rid) override; -	void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; -	void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override; -	void particles_set_emitting(RID p_particles, bool p_emitting) override; -	void particles_set_amount(RID p_particles, int p_amount) override; -	void particles_set_lifetime(RID p_particles, double p_lifetime) override; -	void particles_set_one_shot(RID p_particles, bool p_one_shot) override; -	void particles_set_pre_process_time(RID p_particles, double p_time) override; -	void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override; -	void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override; -	void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override; -	void particles_set_speed_scale(RID p_particles, double p_scale) override; -	void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override; -	void particles_set_process_material(RID p_particles, RID p_material) override; -	RID particles_get_process_material(RID p_particles) const override; -	void particles_set_fixed_fps(RID p_particles, int p_fps) override; -	void particles_set_interpolate(RID p_particles, bool p_enable) override; -	void particles_set_fractional_delta(RID p_particles, bool p_enable) override; -	void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override; -	void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override; -	void particles_set_collision_base_size(RID p_particles, real_t p_size) override; - -	void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override; - -	void particles_set_trails(RID p_particles, bool p_enable, double p_length) override; -	void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override; - -	void particles_restart(RID p_particles) override; - -	void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override; - -	void particles_set_draw_passes(RID p_particles, int p_count) override; -	void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override; - -	void particles_request_process(RID p_particles) override; -	AABB particles_get_current_aabb(RID p_particles) override; -	AABB particles_get_aabb(RID p_particles) const override; - -	void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override; - -	bool particles_get_emitting(RID p_particles) override; -	int particles_get_draw_passes(RID p_particles) const override; -	RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override; - -	void particles_add_collision(RID p_particles, RID p_instance) override; -	void particles_remove_collision(RID p_particles, RID p_instance) override; - -	void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override; - -	void update_particles() override; -	bool particles_is_inactive(RID p_particles) const override; - -	/* PARTICLES COLLISION */ - -	RID particles_collision_allocate() override; -	void particles_collision_initialize(RID p_rid) override; -	void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override; -	void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override; -	void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; -	void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; -	void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override; -	void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override; -	void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override; -	void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; -	void particles_collision_height_field_update(RID p_particles_collision) override; -	void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; -	AABB particles_collision_get_aabb(RID p_particles_collision) const override; -	bool particles_collision_is_heightfield(RID p_particles_collision) const override; -	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; - -	RID particles_collision_instance_create(RID p_collision) override; -	void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override; -	void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override; -  	/* FOG VOLUMES */  	RID fog_volume_allocate() override; diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp new file mode 100644 index 0000000000..9ed9fedd5a --- /dev/null +++ b/drivers/gles3/storage/particles_storage.cpp @@ -0,0 +1,254 @@ +/*************************************************************************/ +/*  particles_storage.cpp                                                */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "particles_storage.h" + +using namespace GLES3; + +ParticlesStorage *ParticlesStorage::singleton = nullptr; + +ParticlesStorage *ParticlesStorage::get_singleton() { +	return singleton; +} + +ParticlesStorage::ParticlesStorage() { +	singleton = this; +} + +ParticlesStorage::~ParticlesStorage() { +	singleton = nullptr; +} + +/* PARTICLES */ + +RID ParticlesStorage::particles_allocate() { +	return RID(); +} + +void ParticlesStorage::particles_initialize(RID p_rid) { +} + +void ParticlesStorage::particles_free(RID p_rid) { +} + +void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) { +} + +void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { +} + +void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) { +} + +void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) { +} + +void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) { +} + +void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) { +} + +void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) { +} + +void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) { +} + +void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) { +} + +void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { +} + +void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) { +} + +void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { +} + +void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) { +} + +RID ParticlesStorage::particles_get_process_material(RID p_particles) const { +	return RID(); +} + +void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) { +} + +void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) { +} + +void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) { +} + +void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { +} + +void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) { +} + +void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) { +} + +void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) { +} + +void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) { +} + +void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) { +} + +void ParticlesStorage::particles_restart(RID p_particles) { +} + +void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { +} + +void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_count) { +} + +void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { +} + +void ParticlesStorage::particles_request_process(RID p_particles) { +} + +AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) { +	return AABB(); +} + +AABB ParticlesStorage::particles_get_aabb(RID p_particles) const { +	return AABB(); +} + +void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) { +} + +bool ParticlesStorage::particles_get_emitting(RID p_particles) { +	return false; +} + +int ParticlesStorage::particles_get_draw_passes(RID p_particles) const { +	return 0; +} + +RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { +	return RID(); +} + +void ParticlesStorage::particles_add_collision(RID p_particles, RID p_instance) { +} + +void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_instance) { +} + +void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) { +} + +void ParticlesStorage::update_particles() { +} + +bool ParticlesStorage::particles_is_inactive(RID p_particles) const { +	return false; +} + +/* PARTICLES COLLISION */ + +RID ParticlesStorage::particles_collision_allocate() { +	return RID(); +} + +void ParticlesStorage::particles_collision_initialize(RID p_rid) { +} + +void ParticlesStorage::particles_collision_free(RID p_rid) { +} + +void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { +} + +void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { +} + +void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) { +} + +void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { +} + +void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) { +} + +void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) { +} + +void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) { +} + +void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { +} + +void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) { +} + +void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { +} + +AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const { +	return AABB(); +} + +bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const { +	return false; +} + +RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { +	return RID(); +} + +RID ParticlesStorage::particles_collision_instance_create(RID p_collision) { +	return RID(); +} + +void ParticlesStorage::particles_collision_instance_free(RID p_rid) { +} + +void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) { +} + +void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h new file mode 100644 index 0000000000..cf47ada5d5 --- /dev/null +++ b/drivers/gles3/storage/particles_storage.h @@ -0,0 +1,140 @@ +/*************************************************************************/ +/*  particles_storage.h                                                  */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#ifndef PARTICLES_STORAGE_GLES3_H +#define PARTICLES_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/storage/particles_storage.h" + +namespace GLES3 { + +class ParticlesStorage : public RendererParticlesStorage { +private: +	static ParticlesStorage *singleton; + +public: +	static ParticlesStorage *get_singleton(); + +	ParticlesStorage(); +	virtual ~ParticlesStorage(); + +	/* PARTICLES */ + +	virtual RID particles_allocate() override; +	virtual void particles_initialize(RID p_rid) override; +	virtual void particles_free(RID p_rid) override; + +	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; +	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override; +	virtual void particles_set_emitting(RID p_particles, bool p_emitting) override; +	virtual void particles_set_amount(RID p_particles, int p_amount) override; +	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override; +	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override; +	virtual void particles_set_pre_process_time(RID p_particles, double p_time) override; +	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override; +	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override; +	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override; +	virtual void particles_set_speed_scale(RID p_particles, double p_scale) override; +	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override; +	virtual void particles_set_process_material(RID p_particles, RID p_material) override; +	virtual RID particles_get_process_material(RID p_particles) const override; +	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override; +	virtual void particles_set_interpolate(RID p_particles, bool p_enable) override; +	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override; +	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override; +	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override; +	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override; + +	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override; + +	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override; +	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override; + +	virtual void particles_restart(RID p_particles) override; + +	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override; + +	virtual void particles_set_draw_passes(RID p_particles, int p_count) override; +	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override; + +	virtual void particles_request_process(RID p_particles) override; +	virtual AABB particles_get_current_aabb(RID p_particles) override; +	virtual AABB particles_get_aabb(RID p_particles) const override; + +	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override; + +	virtual bool particles_get_emitting(RID p_particles) override; +	virtual int particles_get_draw_passes(RID p_particles) const override; +	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override; + +	virtual void particles_add_collision(RID p_particles, RID p_instance) override; +	virtual void particles_remove_collision(RID p_particles, RID p_instance) override; + +	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override; + +	virtual void update_particles() override; +	virtual bool particles_is_inactive(RID p_particles) const override; + +	/* PARTICLES COLLISION */ + +	virtual RID particles_collision_allocate() override; +	virtual void particles_collision_initialize(RID p_rid) override; +	virtual void particles_collision_free(RID p_rid) override; + +	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override; +	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override; +	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; +	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; +	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override; +	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override; +	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override; +	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; +	virtual void particles_collision_height_field_update(RID p_particles_collision) override; +	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; +	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override; +	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; +	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; + +	virtual RID particles_collision_instance_create(RID p_collision) override; +	virtual void particles_collision_instance_free(RID p_rid) override; +	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override; +	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override; +}; + +} // namespace GLES3 + +#endif // GLES3_ENABLED + +#endif // !PARTICLES_STORAGE_GLES3_H diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index 17bf88bbd7..6cad45ea6d 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -40,6 +40,7 @@  #include "servers/rendering/dummy/storage/light_storage.h"  #include "servers/rendering/dummy/storage/material_storage.h"  #include "servers/rendering/dummy/storage/mesh_storage.h" +#include "servers/rendering/dummy/storage/particles_storage.h"  #include "servers/rendering/dummy/storage/texture_storage.h"  #include "servers/rendering/renderer_compositor.h"  #include "servers/rendering_server.h" @@ -54,6 +55,7 @@ protected:  	RendererDummy::LightStorage light_storage;  	RendererDummy::MaterialStorage material_storage;  	RendererDummy::MeshStorage mesh_storage; +	RendererDummy::ParticlesStorage particles_storage;  	RendererDummy::TextureStorage texture_storage;  	RasterizerStorageDummy storage;  	RasterizerSceneDummy scene; @@ -62,6 +64,7 @@ public:  	RendererLightStorage *get_light_storage() override { return &light_storage; };  	RendererMaterialStorage *get_material_storage() override { return &material_storage; };  	RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; }; +	RendererParticlesStorage *get_particles_storage() override { return &particles_storage; };  	RendererTextureStorage *get_texture_storage() override { return &texture_storage; };  	RendererStorage *get_storage() override { return &storage; }  	RendererCanvasRender *get_canvas() override { return &canvas; } diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h index 9aaeead1c2..ac6085cdec 100644 --- a/servers/rendering/dummy/rasterizer_storage_dummy.h +++ b/servers/rendering/dummy/rasterizer_storage_dummy.h @@ -83,84 +83,6 @@ public:  	void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {} -	/* PARTICLES */ - -	RID particles_allocate() override { return RID(); } -	void particles_initialize(RID p_rid) override {} -	void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {} -	void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {} -	void particles_set_emitting(RID p_particles, bool p_emitting) override {} -	void particles_set_amount(RID p_particles, int p_amount) override {} -	void particles_set_lifetime(RID p_particles, double p_lifetime) override {} -	void particles_set_one_shot(RID p_particles, bool p_one_shot) override {} -	void particles_set_pre_process_time(RID p_particles, double p_time) override {} -	void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {} -	void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {} -	void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {} -	void particles_set_speed_scale(RID p_particles, double p_scale) override {} -	void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {} -	void particles_set_process_material(RID p_particles, RID p_material) override {} -	RID particles_get_process_material(RID p_particles) const override { return RID(); } -	void particles_set_fixed_fps(RID p_particles, int p_fps) override {} -	void particles_set_interpolate(RID p_particles, bool p_enable) override {} -	void particles_set_fractional_delta(RID p_particles, bool p_enable) override {} -	void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {} -	void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {} -	void particles_set_collision_base_size(RID p_particles, real_t p_size) override {} - -	void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {} - -	void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {} -	void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {} - -	void particles_restart(RID p_particles) override {} - -	void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {} - -	void particles_set_draw_passes(RID p_particles, int p_count) override {} -	void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {} - -	void particles_request_process(RID p_particles) override {} -	AABB particles_get_current_aabb(RID p_particles) override { return AABB(); } -	AABB particles_get_aabb(RID p_particles) const override { return AABB(); } - -	void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {} - -	bool particles_get_emitting(RID p_particles) override { return false; } -	int particles_get_draw_passes(RID p_particles) const override { return 0; } -	RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); } - -	void particles_add_collision(RID p_particles, RID p_instance) override {} -	void particles_remove_collision(RID p_particles, RID p_instance) override {} - -	void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {} - -	void update_particles() override {} - -	/* PARTICLES COLLISION */ - -	RID particles_collision_allocate() override { return RID(); } -	void particles_collision_initialize(RID p_rid) override {} -	void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {} -	void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {} -	void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {} -	void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {} -	void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {} -	void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {} -	void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {} -	void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {} -	void particles_collision_height_field_update(RID p_particles_collision) override {} -	void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {} -	AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); } -	bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; } -	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); } - -	RID particles_collision_instance_create(RID p_collision) override { return RID(); } -	void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {} -	void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {} - -	bool particles_is_inactive(RID p_particles) const override { return false; } -  	/* FOG VOLUMES */  	RID fog_volume_allocate() override { return RID(); } diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h new file mode 100644 index 0000000000..f614b41c4c --- /dev/null +++ b/servers/rendering/dummy/storage/particles_storage.h @@ -0,0 +1,126 @@ +/*************************************************************************/ +/*  particles_storage.h                                                  */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#ifndef PARTICLES_STORAGE_DUMMY_H +#define PARTICLES_STORAGE_DUMMY_H + +#include "servers/rendering/storage/particles_storage.h" + +namespace RendererDummy { + +class ParticlesStorage : public RendererParticlesStorage { +public: +	/* PARTICLES */ + +	virtual RID particles_allocate() override { return RID(); } +	virtual void particles_initialize(RID p_rid) override {} +	virtual void particles_free(RID p_rid) override {} + +	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {} +	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {} +	virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {} +	virtual void particles_set_amount(RID p_particles, int p_amount) override {} +	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {} +	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {} +	virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {} +	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {} +	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {} +	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {} +	virtual void particles_set_speed_scale(RID p_particles, double p_scale) override {} +	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {} +	virtual void particles_set_process_material(RID p_particles, RID p_material) override {} +	virtual RID particles_get_process_material(RID p_particles) const override { return RID(); } +	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override {} +	virtual void particles_set_interpolate(RID p_particles, bool p_enable) override {} +	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override {} +	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {} +	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {} +	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override {} + +	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {} + +	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {} +	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {} + +	virtual void particles_restart(RID p_particles) override {} + +	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {} + +	virtual void particles_set_draw_passes(RID p_particles, int p_count) override {} +	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {} + +	virtual void particles_request_process(RID p_particles) override {} +	virtual AABB particles_get_current_aabb(RID p_particles) override { return AABB(); } +	virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); } + +	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {} + +	virtual bool particles_get_emitting(RID p_particles) override { return false; } +	virtual int particles_get_draw_passes(RID p_particles) const override { return 0; } +	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); } + +	virtual void particles_add_collision(RID p_particles, RID p_instance) override {} +	virtual void particles_remove_collision(RID p_particles, RID p_instance) override {} + +	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {} + +	virtual void update_particles() override {} + +	/* PARTICLES COLLISION */ + +	virtual RID particles_collision_allocate() override { return RID(); } +	virtual void particles_collision_initialize(RID p_rid) override {} +	virtual void particles_collision_free(RID p_rid) override {} + +	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {} +	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {} +	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {} +	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {} +	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {} +	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {} +	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {} +	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {} +	virtual void particles_collision_height_field_update(RID p_particles_collision) override {} +	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {} +	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); } +	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; } +	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); } + +	virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); } +	virtual void particles_collision_instance_free(RID p_rid) override {} +	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {} +	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {} + +	virtual bool particles_is_inactive(RID p_particles) const override { return false; } +}; + +} // namespace RendererDummy + +#endif // !PARTICLES_STORAGE_DUMMY_H diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 845201ba4b..f4d09ded64 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1338,7 +1338,7 @@ void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles,  	part->texture = p_texture;  	//take the chance and request processing for them, at least once until they become visible again -	RSG::storage->particles_request_process(p_particles); +	RSG::particles_storage->particles_request_process(p_particles);  }  void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) { diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 46ca3b0da8..59cc3b7a92 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -32,6 +32,7 @@  #define RENDERINGSERVERCANVASRENDER_H  #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"  #include "servers/rendering/renderer_storage.h"  class RendererCanvasRender { @@ -419,7 +420,7 @@ public:  					case Item::Command::TYPE_PARTICLES: {  						const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);  						if (particles_cmd->particles.is_valid()) { -							AABB aabb = RendererStorage::base_singleton->particles_get_aabb(particles_cmd->particles); +							AABB aabb = RendererRD::ParticlesStorage::get_singleton()->particles_get_aabb(particles_cmd->particles);  							r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);  						} diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index b93f50e3bc..9466148a31 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -37,6 +37,7 @@  #include "servers/rendering/storage/light_storage.h"  #include "servers/rendering/storage/material_storage.h"  #include "servers/rendering/storage/mesh_storage.h" +#include "servers/rendering/storage/particles_storage.h"  #include "servers/rendering/storage/texture_storage.h"  #include "servers/rendering_server.h" @@ -77,6 +78,7 @@ public:  	virtual RendererLightStorage *get_light_storage() = 0;  	virtual RendererMaterialStorage *get_material_storage() = 0;  	virtual RendererMeshStorage *get_mesh_storage() = 0; +	virtual RendererParticlesStorage *get_particles_storage() = 0;  	virtual RendererTextureStorage *get_texture_storage() = 0;  	virtual RendererStorage *get_storage() = 0;  	virtual RendererCanvasRender *get_canvas() = 0; 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 b283e920fd..925b5c180c 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -32,6 +32,7 @@  #include "core/config/project_settings.h"  #include "servers/rendering/renderer_rd/storage_rd/light_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"  #include "servers/rendering/rendering_device.h" @@ -2027,6 +2028,7 @@ void RenderForwardClustered::_base_uniforms_changed() {  void RenderForwardClustered::_update_render_base_uniform_set() {  	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version()) || base_uniform_set_updated) {  		base_uniform_set_updated = false; @@ -2043,18 +2045,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {  			Vector<RID> ids;  			ids.resize(12);  			RID *ids_ptr = ids.ptrw(); -			ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[0] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[1] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[2] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[3] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[4] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[5] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[6] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[7] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[8] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[9] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[10] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[11] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);  			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); @@ -2076,19 +2078,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {  			RID sampler;  			switch (decals_get_filter()) {  				case RS::DECAL_FILTER_NEAREST: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_NEAREST_MIPMAPS: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_LINEAR: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_LINEAR_MIPMAPS: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  			} @@ -2103,19 +2105,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {  			RID sampler;  			switch (light_projectors_get_filter()) {  				case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { -					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  			} @@ -2784,6 +2786,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw  void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {  	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); +	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();  	GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);  	if (ginstance->data->dirty_dependencies) { @@ -2840,10 +2843,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome  		} break;  #endif  		case RS::INSTANCE_PARTICLES: { -			int draw_passes = storage->particles_get_draw_passes(ginstance->data->base); +			int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);  			for (int j = 0; j < draw_passes; j++) { -				RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j); +				RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);  				if (!mesh.is_valid()) {  					continue;  				} @@ -2859,7 +2862,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome  				}  			} -			ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps); +			ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);  		} break; @@ -2896,10 +2899,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome  		//for particles, stride is the trail size  		ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT); -		if (!storage->particles_is_using_local_coords(ginstance->data->base)) { +		if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {  			store_transform = false;  		} -		ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); +		ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);  	} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {  		if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { 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 5b3c1d226e..ade2b976c8 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -32,6 +32,7 @@  #include "core/config/project_settings.h"  #include "servers/rendering/renderer_rd/storage_rd/light_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/rendering_device.h"  #include "servers/rendering/rendering_server_default.h" @@ -1139,6 +1140,7 @@ void RenderForwardMobile::_base_uniforms_changed() {  void RenderForwardMobile::_update_render_base_uniform_set() {  	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) {  		if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { @@ -1155,18 +1157,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {  			Vector<RID> ids;  			ids.resize(12);  			RID *ids_ptr = ids.ptrw(); -			ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			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); @@ -1188,19 +1190,19 @@ void RenderForwardMobile::_update_render_base_uniform_set() {  			RID sampler;  			switch (decals_get_filter()) {  				case RS::DECAL_FILTER_NEAREST: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_NEAREST_MIPMAPS: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_LINEAR: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_LINEAR_MIPMAPS: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  			} @@ -1215,19 +1217,19 @@ void RenderForwardMobile::_update_render_base_uniform_set() {  			RID sampler;  			switch (light_projectors_get_filter()) {  				case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { -					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);  				} break;  			} @@ -2452,6 +2454,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward  void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {  	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); +	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();  	GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);  	if (ginstance->data->dirty_dependencies) { @@ -2508,10 +2511,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry  		} break;  #endif  		case RS::INSTANCE_PARTICLES: { -			int draw_passes = storage->particles_get_draw_passes(ginstance->data->base); +			int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);  			for (int j = 0; j < draw_passes; j++) { -				RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j); +				RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);  				if (!mesh.is_valid()) {  					continue;  				} @@ -2527,7 +2530,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry  				}  			} -			ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps); +			ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);  		} break; @@ -2566,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry  		//for particles, stride is the trail size  		ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT); -		if (!storage->particles_is_using_local_coords(ginstance->data->base)) { +		if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {  			store_transform = false;  		} -		ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); +		ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);  	} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {  		if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 06eb4ca160..fce798e3df 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -36,6 +36,7 @@  #include "core/math/math_funcs.h"  #include "renderer_compositor_rd.h"  #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/rendering_server_default.h" @@ -401,6 +402,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend  	//create an empty push constant  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();  	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); +	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();  	RS::CanvasItemTextureFilter current_filter = default_filter;  	RS::CanvasItemTextureRepeat current_repeat = default_repeat; @@ -779,24 +781,24 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend  					}  				} else if (c->type == Item::Command::TYPE_PARTICLES) {  					const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c); -					ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D); -					storage->particles_request_process(pt->particles); +					ERR_BREAK(particles_storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D); +					particles_storage->particles_request_process(pt->particles); -					if (storage->particles_is_inactive(pt->particles)) { +					if (particles_storage->particles_is_inactive(pt->particles)) {  						break;  					}  					RenderingServerDefault::redraw_request(); // active particles means redraw request  					bool local_coords = true; -					int dpc = storage->particles_get_draw_passes(pt->particles); +					int dpc = particles_storage->particles_get_draw_passes(pt->particles);  					if (dpc == 0) {  						break; //nothing to draw  					}  					uint32_t divisor = 1; -					instance_count = storage->particles_get_amount(pt->particles, divisor); +					instance_count = particles_storage->particles_get_amount(pt->particles, divisor); -					RID uniform_set = storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); +					RID uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);  					RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);  					push_constant.flags |= divisor; @@ -805,10 +807,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend  					push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;  					push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; -					mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored +					mesh = particles_storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored  					texture = pt->texture; -					if (storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) { +					if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {  						//pass collision information  						Transform2D xform;  						if (local_coords) { @@ -827,9 +829,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend  							to_screen.position = -sdf_rect.position * to_screen.size;  						} -						storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture); +						particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);  					} else { -						storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID()); +						particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());  					}  				} @@ -931,6 +933,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend  RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	//re create canvas state  	Vector<RD::Uniform> uniforms; @@ -1006,18 +1009,18 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo  		Vector<RID> ids;  		ids.resize(12);  		RID *ids_ptr = ids.ptrw(); -		ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -		ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -		ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -		ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -		ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -		ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -		ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -		ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -		ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -		ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -		ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -		ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +		ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +		ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +		ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +		ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +		ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +		ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +		ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +		ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +		ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +		ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +		ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +		ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);  		RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 8, ids); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 9799850a23..fd56de845f 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -155,6 +155,7 @@ void RendererCompositorRD::finalize() {  	memdelete(scene);  	memdelete(canvas);  	memdelete(storage); +	memdelete(particles_storage);  	memdelete(light_storage);  	memdelete(mesh_storage);  	memdelete(material_storage); @@ -291,6 +292,7 @@ RendererCompositorRD::RendererCompositorRD() {  	material_storage = memnew(RendererRD::MaterialStorage);  	mesh_storage = memnew(RendererRD::MeshStorage);  	light_storage = memnew(RendererRD::LightStorage); +	particles_storage = memnew(RendererRD::ParticlesStorage);  	storage = memnew(RendererStorageRD);  	canvas = memnew(RendererCanvasRenderRD(storage)); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index decced77ea..768e9e0947 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -42,6 +42,7 @@  #include "servers/rendering/renderer_rd/storage_rd/light_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" @@ -52,6 +53,7 @@ protected:  	RendererRD::LightStorage *light_storage;  	RendererRD::MaterialStorage *material_storage;  	RendererRD::MeshStorage *mesh_storage; +	RendererRD::ParticlesStorage *particles_storage;  	RendererRD::TextureStorage *texture_storage;  	RendererStorageRD *storage = nullptr;  	RendererSceneRenderRD *scene = nullptr; @@ -99,6 +101,7 @@ public:  	RendererLightStorage *get_light_storage() { return light_storage; };  	RendererMaterialStorage *get_material_storage() { return material_storage; };  	RendererMeshStorage *get_mesh_storage() { return mesh_storage; }; +	RendererParticlesStorage *get_particles_storage() { return particles_storage; };  	RendererTextureStorage *get_texture_storage() { return texture_storage; };  	RendererStorage *get_storage() { return storage; }  	RendererCanvasRender *get_canvas() { return canvas; } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 1d80d0371f..d8b7d5384e 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -32,6 +32,7 @@  #include "core/config/project_settings.h"  #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/rendering_server_default.h" @@ -42,6 +43,8 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF  void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); +  	storage = p_gi->storage;  	gi = p_gi;  	num_cascades = p_env->sdfgi_cascades; @@ -388,7 +391,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V  			RD::Uniform u;  			u.binding = 2;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  		}  		{ @@ -670,7 +673,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  			u.binding = 6; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  		} @@ -950,7 +953,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,  						RD::Uniform u;  						u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  						u.binding = 1; -						u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +						u.append_id(RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  						uniforms.push_back(u);  					} @@ -1111,6 +1114,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() {  void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {  		Vector<RD::Uniform> uniforms; @@ -1177,7 +1181,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons  			RD::Uniform u;  			u.binding = 8;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  		}  		{ @@ -1251,6 +1255,8 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons  }  void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); +  	SDFGIShader::DebugProbesPushConstant push_constant;  	for (int i = 0; i < 4; i++) { @@ -1297,7 +1303,7 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr  			RD::Uniform u;  			u.binding = 3;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  		}  		{ @@ -2020,6 +2026,8 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32  // VoxelGIInstance  void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); +  	uint32_t data_version = storage->voxel_gi_get_data_version(probe);  	// (RE)CREATE IF NEEDED @@ -2112,7 +2120,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c  					RD::Uniform u;  					u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  					u.binding = 10; -					u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +					u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  					uniforms.push_back(u);  				} @@ -2266,7 +2274,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c  								RD::Uniform u;  								u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  								u.binding = 10; -								u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +								u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  								uniforms.push_back(u);  							}  							{ @@ -2335,7 +2343,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c  							RD::Uniform u;  							u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  							u.binding = 10; -							u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +							u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  							uniforms.push_back(u);  						} @@ -2723,6 +2731,8 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c  }  void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); +  	if (mipmaps.size() == 0) {  		return;  	} @@ -2771,7 +2781,7 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p  		RD::Uniform u;  		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  		u.binding = 3; -		u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +		u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  		uniforms.push_back(u);  	} @@ -2812,6 +2822,7 @@ RendererSceneGIRD::~RendererSceneGIRD() {  void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	storage = p_storage; @@ -2937,7 +2948,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  				u.binding = 1; -				u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +				u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  				uniforms.push_back(u);  			} @@ -3130,6 +3141,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra  void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	RD::get_singleton()->draw_command_begin_label("GI Render"); @@ -3255,14 +3267,14 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  			u.binding = 6; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  		}  		{  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  			u.binding = 7; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  		} diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 845139e0b5..bdbc228bde 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2944,6 +2944,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {  void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view"); @@ -2954,7 +2955,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p  	if (p_width != p_internal_width) {  		float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias; -		storage->sampler_rd_configure_custom(fsr_mipmap_bias); +		material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);  		update_uniform_sets();  	} @@ -3046,7 +3047,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p  	rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);  	if (is_clustered_enabled()) { -		rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture); +		rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);  	}  } @@ -4442,7 +4443,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  			u.binding = 7; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  			copy_uniforms.push_back(u);  		} @@ -4504,7 +4505,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  			u.binding = 13; -			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));  			uniforms.push_back(u);  			copy_uniforms.push_back(u);  		} @@ -5331,8 +5332,10 @@ void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform,  }  void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { -	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider)); -	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale(); +	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); + +	ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider)); +	Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();  	CameraMatrix cm;  	cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0); @@ -5342,7 +5345,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,  	Transform3D cam_xform;  	cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_axis(Vector3::AXIS_Y), -p_transform.basis.get_axis(Vector3::AXIS_Z).normalized()); -	RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider); +	RID fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);  	_render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);  } @@ -5748,18 +5751,18 @@ void fog() {  				Vector<RID> ids;  				ids.resize(12);  				RID *ids_ptr = ids.ptrw(); -				ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -				ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -				ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -				ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -				ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -				ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -				ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -				ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -				ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -				ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -				ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -				ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +				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); diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 231bd3c75e..db7a5250b6 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -927,18 +927,18 @@ void sky() {  			Vector<RID> ids;  			ids.resize(12);  			RID *ids_ptr = ids.ptrw(); -			ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);  			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index bb1f2a1d66..fa9f87abbe 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -37,1767 +37,11 @@  #include "renderer_compositor_rd.h"  #include "servers/rendering/renderer_rd/storage_rd/light_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/rendering_server_globals.h"  #include "servers/rendering/shader_language.h" -/* CANVAS TEXTURE */ - -void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { -	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { -		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { -			RD::SamplerState sampler_state; -			switch (i) { -				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.max_lod = 0; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.max_lod = 0; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -					sampler_state.lod_bias = p_mipmap_bias; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -					sampler_state.lod_bias = p_mipmap_bias; - -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -					sampler_state.lod_bias = p_mipmap_bias; -					sampler_state.use_anisotropy = true; -					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -					sampler_state.lod_bias = p_mipmap_bias; -					sampler_state.use_anisotropy = true; -					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - -				} break; -				default: { -				} -			} -			switch (j) { -				case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { -					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; -					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; -					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - -				} break; -				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { -					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; -					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; -					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { -					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; -					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; -					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; -				} break; -				default: { -				} -			} - -			if (custom_rd_samplers[i][j].is_valid()) { -				RD::get_singleton()->free(custom_rd_samplers[i][j]); -			} - -			custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); -		} -	} -} - -/* PARTICLES */ - -RID RendererStorageRD::particles_allocate() { -	return particles_owner.allocate_rid(); -} -void RendererStorageRD::particles_initialize(RID p_rid) { -	particles_owner.initialize_rid(p_rid, Particles()); -} - -void RendererStorageRD::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	if (particles->mode == p_mode) { -		return; -	} - -	_particles_free_data(particles); - -	particles->mode = p_mode; -} - -void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->emitting = p_emitting; -} - -bool RendererStorageRD::particles_get_emitting(RID p_particles) { -	ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, false); - -	return particles->emitting; -} - -void RendererStorageRD::_particles_free_data(Particles *particles) { -	if (particles->particle_buffer.is_valid()) { -		RD::get_singleton()->free(particles->particle_buffer); -		particles->particle_buffer = RID(); -		RD::get_singleton()->free(particles->particle_instance_buffer); -		particles->particle_instance_buffer = RID(); -	} - -	particles->userdata_count = 0; - -	if (particles->frame_params_buffer.is_valid()) { -		RD::get_singleton()->free(particles->frame_params_buffer); -		particles->frame_params_buffer = RID(); -	} -	particles->particles_transforms_buffer_uniform_set = RID(); - -	if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) { -		RD::get_singleton()->free(particles->trail_bind_pose_uniform_set); -	} -	particles->trail_bind_pose_uniform_set = RID(); - -	if (particles->trail_bind_pose_buffer.is_valid()) { -		RD::get_singleton()->free(particles->trail_bind_pose_buffer); -		particles->trail_bind_pose_buffer = RID(); -	} -	if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) { -		RD::get_singleton()->free(particles->collision_textures_uniform_set); -	} -	particles->collision_textures_uniform_set = RID(); - -	if (particles->particles_sort_buffer.is_valid()) { -		RD::get_singleton()->free(particles->particles_sort_buffer); -		particles->particles_sort_buffer = RID(); -		particles->particles_sort_uniform_set = RID(); -	} - -	if (particles->emission_buffer != nullptr) { -		particles->emission_buffer = nullptr; -		particles->emission_buffer_data.clear(); -		RD::get_singleton()->free(particles->emission_storage_buffer); -		particles->emission_storage_buffer = RID(); -	} - -	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { -		//will need to be re-created -		RD::get_singleton()->free(particles->particles_material_uniform_set); -	} -	particles->particles_material_uniform_set = RID(); -} - -void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	if (particles->amount == p_amount) { -		return; -	} - -	_particles_free_data(particles); - -	particles->amount = p_amount; - -	particles->prev_ticks = 0; -	particles->phase = 0; -	particles->prev_phase = 0; -	particles->clear = true; - -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); -} - -void RendererStorageRD::particles_set_lifetime(RID p_particles, double p_lifetime) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->lifetime = p_lifetime; -} - -void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->one_shot = p_one_shot; -} - -void RendererStorageRD::particles_set_pre_process_time(RID p_particles, double p_time) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->pre_process_time = p_time; -} -void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->explosiveness = p_ratio; -} -void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->randomness = p_ratio; -} - -void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->custom_aabb = p_aabb; -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::particles_set_speed_scale(RID p_particles, double p_scale) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->speed_scale = p_scale; -} -void RendererStorageRD::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->use_local_coords = p_enable; -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); -} - -void RendererStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->fixed_fps = p_fps; - -	_particles_free_data(particles); - -	particles->prev_ticks = 0; -	particles->phase = 0; -	particles->prev_phase = 0; -	particles->clear = true; - -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); -} - -void RendererStorageRD::particles_set_interpolate(RID p_particles, bool p_enable) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->interpolate = p_enable; -} - -void RendererStorageRD::particles_set_fractional_delta(RID p_particles, bool p_enable) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->fractional_delta = p_enable; -} - -void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, double p_length) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	ERR_FAIL_COND(p_length < 0.1); -	p_length = MIN(10.0, p_length); - -	particles->trails_enabled = p_enable; -	particles->trail_length = p_length; - -	_particles_free_data(particles); - -	particles->prev_ticks = 0; -	particles->phase = 0; -	particles->prev_phase = 0; -	particles->clear = true; - -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); -} - -void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) { -		_particles_free_data(particles); - -		particles->prev_ticks = 0; -		particles->phase = 0; -		particles->prev_phase = 0; -		particles->clear = true; -	} -	particles->trail_bind_poses = p_bind_poses; -	particles->trail_bind_poses_dirty = true; - -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); -} - -void RendererStorageRD::particles_set_collision_base_size(RID p_particles, real_t p_size) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->collision_base_size = p_size; -} - -void RendererStorageRD::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->transform_align = p_transform_align; -} - -void RendererStorageRD::particles_set_process_material(RID p_particles, RID p_material) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->process_material = p_material; -	particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed -} - -RID RendererStorageRD::particles_get_process_material(RID p_particles) const { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, RID()); - -	return particles->process_material; -} - -void RendererStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->draw_order = p_order; -} - -void RendererStorageRD::particles_set_draw_passes(RID p_particles, int p_passes) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->draw_passes.resize(p_passes); -} - -void RendererStorageRD::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); -	particles->draw_passes.write[p_pass] = p_mesh; -} - -void RendererStorageRD::particles_restart(RID p_particles) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->restart_request = true; -} - -void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles) { -	ERR_FAIL_COND(particles->emission_buffer != nullptr); - -	particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4); -	memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size()); -	particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw()); -	particles->emission_buffer->particle_max = particles->amount; - -	particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data); - -	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { -		//will need to be re-created -		RD::get_singleton()->free(particles->particles_material_uniform_set); -		particles->particles_material_uniform_set = RID(); -	} -} - -void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	ERR_FAIL_COND(p_particles == p_subemitter_particles); - -	particles->sub_emitter = p_subemitter_particles; - -	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { -		RD::get_singleton()->free(particles->particles_material_uniform_set); -		particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting -	} -} - -void RendererStorageRD::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	ERR_FAIL_COND(particles->amount == 0); - -	if (particles->emitting) { -		particles->clear = true; -		particles->emitting = false; -	} - -	if (particles->emission_buffer == nullptr) { -		_particles_allocate_emission_buffer(particles); -	} - -	if (particles->inactive) { -		//in case it was inactive, make active again -		particles->inactive = false; -		particles->inactive_time = 0; -	} - -	int32_t idx = particles->emission_buffer->particle_count; -	if (idx < particles->emission_buffer->particle_max) { -		store_transform(p_transform, particles->emission_buffer->data[idx].xform); - -		particles->emission_buffer->data[idx].velocity[0] = p_velocity.x; -		particles->emission_buffer->data[idx].velocity[1] = p_velocity.y; -		particles->emission_buffer->data[idx].velocity[2] = p_velocity.z; - -		particles->emission_buffer->data[idx].custom[0] = p_custom.r; -		particles->emission_buffer->data[idx].custom[1] = p_custom.g; -		particles->emission_buffer->data[idx].custom[2] = p_custom.b; -		particles->emission_buffer->data[idx].custom[3] = p_custom.a; - -		particles->emission_buffer->data[idx].color[0] = p_color.r; -		particles->emission_buffer->data[idx].color[1] = p_color.g; -		particles->emission_buffer->data[idx].color[2] = p_color.b; -		particles->emission_buffer->data[idx].color[3] = p_color.a; - -		particles->emission_buffer->data[idx].flags = p_emit_flags; -		particles->emission_buffer->particle_count++; -	} -} - -void RendererStorageRD::particles_request_process(RID p_particles) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	if (!particles->dirty) { -		particles->dirty = true; -		particles->update_list = particle_update_list; -		particle_update_list = particles; -	} -} - -AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) { -	if (RSG::threaded) { -		WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care."); -	} - -	const Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, AABB()); - -	int total_amount = particles->amount; -	if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -		total_amount *= particles->trail_bind_poses.size(); -	} - -	Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer); -	ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB()); - -	Transform3D inv = particles->emission_transform.affine_inverse(); - -	AABB aabb; -	if (buffer.size()) { -		bool first = true; - -		const uint8_t *data_ptr = (const uint8_t *)buffer.ptr(); -		uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count; - -		for (int i = 0; i < total_amount; i++) { -			const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i]; -			if (particle_data.active) { -				Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]); -				if (!particles->use_local_coords) { -					pos = inv.xform(pos); -				} -				if (first) { -					aabb.position = pos; -					first = false; -				} else { -					aabb.expand_to(pos); -				} -			} -		} -	} - -	float longest_axis_size = 0; -	for (int i = 0; i < particles->draw_passes.size(); i++) { -		if (particles->draw_passes[i].is_valid()) { -			AABB maabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID()); -			longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size); -		} -	} - -	aabb.grow_by(longest_axis_size); - -	return aabb; -} - -AABB RendererStorageRD::particles_get_aabb(RID p_particles) const { -	const Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, AABB()); - -	return particles->custom_aabb; -} - -void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	particles->emission_transform = p_transform; -} - -int RendererStorageRD::particles_get_draw_passes(RID p_particles) const { -	const Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, 0); - -	return particles->draw_passes.size(); -} - -RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { -	const Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, RID()); -	ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID()); - -	return particles->draw_passes[p_pass]; -} - -void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->collisions.insert(p_particles_collision_instance); -} - -void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->collisions.erase(p_particles_collision_instance); -} - -void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); -	particles->has_sdf_collision = p_enable; -	particles->sdf_collision_transform = p_xform; -	particles->sdf_collision_to_screen = p_to_screen; -	particles->sdf_collision_texture = p_texture; -} - -void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) { -	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); -	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - -	if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { -		Vector<RD::Uniform> uniforms; - -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.binding = 0; -			u.append_id(p_particles->frame_params_buffer); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.binding = 1; -			u.append_id(p_particles->particle_buffer); -			uniforms.push_back(u); -		} - -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.binding = 2; -			if (p_particles->emission_storage_buffer.is_valid()) { -				u.append_id(p_particles->emission_storage_buffer); -			} else { -				u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); -			} -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.binding = 3; -			Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter); -			if (sub_emitter) { -				if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer -					_particles_allocate_emission_buffer(sub_emitter); -				} -				u.append_id(sub_emitter->emission_storage_buffer); -			} else { -				u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); -			} -			uniforms.push_back(u); -		} - -		p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1); -	} - -	double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0); - -	//move back history (if there is any) -	for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) { -		p_particles->frame_history[i] = p_particles->frame_history[i - 1]; -	} -	//update current frame -	ParticlesFrameParams &frame_params = p_particles->frame_history[0]; - -	if (p_particles->clear) { -		p_particles->cycle_number = 0; -		p_particles->random_seed = Math::rand(); -	} else if (new_phase < p_particles->phase) { -		if (p_particles->one_shot) { -			p_particles->emitting = false; -		} -		p_particles->cycle_number++; -	} - -	frame_params.emitting = p_particles->emitting; -	frame_params.system_phase = new_phase; -	frame_params.prev_system_phase = p_particles->phase; - -	p_particles->phase = new_phase; - -	frame_params.time = RendererCompositorRD::singleton->get_total_time(); -	frame_params.delta = p_delta * p_particles->speed_scale; -	frame_params.random_seed = p_particles->random_seed; -	frame_params.explosiveness = p_particles->explosiveness; -	frame_params.randomness = p_particles->randomness; - -	if (p_particles->use_local_coords) { -		store_transform(Transform3D(), frame_params.emission_transform); -	} else { -		store_transform(p_particles->emission_transform, frame_params.emission_transform); -	} - -	frame_params.cycle = p_particles->cycle_number; -	frame_params.frame = p_particles->frame_counter++; -	frame_params.pad0 = 0; -	frame_params.pad1 = 0; -	frame_params.pad2 = 0; - -	{ //collision and attractors - -		frame_params.collider_count = 0; -		frame_params.attractor_count = 0; -		frame_params.particle_size = p_particles->collision_base_size; - -		RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; -		RID collision_heightmap_texture; - -		Transform3D to_particles; -		if (p_particles->use_local_coords) { -			to_particles = p_particles->emission_transform.affine_inverse(); -		} - -		if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) { -			//2D collision - -			Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand -			Transform2D revert = xform.affine_inverse(); -			frame_params.collider_count = 1; -			frame_params.colliders[0].transform[0] = xform.elements[0][0]; -			frame_params.colliders[0].transform[1] = xform.elements[0][1]; -			frame_params.colliders[0].transform[2] = 0; -			frame_params.colliders[0].transform[3] = xform.elements[2][0]; - -			frame_params.colliders[0].transform[4] = xform.elements[1][0]; -			frame_params.colliders[0].transform[5] = xform.elements[1][1]; -			frame_params.colliders[0].transform[6] = 0; -			frame_params.colliders[0].transform[7] = xform.elements[2][1]; - -			frame_params.colliders[0].transform[8] = revert.elements[0][0]; -			frame_params.colliders[0].transform[9] = revert.elements[0][1]; -			frame_params.colliders[0].transform[10] = 0; -			frame_params.colliders[0].transform[11] = revert.elements[2][0]; - -			frame_params.colliders[0].transform[12] = revert.elements[1][0]; -			frame_params.colliders[0].transform[13] = revert.elements[1][1]; -			frame_params.colliders[0].transform[14] = 0; -			frame_params.colliders[0].transform[15] = revert.elements[2][1]; - -			frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x; -			frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y; -			frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x; -			frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y; -			frame_params.colliders[0].texture_index = 0; -			frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF; - -			collision_heightmap_texture = p_particles->sdf_collision_texture; - -			//replace in all other history frames where used because parameters are no longer valid if screen moves -			for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) { -				if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) { -					p_particles->frame_history[i].colliders[0] = frame_params.colliders[0]; -				} -			} -		} - -		uint32_t collision_3d_textures_used = 0; -		for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { -			ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get()); -			if (!pci || !pci->active) { -				continue; -			} -			ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision); -			ERR_CONTINUE(!pc); - -			Transform3D to_collider = pci->transform; -			if (p_particles->use_local_coords) { -				to_collider = to_particles * to_collider; -			} -			Vector3 scale = to_collider.basis.get_scale(); -			to_collider.basis.orthonormalize(); - -			if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) { -				//attractor -				if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) { -					continue; -				} - -				ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count]; - -				store_transform(to_collider, attr.transform); -				attr.strength = pc->attractor_strength; -				attr.attenuation = pc->attractor_attenuation; -				attr.directionality = pc->attractor_directionality; - -				switch (pc->type) { -					case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: { -						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE; -						float radius = pc->radius; -						radius *= (scale.x + scale.y + scale.z) / 3.0; -						attr.extents[0] = radius; -						attr.extents[1] = radius; -						attr.extents[2] = radius; -					} break; -					case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: { -						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX; -						Vector3 extents = pc->extents * scale; -						attr.extents[0] = extents.x; -						attr.extents[1] = extents.y; -						attr.extents[2] = extents.z; -					} break; -					case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: { -						if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) { -							continue; -						} -						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD; -						Vector3 extents = pc->extents * scale; -						attr.extents[0] = extents.x; -						attr.extents[1] = extents.y; -						attr.extents[2] = extents.z; -						attr.texture_index = collision_3d_textures_used; - -						collision_3d_textures[collision_3d_textures_used] = pc->field_texture; -						collision_3d_textures_used++; -					} break; -					default: { -					} -				} - -				frame_params.attractor_count++; -			} else { -				//collider -				if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) { -					continue; -				} - -				ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count]; - -				store_transform(to_collider, col.transform); -				switch (pc->type) { -					case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: { -						col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE; -						float radius = pc->radius; -						radius *= (scale.x + scale.y + scale.z) / 3.0; -						col.extents[0] = radius; -						col.extents[1] = radius; -						col.extents[2] = radius; -					} break; -					case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: { -						col.type = ParticlesFrameParams::COLLISION_TYPE_BOX; -						Vector3 extents = pc->extents * scale; -						col.extents[0] = extents.x; -						col.extents[1] = extents.y; -						col.extents[2] = extents.z; -					} break; -					case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: { -						if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) { -							continue; -						} -						col.type = ParticlesFrameParams::COLLISION_TYPE_SDF; -						Vector3 extents = pc->extents * scale; -						col.extents[0] = extents.x; -						col.extents[1] = extents.y; -						col.extents[2] = extents.z; -						col.texture_index = collision_3d_textures_used; -						col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported - -						collision_3d_textures[collision_3d_textures_used] = pc->field_texture; -						collision_3d_textures_used++; -					} break; -					case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: { -						if (collision_heightmap_texture != RID()) { //already taken -							continue; -						} - -						col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD; -						Vector3 extents = pc->extents * scale; -						col.extents[0] = extents.x; -						col.extents[1] = extents.y; -						col.extents[2] = extents.z; -						collision_heightmap_texture = pc->heightfield_texture; -					} break; -					default: { -					} -				} - -				frame_params.collider_count++; -			} -		} - -		bool different = false; -		if (collision_3d_textures_used == p_particles->collision_3d_textures_used) { -			for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { -				if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) { -					different = true; -					break; -				} -			} -		} - -		if (collision_heightmap_texture != p_particles->collision_heightmap_texture) { -			different = true; -		} - -		bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set); - -		if (different || !uniform_set_valid) { -			if (uniform_set_valid) { -				RD::get_singleton()->free(p_particles->collision_textures_uniform_set); -			} - -			Vector<RD::Uniform> uniforms; - -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -				u.binding = 0; -				for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { -					RID rd_tex; -					if (i < collision_3d_textures_used) { -						RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); -						if (t && t->type == RendererRD::Texture::TYPE_3D) { -							rd_tex = t->rd_texture; -						} -					} - -					if (rd_tex == RID()) { -						rd_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); -					} -					u.append_id(rd_tex); -				} -				uniforms.push_back(u); -			} -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -				u.binding = 1; -				if (collision_heightmap_texture.is_valid()) { -					u.append_id(collision_heightmap_texture); -				} else { -					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); -				} -				uniforms.push_back(u); -			} -			p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2); -		} -	} - -	ParticlesShader::PushConstant push_constant; - -	int process_amount = p_particles->amount; - -	if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) { -		process_amount *= p_particles->trail_bind_poses.size(); -	} -	push_constant.clear = p_particles->clear; -	push_constant.total_particles = p_particles->amount; -	push_constant.lifetime = p_particles->lifetime; -	push_constant.trail_size = p_particles->trail_params.size(); -	push_constant.use_fractional_delta = p_particles->fractional_delta; -	push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit); -	push_constant.trail_pass = false; - -	p_particles->force_sub_emit = false; //reset - -	Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter); - -	if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) { -		//	print_line("updating subemitter buffer"); -		int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 }; -		RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero); -		push_constant.can_emit = true; - -		if (sub_emitter->emitting) { -			sub_emitter->emitting = false; -			sub_emitter->clear = true; //will need to clear if it was emitting, sorry -		} -		//make sure the sub emitter processes particles too -		sub_emitter->inactive = false; -		sub_emitter->inactive_time = 0; - -		sub_emitter->force_sub_emit = true; - -	} else { -		push_constant.can_emit = false; -	} - -	if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) { -		RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer); -		p_particles->emission_buffer->particle_count = 0; -	} - -	p_particles->clear = false; - -	if (p_particles->trail_params.size() > 1) { -		//fill the trail params -		for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) { -			uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size(); -			p_particles->trail_params[i] = p_particles->frame_history[src_idx]; -		} -	} else { -		p_particles->trail_params[0] = p_particles->frame_history[0]; -	} - -	RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - -	ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, RendererRD::SHADER_TYPE_PARTICLES)); -	if (!m) { -		m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES)); -	} - -	ERR_FAIL_COND(!m); - -	p_particles->has_collision_cache = m->shader_data->uses_collision; - -	//todo should maybe compute all particle systems together? -	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); -	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline); -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0); -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1); -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2); - -	if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) { -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3); -	} - -	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant)); - -	if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) { -		//trails requires two passes in order to catch particle starts -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1); - -		RD::get_singleton()->compute_list_add_barrier(compute_list); - -		push_constant.trail_pass = true; -		RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant)); -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1); -	} else { -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1); -	} - -	RD::get_singleton()->compute_list_end(); -} - -void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) { -	Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND(!particles); - -	if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { -		return; -	} - -	if (particles->particle_buffer.is_null()) { -		return; //particles have not processed yet -	} - -	bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH; - -	//copy to sort buffer -	if (do_sort && particles->particles_sort_buffer == RID()) { -		uint32_t size = particles->amount; -		if (size & 1) { -			size++; //make multiple of 16 -		} -		size *= sizeof(float) * 2; -		particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size); - -		{ -			Vector<RD::Uniform> uniforms; - -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -				u.binding = 0; -				u.append_id(particles->particles_sort_buffer); -				uniforms.push_back(u); -			} - -			particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1); -		} -	} - -	ParticlesShader::CopyPushConstant copy_push_constant; - -	if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -		int fixed_fps = 60.0; -		if (particles->fixed_fps > 0) { -			fixed_fps = particles->fixed_fps; -		} - -		copy_push_constant.trail_size = particles->trail_bind_poses.size(); -		copy_push_constant.trail_total = particles->frame_history.size(); -		copy_push_constant.frame_delta = 1.0 / fixed_fps; -	} else { -		copy_push_constant.trail_size = 1; -		copy_push_constant.trail_total = 1; -		copy_push_constant.frame_delta = 0.0; -	} - -	copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME); -	copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1); -	copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME; - -	copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0; -	copy_push_constant.total_particles = particles->amount; -	copy_push_constant.copy_mode_2d = false; - -	Vector3 axis = -p_axis; // cameras look to z negative - -	if (particles->use_local_coords) { -		axis = particles->emission_transform.basis.xform_inv(axis).normalized(); -	} - -	copy_push_constant.sort_direction[0] = axis.x; -	copy_push_constant.sort_direction[1] = axis.y; -	copy_push_constant.sort_direction[2] = axis.z; - -	copy_push_constant.align_up[0] = p_up_axis.x; -	copy_push_constant.align_up[1] = p_up_axis.y; -	copy_push_constant.align_up[2] = p_up_axis.z; - -	copy_push_constant.align_mode = particles->transform_align; - -	if (do_sort) { -		RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - -		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); -		RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); - -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1); - -		RD::get_singleton()->compute_list_end(); -		effects->sort_buffer(particles->particles_sort_uniform_set, particles->amount); -	} - -	copy_push_constant.total_particles *= copy_push_constant.total_particles; - -	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); -	uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES; -	copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX; -	copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0; -	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]); -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); -	if (do_sort) { -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); -	} -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); - -	RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); - -	RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1); - -	RD::get_singleton()->compute_list_end(); -} - -void RendererStorageRD::_particles_update_buffers(Particles *particles) { -	uint32_t userdata_count = 0; - -	const RendererRD::Material *material = RendererRD::MaterialStorage::get_singleton()->get_material(particles->process_material); -	if (material && material->shader && material->shader->data) { -		const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); -		userdata_count = shader_data->userdata_count; -	} - -	if (userdata_count != particles->userdata_count) { -		// Mismatch userdata, re-create buffers. -		_particles_free_data(particles); -	} - -	if (particles->amount > 0 && particles->particle_buffer.is_null()) { -		int total_amount = particles->amount; -		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -			total_amount *= particles->trail_bind_poses.size(); -		} - -		uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3; - -		particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount); - -		particles->userdata_count = userdata_count; - -		particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount); -		//needs to clear it - -		{ -			Vector<RD::Uniform> uniforms; - -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -				u.binding = 1; -				u.append_id(particles->particle_buffer); -				uniforms.push_back(u); -			} -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -				u.binding = 2; -				u.append_id(particles->particle_instance_buffer); -				uniforms.push_back(u); -			} - -			particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0); -		} -	} -} -void RendererStorageRD::update_particles() { -	while (particle_update_list) { -		//use transform feedback to process particles - -		Particles *particles = particle_update_list; - -		//take and remove -		particle_update_list = particles->update_list; -		particles->update_list = nullptr; -		particles->dirty = false; - -		_particles_update_buffers(particles); - -		if (particles->restart_request) { -			particles->prev_ticks = 0; -			particles->phase = 0; -			particles->prev_phase = 0; -			particles->clear = true; -			particles->restart_request = false; -		} - -		if (particles->inactive && !particles->emitting) { -			//go next -			continue; -		} - -		if (particles->emitting) { -			if (particles->inactive) { -				//restart system from scratch -				particles->prev_ticks = 0; -				particles->phase = 0; -				particles->prev_phase = 0; -				particles->clear = true; -			} -			particles->inactive = false; -			particles->inactive_time = 0; -		} else { -			particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time(); -			if (particles->inactive_time > particles->lifetime * 1.2) { -				particles->inactive = true; -				continue; -			} -		} - -#ifndef _MSC_VER -#warning Should use display refresh rate for all this -#endif - -		float screen_hz = 60; - -		int fixed_fps = 0; -		if (particles->fixed_fps > 0) { -			fixed_fps = particles->fixed_fps; -		} else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -			fixed_fps = screen_hz; -		} -		{ -			//update trails -			int history_size = 1; -			int trail_steps = 1; -			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -				history_size = MAX(1, int(particles->trail_length * fixed_fps)); -				trail_steps = particles->trail_bind_poses.size(); -			} - -			if (uint32_t(history_size) != particles->frame_history.size()) { -				particles->frame_history.resize(history_size); -				memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size); -			} - -			if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) { -				particles->trail_params.resize(trail_steps); -				if (particles->frame_params_buffer.is_valid()) { -					RD::get_singleton()->free(particles->frame_params_buffer); -				} -				particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps); -			} - -			if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) { -				particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size()); -				particles->trail_bind_poses_dirty = true; -			} - -			if (particles->trail_bind_pose_uniform_set.is_null()) { -				Vector<RD::Uniform> uniforms; -				{ -					RD::Uniform u; -					u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -					u.binding = 0; -					if (particles->trail_bind_pose_buffer.is_valid()) { -						u.append_id(particles->trail_bind_pose_buffer); -					} else { -						u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer()); -					} -					uniforms.push_back(u); -				} - -				particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2); -			} - -			if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) { -				if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) { -					particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16); -				} - -				for (int i = 0; i < particles->trail_bind_poses.size(); i++) { -					store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]); -				} - -				RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr()); -			} -		} - -		bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0; - -		if (particles->clear && particles->pre_process_time > 0.0) { -			double frame_time; -			if (fixed_fps > 0) { -				frame_time = 1.0 / fixed_fps; -			} else { -				frame_time = 1.0 / 30.0; -			} - -			double todo = particles->pre_process_time; - -			while (todo >= 0) { -				_particles_process(particles, frame_time); -				todo -= frame_time; -			} -		} - -		if (fixed_fps > 0) { -			double frame_time; -			double decr; -			if (zero_time_scale) { -				frame_time = 0.0; -				decr = 1.0 / fixed_fps; -			} else { -				frame_time = 1.0 / fixed_fps; -				decr = frame_time; -			} -			double delta = RendererCompositorRD::singleton->get_frame_delta_time(); -			if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 -				delta = 0.1; -			} else if (delta <= 0.0) { //unlikely but.. -				delta = 0.001; -			} -			double todo = particles->frame_remainder + delta; - -			while (todo >= frame_time) { -				_particles_process(particles, frame_time); -				todo -= decr; -			} - -			particles->frame_remainder = todo; - -		} else { -			if (zero_time_scale) { -				_particles_process(particles, 0.0); -			} else { -				_particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time()); -			} -		} - -		//copy particles to instance buffer - -		if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { -			//does not need view dependent operation, do copy here -			ParticlesShader::CopyPushConstant copy_push_constant; - -			int total_amount = particles->amount; -			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -				total_amount *= particles->trail_bind_poses.size(); -			} - -			// Affect 2D only. -			if (particles->use_local_coords) { -				// In local mode, particle positions are calculated locally (relative to the node position) -				// and they're also drawn locally. -				// It works as expected, so we just pass an identity transform. -				store_transform(Transform3D(), copy_push_constant.inv_emission_transform); -			} else { -				// In global mode, particle positions are calculated globally (relative to the canvas origin) -				// but they're drawn locally. -				// So, we need to pass the inverse of the emission transform to bring the -				// particles to local coordinates before drawing. -				Transform3D inv = particles->emission_transform.affine_inverse(); -				store_transform(inv, copy_push_constant.inv_emission_transform); -			} - -			copy_push_constant.total_particles = total_amount; -			copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0; -			copy_push_constant.align_mode = particles->transform_align; -			copy_push_constant.align_up[0] = 0; -			copy_push_constant.align_up[1] = 0; -			copy_push_constant.align_up[2] = 0; - -			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -				copy_push_constant.trail_size = particles->trail_bind_poses.size(); -				copy_push_constant.trail_total = particles->frame_history.size(); -				copy_push_constant.frame_delta = 1.0 / fixed_fps; -			} else { -				copy_push_constant.trail_size = 1; -				copy_push_constant.trail_total = 1; -				copy_push_constant.frame_delta = 0.0; -			} - -			copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME); -			copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1); -			copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME; - -			RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); -			copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0; -			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]); -			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); -			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); -			RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); - -			RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1); - -			RD::get_singleton()->compute_list_end(); -		} - -		particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -	} -} - -bool RendererStorageRD::particles_is_inactive(RID p_particles) const { -	ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); -	const Particles *particles = particles_owner.get_or_null(p_particles); -	ERR_FAIL_COND_V(!particles, false); -	return !particles->emitting && particles->inactive; -} - -/* SKY SHADER */ - -void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { -	//compile - -	code = p_code; -	valid = false; -	ubo_size = 0; -	uniforms.clear(); -	uses_collision = false; - -	if (code.is_empty()) { -		return; //just invalid, but no error -	} - -	ShaderCompiler::GeneratedCode gen_code; -	ShaderCompiler::IdentifierActions actions; -	actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE; -	actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE; - -	/* -	uses_time = false; - -	actions.render_mode_flags["use_half_res_pass"] = &uses_half_res; -	actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res; - -	actions.usage_flag_pointers["TIME"] = &uses_time; -*/ - -	actions.usage_flag_pointers["COLLIDED"] = &uses_collision; - -	userdata_count = 0; -	for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { -		userdatas_used[i] = false; -		actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i]; -	} - -	actions.uniforms = &uniforms; - -	Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code); -	ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); - -	if (version.is_null()) { -		version = base_singleton->particles_shader.shader.version_create(); -	} - -	for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { -		if (userdatas_used[i]) { -			userdata_count++; -		} -	} - -	base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); -	ERR_FAIL_COND(!base_singleton->particles_shader.shader.version_is_valid(version)); - -	ubo_size = gen_code.uniform_total_size; -	ubo_offsets = gen_code.uniform_offsets; -	texture_uniforms = gen_code.texture_uniforms; - -	//update pipelines - -	pipeline = RD::get_singleton()->compute_pipeline_create(base_singleton->particles_shader.shader.version_get_shader(version, 0)); - -	valid = true; -} - -void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { -	if (!p_texture.is_valid()) { -		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { -			default_texture_params[p_name].erase(p_index); - -			if (default_texture_params[p_name].is_empty()) { -				default_texture_params.erase(p_name); -			} -		} -	} else { -		if (!default_texture_params.has(p_name)) { -			default_texture_params[p_name] = Map<int, RID>(); -		} -		default_texture_params[p_name][p_index] = p_texture; -	} -} - -void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { -	Map<int, StringName> order; - -	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { -		if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { -			continue; -		} - -		if (E.value.texture_order >= 0) { -			order[E.value.texture_order + 100000] = E.key; -		} else { -			order[E.value.order] = E.key; -		} -	} - -	for (const KeyValue<int, StringName> &E : order) { -		PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); -		pi.name = E.value; -		p_param_list->push_back(pi); -	} -} - -void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<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 RendererStorageRD::ParticlesShaderData::is_param_texture(const StringName &p_param) const { -	if (!uniforms.has(p_param)) { -		return false; -	} - -	return uniforms[p_param].texture_order >= 0; -} - -bool RendererStorageRD::ParticlesShaderData::is_animated() const { -	return false; -} - -bool RendererStorageRD::ParticlesShaderData::casts_shadows() const { -	return false; -} - -Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const { -	if (uniforms.has(p_parameter)) { -		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; -		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; -		return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); -	} -	return Variant(); -} - -RS::ShaderNativeSourceCode RendererStorageRD::ParticlesShaderData::get_native_source_code() const { -	return base_singleton->particles_shader.shader.version_get_native_source_code(version); -} - -RendererStorageRD::ParticlesShaderData::ParticlesShaderData() { -	valid = false; -} - -RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() { -	//pipeline variants will clear themselves if shader is gone -	if (version.is_valid()) { -		base_singleton->particles_shader.shader.version_free(version); -	} -} - -RendererRD::ShaderData *RendererStorageRD::_create_particles_shader_func() { -	ParticlesShaderData *shader_data = memnew(ParticlesShaderData); -	return shader_data; -} - -bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { -	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); -} - -RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { -	free_parameters_uniform_set(uniform_set); -} - -RendererRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { -	ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); -	material_data->shader_data = p_shader; -	//update will happen later anyway so do nothing. -	return material_data; -} -//////// - -/* PARTICLES COLLISION API */ - -RID RendererStorageRD::particles_collision_allocate() { -	return particles_collision_owner.allocate_rid(); -} -void RendererStorageRD::particles_collision_initialize(RID p_rid) { -	particles_collision_owner.initialize_rid(p_rid, ParticlesCollision()); -} - -RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND_V(!particles_collision, RID()); -	ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID()); - -	if (particles_collision->heightfield_texture == RID()) { -		//create -		int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 }; -		Size2i size; -		if (particles_collision->extents.x > particles_collision->extents.z) { -			size.x = resolutions[particles_collision->heightfield_resolution]; -			size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x); -		} else { -			size.y = resolutions[particles_collision->heightfield_resolution]; -			size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y); -		} - -		RD::TextureFormat tf; -		tf.format = RD::DATA_FORMAT_D32_SFLOAT; -		tf.width = size.x; -		tf.height = size.y; -		tf.texture_type = RD::TEXTURE_TYPE_2D; -		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - -		particles_collision->heightfield_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - -		Vector<RID> fb_tex; -		fb_tex.push_back(particles_collision->heightfield_texture); -		particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex); -		particles_collision->heightfield_fb_size = size; -	} - -	return particles_collision->heightfield_fb; -} - -void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	if (p_type == particles_collision->type) { -		return; -	} - -	if (particles_collision->heightfield_texture.is_valid()) { -		RD::get_singleton()->free(particles_collision->heightfield_texture); -		particles_collision->heightfield_texture = RID(); -	} -	particles_collision->type = p_type; -	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); -	particles_collision->cull_mask = p_cull_mask; -} - -void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	particles_collision->radius = p_radius; -	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	particles_collision->extents = p_extents; -	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	particles_collision->attractor_strength = p_strength; -} - -void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	particles_collision->attractor_directionality = p_directionality; -} - -void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	particles_collision->attractor_attenuation = p_curve; -} - -void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); - -	particles_collision->field_texture = p_texture; -} - -void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); -	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND(!particles_collision); -	ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX); - -	if (particles_collision->heightfield_resolution == p_resolution) { -		return; -	} - -	particles_collision->heightfield_resolution = p_resolution; - -	if (particles_collision->heightfield_texture.is_valid()) { -		RD::get_singleton()->free(particles_collision->heightfield_texture); -		particles_collision->heightfield_texture = RID(); -	} -} - -AABB RendererStorageRD::particles_collision_get_aabb(RID p_particles_collision) const { -	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND_V(!particles_collision, AABB()); - -	switch (particles_collision->type) { -		case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: -		case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: { -			AABB aabb; -			aabb.position = -Vector3(1, 1, 1) * particles_collision->radius; -			aabb.size = Vector3(2, 2, 2) * particles_collision->radius; -			return aabb; -		} -		default: { -			AABB aabb; -			aabb.position = -particles_collision->extents; -			aabb.size = particles_collision->extents * 2; -			return aabb; -		} -	} - -	return AABB(); -} - -Vector3 RendererStorageRD::particles_collision_get_extents(RID p_particles_collision) const { -	const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND_V(!particles_collision, Vector3()); -	return particles_collision->extents; -} - -bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_collision) const { -	const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); -	ERR_FAIL_COND_V(!particles_collision, false); -	return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE; -} - -RID RendererStorageRD::particles_collision_instance_create(RID p_collision) { -	ParticlesCollisionInstance pci; -	pci.collision = p_collision; -	return particles_collision_instance_owner.make_rid(pci); -} -void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) { -	ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance); -	ERR_FAIL_COND(!pci); -	pci->transform = p_transform; -} -void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { -	ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance); -	ERR_FAIL_COND(!pci); -	pci->active = p_active; -} -  /* FOG VOLUMES */  RID RendererStorageRD::fog_volume_allocate() { @@ -2257,6 +501,8 @@ RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) {  	return voxel_gi->sdf_texture;  } +/* misc */ +  void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {  	if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {  		RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base); @@ -2282,11 +528,11 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_  	} else if (RendererRD::LightStorage::get_singleton()->owns_light(p_base)) {  		RendererRD::Light *l = RendererRD::LightStorage::get_singleton()->get_light(p_base);  		p_instance->update_dependency(&l->dependency); -	} else if (particles_owner.owns(p_base)) { -		Particles *p = particles_owner.get_or_null(p_base); +	} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_base)) { +		RendererRD::Particles *p = RendererRD::ParticlesStorage::get_singleton()->get_particles(p_base);  		p_instance->update_dependency(&p->dependency); -	} else if (particles_collision_owner.owns(p_base)) { -		ParticlesCollision *pc = particles_collision_owner.get_or_null(p_base); +	} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) { +		RendererRD::ParticlesCollision *pc = RendererRD::ParticlesStorage::get_singleton()->get_particles_collision(p_base);  		p_instance->update_dependency(&pc->dependency);  	} else if (fog_volume_owner.owns(p_base)) {  		FogVolume *fv = fog_volume_owner.get_or_null(p_base); @@ -2319,10 +565,10 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {  	if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {  		return RS::INSTANCE_LIGHTMAP;  	} -	if (particles_owner.owns(p_rid)) { +	if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {  		return RS::INSTANCE_PARTICLES;  	} -	if (particles_collision_owner.owns(p_rid)) { +	if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {  		return RS::INSTANCE_PARTICLES_COLLISION;  	}  	if (fog_volume_owner.owns(p_rid)) { @@ -2393,26 +639,16 @@ bool RendererStorageRD::free(RID p_rid) {  		RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid);  	} else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {  		RendererRD::LightStorage::get_singleton()->light_free(p_rid); -	} else if (particles_owner.owns(p_rid)) { -		update_particles(); -		Particles *particles = particles_owner.get_or_null(p_rid); -		particles->dependency.deleted_notify(p_rid); -		_particles_free_data(particles); -		particles_owner.free(p_rid); -	} else if (particles_collision_owner.owns(p_rid)) { -		ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid); - -		if (particles_collision->heightfield_texture.is_valid()) { -			RD::get_singleton()->free(particles_collision->heightfield_texture); -		} -		particles_collision->dependency.deleted_notify(p_rid); -		particles_collision_owner.free(p_rid); +	} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) { +		RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid); +	} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) { +		RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);  	} else if (visibility_notifier_owner.owns(p_rid)) {  		VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid);  		vn->dependency.deleted_notify(p_rid);  		visibility_notifier_owner.free(p_rid); -	} else if (particles_collision_instance_owner.owns(p_rid)) { -		particles_collision_instance_owner.free(p_rid); +	} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) { +		RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);  	} else if (fog_volume_owner.owns(p_rid)) {  		FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);  		fog_volume->dependency.deleted_notify(p_rid); @@ -2495,272 +731,9 @@ RendererStorageRD *RendererStorageRD::base_singleton = nullptr;  RendererStorageRD::RendererStorageRD() {  	base_singleton = this; - -	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - -	//default samplers -	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { -		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { -			RD::SamplerState sampler_state; -			switch (i) { -				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.max_lod = 0; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.max_lod = 0; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} - -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; -					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -					sampler_state.use_anisotropy = true; -					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); -				} break; -				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { -					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; -					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; -					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; -					} else { -						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; -					} -					sampler_state.use_anisotropy = true; -					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - -				} break; -				default: { -				} -			} -			switch (j) { -				case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { -					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; -					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; -					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - -				} break; -				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { -					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; -					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; -					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; -				} break; -				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { -					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; -					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; -					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; -				} break; -				default: { -				} -			} - -			default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); -		} -	} - -	//custom sampler -	sampler_rd_configure_custom(0.0f); - -	/* Particles */ - -	{ -		// Initialize particles -		Vector<String> particles_modes; -		particles_modes.push_back(""); -		particles_shader.shader.initialize(particles_modes, String()); -	} -	RendererRD::MaterialStorage::get_singleton()->shader_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); -	RendererRD::MaterialStorage::get_singleton()->material_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); - -	{ -		ShaderCompiler::DefaultIdentifierActions actions; - -		actions.renames["COLOR"] = "PARTICLE.color"; -		actions.renames["VELOCITY"] = "PARTICLE.velocity"; -		//actions.renames["MASS"] = "mass"; ? -		actions.renames["ACTIVE"] = "particle_active"; -		actions.renames["RESTART"] = "restart"; -		actions.renames["CUSTOM"] = "PARTICLE.custom"; -		for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { -			String udname = "USERDATA" + itos(i + 1); -			actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1); -			actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n"; -		} -		actions.renames["TRANSFORM"] = "PARTICLE.xform"; -		actions.renames["TIME"] = "frame_history.data[0].time"; -		actions.renames["PI"] = _MKSTR(Math_PI); -		actions.renames["TAU"] = _MKSTR(Math_TAU); -		actions.renames["E"] = _MKSTR(Math_E); -		actions.renames["LIFETIME"] = "params.lifetime"; -		actions.renames["DELTA"] = "local_delta"; -		actions.renames["NUMBER"] = "particle_number"; -		actions.renames["INDEX"] = "index"; -		//actions.renames["GRAVITY"] = "current_gravity"; -		actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform"; -		actions.renames["RANDOM_SEED"] = "FRAME.random_seed"; -		actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION"; -		actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE"; -		actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY"; -		actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR"; -		actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM"; -		actions.renames["RESTART_POSITION"] = "restart_position"; -		actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale"; -		actions.renames["RESTART_VELOCITY"] = "restart_velocity"; -		actions.renames["RESTART_COLOR"] = "restart_color"; -		actions.renames["RESTART_CUSTOM"] = "restart_custom"; -		actions.renames["emit_subparticle"] = "emit_subparticle"; -		actions.renames["COLLIDED"] = "collided"; -		actions.renames["COLLISION_NORMAL"] = "collision_normal"; -		actions.renames["COLLISION_DEPTH"] = "collision_depth"; -		actions.renames["ATTRACTOR_FORCE"] = "attractor_force"; - -		actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; -		actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; -		actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; -		actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n"; - -		actions.sampler_array_name = "material_samplers"; -		actions.base_texture_binding_index = 1; -		actions.texture_layout_set = 3; -		actions.base_uniform_string = "material."; -		actions.base_varying_index = 10; - -		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; -		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; -		actions.global_buffer_array_variable = "global_variables.data"; - -		particles_shader.compiler.initialize(actions); -	} - -	{ -		// default material and shader for particles shader -		particles_shader.default_shader = material_storage->shader_allocate(); -		material_storage->shader_initialize(particles_shader.default_shader); -		material_storage->shader_set_code(particles_shader.default_shader, R"( -// Default particles shader. - -shader_type particles; - -void process() { -	COLOR = vec4(1.0); -} -)"); -		particles_shader.default_material = material_storage->material_allocate(); -		material_storage->material_initialize(particles_shader.default_material); -		material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - -		ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES)); -		particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); - -		Vector<RD::Uniform> uniforms; - -		{ -			Vector<RID> ids; -			ids.resize(12); -			RID *ids_ptr = ids.ptrw(); -			ids_ptr[0] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[1] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[2] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[3] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[4] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[5] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); -			ids_ptr[6] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[7] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[8] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[9] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[10] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); -			ids_ptr[11] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - -			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); -			uniforms.push_back(u); -		} - -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.binding = 2; -			u.append_id(material_storage->global_variables_get_storage_buffer()); -			uniforms.push_back(u); -		} - -		particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0); -	} - -	{ -		Vector<String> copy_modes; -		for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { -			if (i == 0) { -				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n"); -				copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n"); -				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n"); -			} else { -				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n"); -				copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n"); -				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n"); -			} -		} - -		particles_shader.copy_shader.initialize(copy_modes); - -		particles_shader.copy_shader_version = particles_shader.copy_shader.version_create(); - -		for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { -			for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) { -				particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j)); -			} -		} -	}  }  RendererStorageRD::~RendererStorageRD() { -	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - -	//def samplers -	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { -		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { -			RD::get_singleton()->free(default_rd_samplers[i][j]); -		} -	} - -	//custom samplers -	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { -		for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { -			if (custom_rd_samplers[i][j].is_valid()) { -				RD::get_singleton()->free(custom_rd_samplers[i][j]); -			} -		} -	} - -	particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); - -	material_storage->material_free(particles_shader.default_material); -	material_storage->shader_free(particles_shader.default_shader); -  	if (effects) {  		memdelete(effects);  		effects = nullptr; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 041daea520..37c76f9c62 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -36,8 +36,6 @@  #include "core/templates/rid_owner.h"  #include "servers/rendering/renderer_compositor.h"  #include "servers/rendering/renderer_rd/effects_rd.h" -#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"  #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"  #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"  #include "servers/rendering/renderer_scene_render.h" @@ -125,363 +123,6 @@ public:  	}  private: -	/* TEXTURE API */ - -	RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; -	RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - -	/* PARTICLES */ - -	struct ParticleData { -		float xform[16]; -		float velocity[3]; -		uint32_t active; -		float color[4]; -		float custom[3]; -		float lifetime; -	}; - -	struct ParticlesFrameParams { -		enum { -			MAX_ATTRACTORS = 32, -			MAX_COLLIDERS = 32, -			MAX_3D_TEXTURES = 7 -		}; - -		enum AttractorType { -			ATTRACTOR_TYPE_SPHERE, -			ATTRACTOR_TYPE_BOX, -			ATTRACTOR_TYPE_VECTOR_FIELD, -		}; - -		struct Attractor { -			float transform[16]; -			float extents[3]; //exents or radius -			uint32_t type; - -			uint32_t texture_index; //texture index for vector field -			float strength; -			float attenuation; -			float directionality; -		}; - -		enum CollisionType { -			COLLISION_TYPE_SPHERE, -			COLLISION_TYPE_BOX, -			COLLISION_TYPE_SDF, -			COLLISION_TYPE_HEIGHT_FIELD, -			COLLISION_TYPE_2D_SDF, - -		}; - -		struct Collider { -			float transform[16]; -			float extents[3]; //exents or radius -			uint32_t type; - -			uint32_t texture_index; //texture index for vector field -			real_t scale; -			uint32_t pad[2]; -		}; - -		uint32_t emitting; -		float system_phase; -		float prev_system_phase; -		uint32_t cycle; - -		real_t explosiveness; -		real_t randomness; -		float time; -		float delta; - -		uint32_t frame; -		uint32_t pad0; -		uint32_t pad1; -		uint32_t pad2; - -		uint32_t random_seed; -		uint32_t attractor_count; -		uint32_t collider_count; -		float particle_size; - -		float emission_transform[16]; - -		Attractor attractors[MAX_ATTRACTORS]; -		Collider colliders[MAX_COLLIDERS]; -	}; - -	struct ParticleEmissionBufferData { -	}; - -	struct ParticleEmissionBuffer { -		struct Data { -			float xform[16]; -			float velocity[3]; -			uint32_t flags; -			float color[4]; -			float custom[4]; -		}; - -		int32_t particle_count; -		int32_t particle_max; -		uint32_t pad1; -		uint32_t pad2; -		Data data[1]; //its 2020 and empty arrays are still non standard in C++ -	}; - -	struct Particles { -		RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; -		bool inactive = true; -		double inactive_time = 0.0; -		bool emitting = false; -		bool one_shot = false; -		int amount = 0; -		double lifetime = 1.0; -		double pre_process_time = 0.0; -		real_t explosiveness = 0.0; -		real_t randomness = 0.0; -		bool restart_request = false; -		AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); -		bool use_local_coords = true; -		bool has_collision_cache = false; - -		bool has_sdf_collision = false; -		Transform2D sdf_collision_transform; -		Rect2 sdf_collision_to_screen; -		RID sdf_collision_texture; - -		RID process_material; -		uint32_t frame_counter = 0; -		RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; - -		RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; - -		Vector<RID> draw_passes; -		Vector<Transform3D> trail_bind_poses; -		bool trail_bind_poses_dirty = false; -		RID trail_bind_pose_buffer; -		RID trail_bind_pose_uniform_set; - -		RID particle_buffer; -		RID particle_instance_buffer; -		RID frame_params_buffer; - -		uint32_t userdata_count = 0; - -		RID particles_material_uniform_set; -		RID particles_copy_uniform_set; -		RID particles_transforms_buffer_uniform_set; -		RID collision_textures_uniform_set; - -		RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; -		uint32_t collision_3d_textures_used = 0; -		RID collision_heightmap_texture; - -		RID particles_sort_buffer; -		RID particles_sort_uniform_set; - -		bool dirty = false; -		Particles *update_list = nullptr; - -		RID sub_emitter; - -		double phase = 0.0; -		double prev_phase = 0.0; -		uint64_t prev_ticks = 0; -		uint32_t random_seed = 0; - -		uint32_t cycle_number = 0; - -		double speed_scale = 1.0; - -		int fixed_fps = 30; -		bool interpolate = true; -		bool fractional_delta = false; -		double frame_remainder = 0; -		real_t collision_base_size = 0.01; - -		bool clear = true; - -		bool force_sub_emit = false; - -		Transform3D emission_transform; - -		Vector<uint8_t> emission_buffer_data; - -		ParticleEmissionBuffer *emission_buffer = nullptr; -		RID emission_storage_buffer; - -		Set<RID> collisions; - -		Dependency dependency; - -		double trail_length = 1.0; -		bool trails_enabled = false; -		LocalVector<ParticlesFrameParams> frame_history; -		LocalVector<ParticlesFrameParams> trail_params; - -		Particles() { -		} -	}; - -	void _particles_process(Particles *p_particles, double p_delta); -	void _particles_allocate_emission_buffer(Particles *particles); -	void _particles_free_data(Particles *particles); -	void _particles_update_buffers(Particles *particles); - -	struct ParticlesShader { -		struct PushConstant { -			float lifetime; -			uint32_t clear; -			uint32_t total_particles; -			uint32_t trail_size; - -			uint32_t use_fractional_delta; -			uint32_t sub_emitter_mode; -			uint32_t can_emit; -			uint32_t trail_pass; -		}; - -		ParticlesShaderRD shader; -		ShaderCompiler compiler; - -		RID default_shader; -		RID default_material; -		RID default_shader_rd; - -		RID base_uniform_set; - -		struct CopyPushConstant { -			float sort_direction[3]; -			uint32_t total_particles; - -			uint32_t trail_size; -			uint32_t trail_total; -			float frame_delta; -			float frame_remainder; - -			float align_up[3]; -			uint32_t align_mode; - -			uint32_t order_by_lifetime; -			uint32_t lifetime_split; -			uint32_t lifetime_reverse; -			uint32_t copy_mode_2d; - -			float inv_emission_transform[16]; -		}; - -		enum { -			MAX_USERDATAS = 6 -		}; -		enum { -			COPY_MODE_FILL_INSTANCES, -			COPY_MODE_FILL_SORT_BUFFER, -			COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER, -			COPY_MODE_MAX, -		}; - -		ParticlesCopyShaderRD copy_shader; -		RID copy_shader_version; -		RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)]; - -		LocalVector<float> pose_update_buffer; - -	} particles_shader; - -	Particles *particle_update_list = nullptr; - -	struct ParticlesShaderData : public RendererRD::ShaderData { -		bool valid; -		RID version; -		bool uses_collision = false; - -		//PipelineCacheRD pipelines[SKY_VERSION_MAX]; -		Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; -		Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; - -		Vector<uint32_t> ubo_offsets; -		uint32_t ubo_size; - -		String path; -		String code; -		Map<StringName, Map<int, RID>> default_texture_params; - -		RID pipeline; - -		bool uses_time = false; - -		bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {}; -		uint32_t userdata_count = 0; - -		virtual void set_code(const String &p_Code); -		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); -		virtual void get_param_list(List<PropertyInfo> *p_param_list) const; -		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; -		virtual bool is_param_texture(const StringName &p_param) const; -		virtual bool is_animated() const; -		virtual bool casts_shadows() const; -		virtual Variant get_default_parameter(const StringName &p_parameter) const; -		virtual RS::ShaderNativeSourceCode get_native_source_code() const; - -		ParticlesShaderData(); -		virtual ~ParticlesShaderData(); -	}; - -	RendererRD::ShaderData *_create_particles_shader_func(); -	static RendererRD::ShaderData *_create_particles_shader_funcs() { -		return base_singleton->_create_particles_shader_func(); -	} - -	struct ParticlesMaterialData : public RendererRD::MaterialData { -		ParticlesShaderData *shader_data = nullptr; -		RID uniform_set; - -		virtual void set_render_priority(int p_priority) {} -		virtual void set_next_pass(RID p_pass) {} -		virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); -		virtual ~ParticlesMaterialData(); -	}; - -	RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); -	static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) { -		return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); -	} - -	void update_particles(); - -	mutable RID_Owner<Particles, true> particles_owner; - -	/* Particles Collision */ - -	struct ParticlesCollision { -		RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; -		uint32_t cull_mask = 0xFFFFFFFF; -		float radius = 1.0; -		Vector3 extents = Vector3(1, 1, 1); -		float attractor_strength = 1.0; -		float attractor_attenuation = 1.0; -		float attractor_directionality = 0.0; -		RID field_texture; -		RID heightfield_texture; -		RID heightfield_fb; -		Size2i heightfield_fb_size; - -		RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; - -		Dependency dependency; -	}; - -	mutable RID_Owner<ParticlesCollision, true> particles_collision_owner; - -	struct ParticlesCollisionInstance { -		RID collision; -		Transform3D transform; -		bool active = false; -	}; - -	mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; -  	/* FOG VOLUMES */  	struct FogVolume { @@ -549,17 +190,6 @@ private:  public:  	//internal usage -	_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { -		return default_rd_samplers[p_filter][p_repeat]; -	} -	_FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { -		return custom_rd_samplers[p_filter][p_repeat]; -	} - -	void sampler_rd_configure_custom(float mipmap_bias); - -	void sampler_rd_set_default(float p_mipmap_bias); -  	void base_update_dependency(RID p_base, DependencyTracker *p_instance);  	/* VOXEL GI API */ @@ -610,137 +240,6 @@ public:  	RID voxel_gi_get_sdf_texture(RID p_voxel_gi); -	/* PARTICLES */ - -	RID particles_allocate(); -	void particles_initialize(RID p_particles_collision); - -	void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode); -	void particles_set_emitting(RID p_particles, bool p_emitting); -	void particles_set_amount(RID p_particles, int p_amount); -	void particles_set_lifetime(RID p_particles, double p_lifetime); -	void particles_set_one_shot(RID p_particles, bool p_one_shot); -	void particles_set_pre_process_time(RID p_particles, double p_time); -	void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio); -	void particles_set_randomness_ratio(RID p_particles, real_t p_ratio); -	void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb); -	void particles_set_speed_scale(RID p_particles, double p_scale); -	void particles_set_use_local_coordinates(RID p_particles, bool p_enable); -	void particles_set_process_material(RID p_particles, RID p_material); -	RID particles_get_process_material(RID p_particles) const; - -	void particles_set_fixed_fps(RID p_particles, int p_fps); -	void particles_set_interpolate(RID p_particles, bool p_enable); -	void particles_set_fractional_delta(RID p_particles, bool p_enable); -	void particles_set_collision_base_size(RID p_particles, real_t p_size); -	void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align); - -	void particles_set_trails(RID p_particles, bool p_enable, double p_length); -	void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses); - -	void particles_restart(RID p_particles); -	void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); - -	void particles_set_subemitter(RID p_particles, RID p_subemitter_particles); - -	void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order); - -	void particles_set_draw_passes(RID p_particles, int p_count); -	void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh); - -	void particles_request_process(RID p_particles); -	AABB particles_get_current_aabb(RID p_particles); -	AABB particles_get_aabb(RID p_particles) const; - -	void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform); - -	bool particles_get_emitting(RID p_particles); -	int particles_get_draw_passes(RID p_particles) const; -	RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const; - -	void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis); - -	virtual bool particles_is_inactive(RID p_particles) const; - -	_FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) { -		Particles *particles = particles_owner.get_or_null(p_particles); -		ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D); -		return particles->mode; -	} - -	_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) { -		Particles *particles = particles_owner.get_or_null(p_particles); -		ERR_FAIL_COND_V(!particles, 0); - -		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { -			r_trail_divisor = particles->trail_bind_poses.size(); -		} else { -			r_trail_divisor = 1; -		} - -		return particles->amount * r_trail_divisor; -	} - -	_FORCE_INLINE_ bool particles_has_collision(RID p_particles) { -		Particles *particles = particles_owner.get_or_null(p_particles); -		ERR_FAIL_COND_V(!particles, 0); - -		return particles->has_collision_cache; -	} - -	_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) { -		Particles *particles = particles_owner.get_or_null(p_particles); -		ERR_FAIL_COND_V(!particles, false); - -		return particles->use_local_coords; -	} - -	_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) { -		Particles *particles = particles_owner.get_or_null(p_particles); -		ERR_FAIL_COND_V(!particles, RID()); -		if (particles->particles_transforms_buffer_uniform_set.is_null()) { -			_particles_update_buffers(particles); - -			Vector<RD::Uniform> uniforms; - -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -				u.binding = 0; -				u.append_id(particles->particle_instance_buffer); -				uniforms.push_back(u); -			} - -			particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); -		} - -		return particles->particles_transforms_buffer_uniform_set; -	} - -	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance); -	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance); -	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture); - -	/* PARTICLES COLLISION */ - -	RID particles_collision_allocate(); -	void particles_collision_initialize(RID p_particles_collision); - -	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type); -	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask); -	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius); //for spheres -	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents); //for non-spheres -	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength); -	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality); -	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve); -	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture); //for SDF and vector field, heightfield is dynamic -	virtual void particles_collision_height_field_update(RID p_particles_collision); //for SDF and vector field -	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution); //for SDF and vector field -	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const; -	virtual Vector3 particles_collision_get_extents(RID p_particles_collision) const; -	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const; -	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const; -  	/* FOG VOLUMES */  	virtual RID fog_volume_allocate(); @@ -764,11 +263,6 @@ public:  	virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;  	virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred); -	//used from 2D and 3D -	virtual RID particles_collision_instance_create(RID p_collision); -	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform); -	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active); -  	RS::InstanceType get_base_type(RID p_rid) const;  	bool free(RID p_rid); diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 2a2c5f350a..75c502c666 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -1298,6 +1298,94 @@ MaterialStorage *MaterialStorage::get_singleton() {  MaterialStorage::MaterialStorage() {  	singleton = this; +	//default samplers +	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { +		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { +			RD::SamplerState sampler_state; +			switch (i) { +				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.max_lod = 0; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.max_lod = 0; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} + +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +					sampler_state.use_anisotropy = true; +					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +					sampler_state.use_anisotropy = true; +					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); + +				} break; +				default: { +				} +			} +			switch (j) { +				case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { +					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; +					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; +					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + +				} break; +				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { +					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; +					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; +					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { +					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; +					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; +					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; +				} break; +				default: { +				} +			} + +			default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); +		} +	} + +	//custom sampler +	sampler_rd_configure_custom(0.0f); +  	for (int i = 0; i < SHADER_TYPE_MAX; i++) {  		shader_data_request_func[i] = nullptr;  	} @@ -1319,9 +1407,121 @@ MaterialStorage::~MaterialStorage() {  	memdelete_arr(global_variables.buffer_dirty_regions);  	RD::get_singleton()->free(global_variables.buffer); +	//def samplers +	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { +		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { +			RD::get_singleton()->free(default_rd_samplers[i][j]); +		} +	} + +	//custom samplers +	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { +		for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { +			if (custom_rd_samplers[i][j].is_valid()) { +				RD::get_singleton()->free(custom_rd_samplers[i][j]); +			} +		} +	} +  	singleton = nullptr;  } +/* Samplers */ + +void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) { +	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { +		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { +			RD::SamplerState sampler_state; +			switch (i) { +				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.max_lod = 0; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.max_lod = 0; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +					sampler_state.lod_bias = p_mipmap_bias; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +					sampler_state.lod_bias = p_mipmap_bias; + +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; +					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +					sampler_state.lod_bias = p_mipmap_bias; +					sampler_state.use_anisotropy = true; +					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); +				} break; +				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { +					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; +					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; +					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; +					} else { +						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; +					} +					sampler_state.lod_bias = p_mipmap_bias; +					sampler_state.use_anisotropy = true; +					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); + +				} break; +				default: { +				} +			} +			switch (j) { +				case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { +					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; +					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; +					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + +				} break; +				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { +					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; +					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; +					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; +				} break; +				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { +					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; +					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; +					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; +				} break; +				default: { +				} +			} + +			if (custom_rd_samplers[i][j].is_valid()) { +				RD::get_singleton()->free(custom_rd_samplers[i][j]); +			} + +			custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); +		} +	} +} +  /* GLOBAL VARIABLE API */  int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 270d9f0982..c8cc418c3a 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -195,6 +195,11 @@ private:  	friend struct MaterialData;  	static MaterialStorage *singleton; +	/* Samplers */ + +	RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; +	RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; +  	/* GLOBAL VARIABLE API */  	GlobalVariables global_variables; @@ -222,6 +227,19 @@ public:  	MaterialStorage();  	virtual ~MaterialStorage(); +	/* Samplers */ + +	_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { +		return default_rd_samplers[p_filter][p_repeat]; +	} +	_FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { +		return custom_rd_samplers[p_filter][p_repeat]; +	} + +	void sampler_rd_configure_custom(float mipmap_bias); + +	// void sampler_rd_set_default(float p_mipmap_bias); +  	/* GLOBAL VARIABLE API */  	void _update_global_variables(); diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp new file mode 100644 index 0000000000..75dd20bdbd --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -0,0 +1,1897 @@ +/*************************************************************************/ +/*  particles_storage.cpp                                                */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#include "particles_storage.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/rendering_server_globals.h" +#include "texture_storage.h" + +using namespace RendererRD; + +ParticlesStorage *ParticlesStorage::singleton = nullptr; + +ParticlesStorage *ParticlesStorage::get_singleton() { +	return singleton; +} + +ParticlesStorage::ParticlesStorage() { +	singleton = this; + +	MaterialStorage *material_storage = MaterialStorage::get_singleton(); + +	/* Particles */ + +	{ +		// Initialize particles +		Vector<String> particles_modes; +		particles_modes.push_back(""); +		particles_shader.shader.initialize(particles_modes, String()); +	} +	MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); +	MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs); + +	{ +		ShaderCompiler::DefaultIdentifierActions actions; + +		actions.renames["COLOR"] = "PARTICLE.color"; +		actions.renames["VELOCITY"] = "PARTICLE.velocity"; +		//actions.renames["MASS"] = "mass"; ? +		actions.renames["ACTIVE"] = "particle_active"; +		actions.renames["RESTART"] = "restart"; +		actions.renames["CUSTOM"] = "PARTICLE.custom"; +		for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { +			String udname = "USERDATA" + itos(i + 1); +			actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1); +			actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n"; +		} +		actions.renames["TRANSFORM"] = "PARTICLE.xform"; +		actions.renames["TIME"] = "frame_history.data[0].time"; +		actions.renames["PI"] = _MKSTR(Math_PI); +		actions.renames["TAU"] = _MKSTR(Math_TAU); +		actions.renames["E"] = _MKSTR(Math_E); +		actions.renames["LIFETIME"] = "params.lifetime"; +		actions.renames["DELTA"] = "local_delta"; +		actions.renames["NUMBER"] = "particle_number"; +		actions.renames["INDEX"] = "index"; +		//actions.renames["GRAVITY"] = "current_gravity"; +		actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform"; +		actions.renames["RANDOM_SEED"] = "FRAME.random_seed"; +		actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION"; +		actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE"; +		actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY"; +		actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR"; +		actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM"; +		actions.renames["RESTART_POSITION"] = "restart_position"; +		actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale"; +		actions.renames["RESTART_VELOCITY"] = "restart_velocity"; +		actions.renames["RESTART_COLOR"] = "restart_color"; +		actions.renames["RESTART_CUSTOM"] = "restart_custom"; +		actions.renames["emit_subparticle"] = "emit_subparticle"; +		actions.renames["COLLIDED"] = "collided"; +		actions.renames["COLLISION_NORMAL"] = "collision_normal"; +		actions.renames["COLLISION_DEPTH"] = "collision_depth"; +		actions.renames["ATTRACTOR_FORCE"] = "attractor_force"; + +		actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; +		actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; +		actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; +		actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n"; + +		actions.sampler_array_name = "material_samplers"; +		actions.base_texture_binding_index = 1; +		actions.texture_layout_set = 3; +		actions.base_uniform_string = "material."; +		actions.base_varying_index = 10; + +		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; +		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; +		actions.global_buffer_array_variable = "global_variables.data"; + +		particles_shader.compiler.initialize(actions); +	} + +	{ +		// default material and shader for particles shader +		particles_shader.default_shader = material_storage->shader_allocate(); +		material_storage->shader_initialize(particles_shader.default_shader); +		material_storage->shader_set_code(particles_shader.default_shader, R"( +// Default particles shader. + +shader_type particles; + +void process() { +	COLOR = vec4(1.0); +} +)"); +		particles_shader.default_material = material_storage->material_allocate(); +		material_storage->material_initialize(particles_shader.default_material); +		material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); + +		ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES)); +		particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); + +		Vector<RD::Uniform> uniforms; + +		{ +			Vector<RID> ids; +			ids.resize(12); +			RID *ids_ptr = ids.ptrw(); +			ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); +			ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); +			ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + +			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); +			uniforms.push_back(u); +		} + +		{ +			RD::Uniform u; +			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +			u.binding = 2; +			u.append_id(material_storage->global_variables_get_storage_buffer()); +			uniforms.push_back(u); +		} + +		particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0); +	} + +	{ +		Vector<String> copy_modes; +		for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { +			if (i == 0) { +				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n"); +				copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n"); +				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n"); +			} else { +				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n"); +				copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n"); +				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n"); +			} +		} + +		particles_shader.copy_shader.initialize(copy_modes); + +		particles_shader.copy_shader_version = particles_shader.copy_shader.version_create(); + +		for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { +			for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) { +				particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j)); +			} +		} +	} +} + +ParticlesStorage::~ParticlesStorage() { +	MaterialStorage *material_storage = MaterialStorage::get_singleton(); + +	particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); + +	material_storage->material_free(particles_shader.default_material); +	material_storage->shader_free(particles_shader.default_shader); + +	singleton = nullptr; +} + +/* PARTICLES */ + +RID ParticlesStorage::particles_allocate() { +	return particles_owner.allocate_rid(); +} + +void ParticlesStorage::particles_initialize(RID p_rid) { +	particles_owner.initialize_rid(p_rid, Particles()); +} + +void ParticlesStorage::particles_free(RID p_rid) { +	update_particles(); +	Particles *particles = particles_owner.get_or_null(p_rid); +	particles->dependency.deleted_notify(p_rid); +	_particles_free_data(particles); +	particles_owner.free(p_rid); +} + +void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	if (particles->mode == p_mode) { +		return; +	} + +	_particles_free_data(particles); + +	particles->mode = p_mode; +} + +void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->emitting = p_emitting; +} + +bool ParticlesStorage::particles_get_emitting(RID p_particles) { +	ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, false); + +	return particles->emitting; +} + +void ParticlesStorage::_particles_free_data(Particles *particles) { +	if (particles->particle_buffer.is_valid()) { +		RD::get_singleton()->free(particles->particle_buffer); +		particles->particle_buffer = RID(); +		RD::get_singleton()->free(particles->particle_instance_buffer); +		particles->particle_instance_buffer = RID(); +	} + +	particles->userdata_count = 0; + +	if (particles->frame_params_buffer.is_valid()) { +		RD::get_singleton()->free(particles->frame_params_buffer); +		particles->frame_params_buffer = RID(); +	} +	particles->particles_transforms_buffer_uniform_set = RID(); + +	if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) { +		RD::get_singleton()->free(particles->trail_bind_pose_uniform_set); +	} +	particles->trail_bind_pose_uniform_set = RID(); + +	if (particles->trail_bind_pose_buffer.is_valid()) { +		RD::get_singleton()->free(particles->trail_bind_pose_buffer); +		particles->trail_bind_pose_buffer = RID(); +	} +	if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) { +		RD::get_singleton()->free(particles->collision_textures_uniform_set); +	} +	particles->collision_textures_uniform_set = RID(); + +	if (particles->particles_sort_buffer.is_valid()) { +		RD::get_singleton()->free(particles->particles_sort_buffer); +		particles->particles_sort_buffer = RID(); +		particles->particles_sort_uniform_set = RID(); +	} + +	if (particles->emission_buffer != nullptr) { +		particles->emission_buffer = nullptr; +		particles->emission_buffer_data.clear(); +		RD::get_singleton()->free(particles->emission_storage_buffer); +		particles->emission_storage_buffer = RID(); +	} + +	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { +		//will need to be re-created +		RD::get_singleton()->free(particles->particles_material_uniform_set); +	} +	particles->particles_material_uniform_set = RID(); +} + +void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	if (particles->amount == p_amount) { +		return; +	} + +	_particles_free_data(particles); + +	particles->amount = p_amount; + +	particles->prev_ticks = 0; +	particles->phase = 0; +	particles->prev_phase = 0; +	particles->clear = true; + +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); +} + +void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->lifetime = p_lifetime; +} + +void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->one_shot = p_one_shot; +} + +void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->pre_process_time = p_time; +} +void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->explosiveness = p_ratio; +} +void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->randomness = p_ratio; +} + +void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->custom_aabb = p_aabb; +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->speed_scale = p_scale; +} +void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->use_local_coords = p_enable; +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); +} + +void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->fixed_fps = p_fps; + +	_particles_free_data(particles); + +	particles->prev_ticks = 0; +	particles->phase = 0; +	particles->prev_phase = 0; +	particles->clear = true; + +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); +} + +void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->interpolate = p_enable; +} + +void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->fractional_delta = p_enable; +} + +void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	ERR_FAIL_COND(p_length < 0.1); +	p_length = MIN(10.0, p_length); + +	particles->trails_enabled = p_enable; +	particles->trail_length = p_length; + +	_particles_free_data(particles); + +	particles->prev_ticks = 0; +	particles->phase = 0; +	particles->prev_phase = 0; +	particles->clear = true; + +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); +} + +void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) { +		_particles_free_data(particles); + +		particles->prev_ticks = 0; +		particles->phase = 0; +		particles->prev_phase = 0; +		particles->clear = true; +	} +	particles->trail_bind_poses = p_bind_poses; +	particles->trail_bind_poses_dirty = true; + +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); +} + +void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->collision_base_size = p_size; +} + +void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->transform_align = p_transform_align; +} + +void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->process_material = p_material; +	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed +} + +RID ParticlesStorage::particles_get_process_material(RID p_particles) const { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, RID()); + +	return particles->process_material; +} + +void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->draw_order = p_order; +} + +void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->draw_passes.resize(p_passes); +} + +void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); +	particles->draw_passes.write[p_pass] = p_mesh; +} + +void ParticlesStorage::particles_restart(RID p_particles) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->restart_request = true; +} + +void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) { +	ERR_FAIL_COND(particles->emission_buffer != nullptr); + +	particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4); +	memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size()); +	particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw()); +	particles->emission_buffer->particle_max = particles->amount; + +	particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data); + +	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { +		//will need to be re-created +		RD::get_singleton()->free(particles->particles_material_uniform_set); +		particles->particles_material_uniform_set = RID(); +	} +} + +void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	ERR_FAIL_COND(p_particles == p_subemitter_particles); + +	particles->sub_emitter = p_subemitter_particles; + +	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { +		RD::get_singleton()->free(particles->particles_material_uniform_set); +		particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting +	} +} + +void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	ERR_FAIL_COND(particles->amount == 0); + +	if (particles->emitting) { +		particles->clear = true; +		particles->emitting = false; +	} + +	if (particles->emission_buffer == nullptr) { +		_particles_allocate_emission_buffer(particles); +	} + +	if (particles->inactive) { +		//in case it was inactive, make active again +		particles->inactive = false; +		particles->inactive_time = 0; +	} + +	int32_t idx = particles->emission_buffer->particle_count; +	if (idx < particles->emission_buffer->particle_max) { +		RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform); + +		particles->emission_buffer->data[idx].velocity[0] = p_velocity.x; +		particles->emission_buffer->data[idx].velocity[1] = p_velocity.y; +		particles->emission_buffer->data[idx].velocity[2] = p_velocity.z; + +		particles->emission_buffer->data[idx].custom[0] = p_custom.r; +		particles->emission_buffer->data[idx].custom[1] = p_custom.g; +		particles->emission_buffer->data[idx].custom[2] = p_custom.b; +		particles->emission_buffer->data[idx].custom[3] = p_custom.a; + +		particles->emission_buffer->data[idx].color[0] = p_color.r; +		particles->emission_buffer->data[idx].color[1] = p_color.g; +		particles->emission_buffer->data[idx].color[2] = p_color.b; +		particles->emission_buffer->data[idx].color[3] = p_color.a; + +		particles->emission_buffer->data[idx].flags = p_emit_flags; +		particles->emission_buffer->particle_count++; +	} +} + +void ParticlesStorage::particles_request_process(RID p_particles) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	if (!particles->dirty) { +		particles->dirty = true; +		particles->update_list = particle_update_list; +		particle_update_list = particles; +	} +} + +AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) { +	if (RSG::threaded) { +		WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care."); +	} + +	const Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, AABB()); + +	int total_amount = particles->amount; +	if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +		total_amount *= particles->trail_bind_poses.size(); +	} + +	Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer); +	ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB()); + +	Transform3D inv = particles->emission_transform.affine_inverse(); + +	AABB aabb; +	if (buffer.size()) { +		bool first = true; + +		const uint8_t *data_ptr = (const uint8_t *)buffer.ptr(); +		uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count; + +		for (int i = 0; i < total_amount; i++) { +			const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i]; +			if (particle_data.active) { +				Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]); +				if (!particles->use_local_coords) { +					pos = inv.xform(pos); +				} +				if (first) { +					aabb.position = pos; +					first = false; +				} else { +					aabb.expand_to(pos); +				} +			} +		} +	} + +	float longest_axis_size = 0; +	for (int i = 0; i < particles->draw_passes.size(); i++) { +		if (particles->draw_passes[i].is_valid()) { +			AABB maabb = MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID()); +			longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size); +		} +	} + +	aabb.grow_by(longest_axis_size); + +	return aabb; +} + +AABB ParticlesStorage::particles_get_aabb(RID p_particles) const { +	const Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, AABB()); + +	return particles->custom_aabb; +} + +void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	particles->emission_transform = p_transform; +} + +int ParticlesStorage::particles_get_draw_passes(RID p_particles) const { +	const Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, 0); + +	return particles->draw_passes.size(); +} + +RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { +	const Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, RID()); +	ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID()); + +	return particles->draw_passes[p_pass]; +} + +void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->collisions.insert(p_particles_collision_instance); +} + +void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->collisions.erase(p_particles_collision_instance); +} + +void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); +	particles->has_sdf_collision = p_enable; +	particles->sdf_collision_transform = p_xform; +	particles->sdf_collision_to_screen = p_to_screen; +	particles->sdf_collision_texture = p_texture; +} + +void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta) { +	TextureStorage *texture_storage = TextureStorage::get_singleton(); +	MaterialStorage *material_storage = MaterialStorage::get_singleton(); + +	if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { +		Vector<RD::Uniform> uniforms; + +		{ +			RD::Uniform u; +			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +			u.binding = 0; +			u.append_id(p_particles->frame_params_buffer); +			uniforms.push_back(u); +		} +		{ +			RD::Uniform u; +			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +			u.binding = 1; +			u.append_id(p_particles->particle_buffer); +			uniforms.push_back(u); +		} + +		{ +			RD::Uniform u; +			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +			u.binding = 2; +			if (p_particles->emission_storage_buffer.is_valid()) { +				u.append_id(p_particles->emission_storage_buffer); +			} else { +				u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer()); +			} +			uniforms.push_back(u); +		} +		{ +			RD::Uniform u; +			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +			u.binding = 3; +			Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter); +			if (sub_emitter) { +				if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer +					_particles_allocate_emission_buffer(sub_emitter); +				} +				u.append_id(sub_emitter->emission_storage_buffer); +			} else { +				u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer()); +			} +			uniforms.push_back(u); +		} + +		p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1); +	} + +	double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0); + +	//move back history (if there is any) +	for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) { +		p_particles->frame_history[i] = p_particles->frame_history[i - 1]; +	} +	//update current frame +	ParticlesFrameParams &frame_params = p_particles->frame_history[0]; + +	if (p_particles->clear) { +		p_particles->cycle_number = 0; +		p_particles->random_seed = Math::rand(); +	} else if (new_phase < p_particles->phase) { +		if (p_particles->one_shot) { +			p_particles->emitting = false; +		} +		p_particles->cycle_number++; +	} + +	frame_params.emitting = p_particles->emitting; +	frame_params.system_phase = new_phase; +	frame_params.prev_system_phase = p_particles->phase; + +	p_particles->phase = new_phase; + +	frame_params.time = RendererCompositorRD::singleton->get_total_time(); +	frame_params.delta = p_delta * p_particles->speed_scale; +	frame_params.random_seed = p_particles->random_seed; +	frame_params.explosiveness = p_particles->explosiveness; +	frame_params.randomness = p_particles->randomness; + +	if (p_particles->use_local_coords) { +		RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform); +	} else { +		RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform); +	} + +	frame_params.cycle = p_particles->cycle_number; +	frame_params.frame = p_particles->frame_counter++; +	frame_params.pad0 = 0; +	frame_params.pad1 = 0; +	frame_params.pad2 = 0; + +	{ //collision and attractors + +		frame_params.collider_count = 0; +		frame_params.attractor_count = 0; +		frame_params.particle_size = p_particles->collision_base_size; + +		RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; +		RID collision_heightmap_texture; + +		Transform3D to_particles; +		if (p_particles->use_local_coords) { +			to_particles = p_particles->emission_transform.affine_inverse(); +		} + +		if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) { +			//2D collision + +			Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand +			Transform2D revert = xform.affine_inverse(); +			frame_params.collider_count = 1; +			frame_params.colliders[0].transform[0] = xform.elements[0][0]; +			frame_params.colliders[0].transform[1] = xform.elements[0][1]; +			frame_params.colliders[0].transform[2] = 0; +			frame_params.colliders[0].transform[3] = xform.elements[2][0]; + +			frame_params.colliders[0].transform[4] = xform.elements[1][0]; +			frame_params.colliders[0].transform[5] = xform.elements[1][1]; +			frame_params.colliders[0].transform[6] = 0; +			frame_params.colliders[0].transform[7] = xform.elements[2][1]; + +			frame_params.colliders[0].transform[8] = revert.elements[0][0]; +			frame_params.colliders[0].transform[9] = revert.elements[0][1]; +			frame_params.colliders[0].transform[10] = 0; +			frame_params.colliders[0].transform[11] = revert.elements[2][0]; + +			frame_params.colliders[0].transform[12] = revert.elements[1][0]; +			frame_params.colliders[0].transform[13] = revert.elements[1][1]; +			frame_params.colliders[0].transform[14] = 0; +			frame_params.colliders[0].transform[15] = revert.elements[2][1]; + +			frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x; +			frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y; +			frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x; +			frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y; +			frame_params.colliders[0].texture_index = 0; +			frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF; + +			collision_heightmap_texture = p_particles->sdf_collision_texture; + +			//replace in all other history frames where used because parameters are no longer valid if screen moves +			for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) { +				if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) { +					p_particles->frame_history[i].colliders[0] = frame_params.colliders[0]; +				} +			} +		} + +		uint32_t collision_3d_textures_used = 0; +		for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { +			ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get()); +			if (!pci || !pci->active) { +				continue; +			} +			ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision); +			ERR_CONTINUE(!pc); + +			Transform3D to_collider = pci->transform; +			if (p_particles->use_local_coords) { +				to_collider = to_particles * to_collider; +			} +			Vector3 scale = to_collider.basis.get_scale(); +			to_collider.basis.orthonormalize(); + +			if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) { +				//attractor +				if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) { +					continue; +				} + +				ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count]; + +				RendererStorageRD::store_transform(to_collider, attr.transform); +				attr.strength = pc->attractor_strength; +				attr.attenuation = pc->attractor_attenuation; +				attr.directionality = pc->attractor_directionality; + +				switch (pc->type) { +					case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: { +						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE; +						float radius = pc->radius; +						radius *= (scale.x + scale.y + scale.z) / 3.0; +						attr.extents[0] = radius; +						attr.extents[1] = radius; +						attr.extents[2] = radius; +					} break; +					case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: { +						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX; +						Vector3 extents = pc->extents * scale; +						attr.extents[0] = extents.x; +						attr.extents[1] = extents.y; +						attr.extents[2] = extents.z; +					} break; +					case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: { +						if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) { +							continue; +						} +						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD; +						Vector3 extents = pc->extents * scale; +						attr.extents[0] = extents.x; +						attr.extents[1] = extents.y; +						attr.extents[2] = extents.z; +						attr.texture_index = collision_3d_textures_used; + +						collision_3d_textures[collision_3d_textures_used] = pc->field_texture; +						collision_3d_textures_used++; +					} break; +					default: { +					} +				} + +				frame_params.attractor_count++; +			} else { +				//collider +				if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) { +					continue; +				} + +				ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count]; + +				RendererStorageRD::store_transform(to_collider, col.transform); +				switch (pc->type) { +					case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: { +						col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE; +						float radius = pc->radius; +						radius *= (scale.x + scale.y + scale.z) / 3.0; +						col.extents[0] = radius; +						col.extents[1] = radius; +						col.extents[2] = radius; +					} break; +					case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: { +						col.type = ParticlesFrameParams::COLLISION_TYPE_BOX; +						Vector3 extents = pc->extents * scale; +						col.extents[0] = extents.x; +						col.extents[1] = extents.y; +						col.extents[2] = extents.z; +					} break; +					case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: { +						if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) { +							continue; +						} +						col.type = ParticlesFrameParams::COLLISION_TYPE_SDF; +						Vector3 extents = pc->extents * scale; +						col.extents[0] = extents.x; +						col.extents[1] = extents.y; +						col.extents[2] = extents.z; +						col.texture_index = collision_3d_textures_used; +						col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported + +						collision_3d_textures[collision_3d_textures_used] = pc->field_texture; +						collision_3d_textures_used++; +					} break; +					case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: { +						if (collision_heightmap_texture != RID()) { //already taken +							continue; +						} + +						col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD; +						Vector3 extents = pc->extents * scale; +						col.extents[0] = extents.x; +						col.extents[1] = extents.y; +						col.extents[2] = extents.z; +						collision_heightmap_texture = pc->heightfield_texture; +					} break; +					default: { +					} +				} + +				frame_params.collider_count++; +			} +		} + +		bool different = false; +		if (collision_3d_textures_used == p_particles->collision_3d_textures_used) { +			for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { +				if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) { +					different = true; +					break; +				} +			} +		} + +		if (collision_heightmap_texture != p_particles->collision_heightmap_texture) { +			different = true; +		} + +		bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set); + +		if (different || !uniform_set_valid) { +			if (uniform_set_valid) { +				RD::get_singleton()->free(p_particles->collision_textures_uniform_set); +			} + +			Vector<RD::Uniform> uniforms; + +			{ +				RD::Uniform u; +				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +				u.binding = 0; +				for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { +					RID rd_tex; +					if (i < collision_3d_textures_used) { +						Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); +						if (t && t->type == Texture::TYPE_3D) { +							rd_tex = t->rd_texture; +						} +					} + +					if (rd_tex == RID()) { +						rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); +					} +					u.append_id(rd_tex); +				} +				uniforms.push_back(u); +			} +			{ +				RD::Uniform u; +				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +				u.binding = 1; +				if (collision_heightmap_texture.is_valid()) { +					u.append_id(collision_heightmap_texture); +				} else { +					u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK)); +				} +				uniforms.push_back(u); +			} +			p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2); +		} +	} + +	ParticlesShader::PushConstant push_constant; + +	int process_amount = p_particles->amount; + +	if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) { +		process_amount *= p_particles->trail_bind_poses.size(); +	} +	push_constant.clear = p_particles->clear; +	push_constant.total_particles = p_particles->amount; +	push_constant.lifetime = p_particles->lifetime; +	push_constant.trail_size = p_particles->trail_params.size(); +	push_constant.use_fractional_delta = p_particles->fractional_delta; +	push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit); +	push_constant.trail_pass = false; + +	p_particles->force_sub_emit = false; //reset + +	Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter); + +	if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) { +		//	print_line("updating subemitter buffer"); +		int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 }; +		RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero); +		push_constant.can_emit = true; + +		if (sub_emitter->emitting) { +			sub_emitter->emitting = false; +			sub_emitter->clear = true; //will need to clear if it was emitting, sorry +		} +		//make sure the sub emitter processes particles too +		sub_emitter->inactive = false; +		sub_emitter->inactive_time = 0; + +		sub_emitter->force_sub_emit = true; + +	} else { +		push_constant.can_emit = false; +	} + +	if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) { +		RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer); +		p_particles->emission_buffer->particle_count = 0; +	} + +	p_particles->clear = false; + +	if (p_particles->trail_params.size() > 1) { +		//fill the trail params +		for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) { +			uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size(); +			p_particles->trail_params[i] = p_particles->frame_history[src_idx]; +		} +	} else { +		p_particles->trail_params[0] = p_particles->frame_history[0]; +	} + +	RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); + +	ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES)); +	if (!m) { +		m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES)); +	} + +	ERR_FAIL_COND(!m); + +	p_particles->has_collision_cache = m->shader_data->uses_collision; + +	//todo should maybe compute all particle systems together? +	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); +	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline); +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0); +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1); +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2); + +	if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) { +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3); +	} + +	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant)); + +	if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) { +		//trails requires two passes in order to catch particle starts +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1); + +		RD::get_singleton()->compute_list_add_barrier(compute_list); + +		push_constant.trail_pass = true; +		RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant)); +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1); +	} else { +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1); +	} + +	RD::get_singleton()->compute_list_end(); +} + +void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) { +	Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND(!particles); + +	if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { +		return; +	} + +	if (particles->particle_buffer.is_null()) { +		return; //particles have not processed yet +	} + +	bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH; + +	//copy to sort buffer +	if (do_sort && particles->particles_sort_buffer == RID()) { +		uint32_t size = particles->amount; +		if (size & 1) { +			size++; //make multiple of 16 +		} +		size *= sizeof(float) * 2; +		particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size); + +		{ +			Vector<RD::Uniform> uniforms; + +			{ +				RD::Uniform u; +				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +				u.binding = 0; +				u.append_id(particles->particles_sort_buffer); +				uniforms.push_back(u); +			} + +			particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1); +		} +	} + +	ParticlesShader::CopyPushConstant copy_push_constant; + +	if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +		int fixed_fps = 60.0; +		if (particles->fixed_fps > 0) { +			fixed_fps = particles->fixed_fps; +		} + +		copy_push_constant.trail_size = particles->trail_bind_poses.size(); +		copy_push_constant.trail_total = particles->frame_history.size(); +		copy_push_constant.frame_delta = 1.0 / fixed_fps; +	} else { +		copy_push_constant.trail_size = 1; +		copy_push_constant.trail_total = 1; +		copy_push_constant.frame_delta = 0.0; +	} + +	copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME); +	copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1); +	copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME; + +	copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0; +	copy_push_constant.total_particles = particles->amount; +	copy_push_constant.copy_mode_2d = false; + +	Vector3 axis = -p_axis; // cameras look to z negative + +	if (particles->use_local_coords) { +		axis = particles->emission_transform.basis.xform_inv(axis).normalized(); +	} + +	copy_push_constant.sort_direction[0] = axis.x; +	copy_push_constant.sort_direction[1] = axis.y; +	copy_push_constant.sort_direction[2] = axis.z; + +	copy_push_constant.align_up[0] = p_up_axis.x; +	copy_push_constant.align_up[1] = p_up_axis.y; +	copy_push_constant.align_up[2] = p_up_axis.z; + +	copy_push_constant.align_mode = particles->transform_align; + +	if (do_sort) { +		RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + +		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); +		RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); + +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1); + +		RD::get_singleton()->compute_list_end(); +		RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount); +	} + +	copy_push_constant.total_particles *= copy_push_constant.total_particles; + +	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); +	uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES; +	copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX; +	copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0; +	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]); +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); +	if (do_sort) { +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); +	} +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); + +	RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); + +	RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1); + +	RD::get_singleton()->compute_list_end(); +} + +void ParticlesStorage::_particles_update_buffers(Particles *particles) { +	uint32_t userdata_count = 0; + +	const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material); +	if (material && material->shader && material->shader->data) { +		const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); +		userdata_count = shader_data->userdata_count; +	} + +	if (userdata_count != particles->userdata_count) { +		// Mismatch userdata, re-create buffers. +		_particles_free_data(particles); +	} + +	if (particles->amount > 0 && particles->particle_buffer.is_null()) { +		int total_amount = particles->amount; +		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +			total_amount *= particles->trail_bind_poses.size(); +		} + +		uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3; + +		particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount); + +		particles->userdata_count = userdata_count; + +		particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount); +		//needs to clear it + +		{ +			Vector<RD::Uniform> uniforms; + +			{ +				RD::Uniform u; +				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +				u.binding = 1; +				u.append_id(particles->particle_buffer); +				uniforms.push_back(u); +			} +			{ +				RD::Uniform u; +				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +				u.binding = 2; +				u.append_id(particles->particle_instance_buffer); +				uniforms.push_back(u); +			} + +			particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0); +		} +	} +} +void ParticlesStorage::update_particles() { +	while (particle_update_list) { +		//use transform feedback to process particles + +		Particles *particles = particle_update_list; + +		//take and remove +		particle_update_list = particles->update_list; +		particles->update_list = nullptr; +		particles->dirty = false; + +		_particles_update_buffers(particles); + +		if (particles->restart_request) { +			particles->prev_ticks = 0; +			particles->phase = 0; +			particles->prev_phase = 0; +			particles->clear = true; +			particles->restart_request = false; +		} + +		if (particles->inactive && !particles->emitting) { +			//go next +			continue; +		} + +		if (particles->emitting) { +			if (particles->inactive) { +				//restart system from scratch +				particles->prev_ticks = 0; +				particles->phase = 0; +				particles->prev_phase = 0; +				particles->clear = true; +			} +			particles->inactive = false; +			particles->inactive_time = 0; +		} else { +			particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time(); +			if (particles->inactive_time > particles->lifetime * 1.2) { +				particles->inactive = true; +				continue; +			} +		} + +#ifndef _MSC_VER +#warning Should use display refresh rate for all this +#endif + +		float screen_hz = 60; + +		int fixed_fps = 0; +		if (particles->fixed_fps > 0) { +			fixed_fps = particles->fixed_fps; +		} else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +			fixed_fps = screen_hz; +		} +		{ +			//update trails +			int history_size = 1; +			int trail_steps = 1; +			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +				history_size = MAX(1, int(particles->trail_length * fixed_fps)); +				trail_steps = particles->trail_bind_poses.size(); +			} + +			if (uint32_t(history_size) != particles->frame_history.size()) { +				particles->frame_history.resize(history_size); +				memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size); +			} + +			if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) { +				particles->trail_params.resize(trail_steps); +				if (particles->frame_params_buffer.is_valid()) { +					RD::get_singleton()->free(particles->frame_params_buffer); +				} +				particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps); +			} + +			if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) { +				particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size()); +				particles->trail_bind_poses_dirty = true; +			} + +			if (particles->trail_bind_pose_uniform_set.is_null()) { +				Vector<RD::Uniform> uniforms; +				{ +					RD::Uniform u; +					u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +					u.binding = 0; +					if (particles->trail_bind_pose_buffer.is_valid()) { +						u.append_id(particles->trail_bind_pose_buffer); +					} else { +						u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer()); +					} +					uniforms.push_back(u); +				} + +				particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2); +			} + +			if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) { +				if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) { +					particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16); +				} + +				for (int i = 0; i < particles->trail_bind_poses.size(); i++) { +					RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]); +				} + +				RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr()); +			} +		} + +		bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0; + +		if (particles->clear && particles->pre_process_time > 0.0) { +			double frame_time; +			if (fixed_fps > 0) { +				frame_time = 1.0 / fixed_fps; +			} else { +				frame_time = 1.0 / 30.0; +			} + +			double todo = particles->pre_process_time; + +			while (todo >= 0) { +				_particles_process(particles, frame_time); +				todo -= frame_time; +			} +		} + +		if (fixed_fps > 0) { +			double frame_time; +			double decr; +			if (zero_time_scale) { +				frame_time = 0.0; +				decr = 1.0 / fixed_fps; +			} else { +				frame_time = 1.0 / fixed_fps; +				decr = frame_time; +			} +			double delta = RendererCompositorRD::singleton->get_frame_delta_time(); +			if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 +				delta = 0.1; +			} else if (delta <= 0.0) { //unlikely but.. +				delta = 0.001; +			} +			double todo = particles->frame_remainder + delta; + +			while (todo >= frame_time) { +				_particles_process(particles, frame_time); +				todo -= decr; +			} + +			particles->frame_remainder = todo; + +		} else { +			if (zero_time_scale) { +				_particles_process(particles, 0.0); +			} else { +				_particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time()); +			} +		} + +		//copy particles to instance buffer + +		if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { +			//does not need view dependent operation, do copy here +			ParticlesShader::CopyPushConstant copy_push_constant; + +			int total_amount = particles->amount; +			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +				total_amount *= particles->trail_bind_poses.size(); +			} + +			// Affect 2D only. +			if (particles->use_local_coords) { +				// In local mode, particle positions are calculated locally (relative to the node position) +				// and they're also drawn locally. +				// It works as expected, so we just pass an identity transform. +				RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform); +			} else { +				// In global mode, particle positions are calculated globally (relative to the canvas origin) +				// but they're drawn locally. +				// So, we need to pass the inverse of the emission transform to bring the +				// particles to local coordinates before drawing. +				Transform3D inv = particles->emission_transform.affine_inverse(); +				RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform); +			} + +			copy_push_constant.total_particles = total_amount; +			copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0; +			copy_push_constant.align_mode = particles->transform_align; +			copy_push_constant.align_up[0] = 0; +			copy_push_constant.align_up[1] = 0; +			copy_push_constant.align_up[2] = 0; + +			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +				copy_push_constant.trail_size = particles->trail_bind_poses.size(); +				copy_push_constant.trail_total = particles->frame_history.size(); +				copy_push_constant.frame_delta = 1.0 / fixed_fps; +			} else { +				copy_push_constant.trail_size = 1; +				copy_push_constant.trail_total = 1; +				copy_push_constant.frame_delta = 0.0; +			} + +			copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME); +			copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1); +			copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME; + +			RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); +			copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0; +			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]); +			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); +			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); +			RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); + +			RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1); + +			RD::get_singleton()->compute_list_end(); +		} + +		particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +	} +} + +bool ParticlesStorage::particles_is_inactive(RID p_particles) const { +	ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); +	const Particles *particles = particles_owner.get_or_null(p_particles); +	ERR_FAIL_COND_V(!particles, false); +	return !particles->emitting && particles->inactive; +} + +/* Particles SHADER */ + +void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) { +	ParticlesStorage *particles_storage = ParticlesStorage::get_singleton(); +	//compile + +	code = p_code; +	valid = false; +	ubo_size = 0; +	uniforms.clear(); +	uses_collision = false; + +	if (code.is_empty()) { +		return; //just invalid, but no error +	} + +	ShaderCompiler::GeneratedCode gen_code; +	ShaderCompiler::IdentifierActions actions; +	actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE; +	actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE; + +	/* +	uses_time = false; + +	actions.render_mode_flags["use_half_res_pass"] = &uses_half_res; +	actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res; + +	actions.usage_flag_pointers["TIME"] = &uses_time; +*/ + +	actions.usage_flag_pointers["COLLIDED"] = &uses_collision; + +	userdata_count = 0; +	for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { +		userdatas_used[i] = false; +		actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i]; +	} + +	actions.uniforms = &uniforms; + +	Error err = particles_storage->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code); +	ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); + +	if (version.is_null()) { +		version = particles_storage->particles_shader.shader.version_create(); +	} + +	for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { +		if (userdatas_used[i]) { +			userdata_count++; +		} +	} + +	particles_storage->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); +	ERR_FAIL_COND(!particles_storage->particles_shader.shader.version_is_valid(version)); + +	ubo_size = gen_code.uniform_total_size; +	ubo_offsets = gen_code.uniform_offsets; +	texture_uniforms = gen_code.texture_uniforms; + +	//update pipelines + +	pipeline = RD::get_singleton()->compute_pipeline_create(particles_storage->particles_shader.shader.version_get_shader(version, 0)); + +	valid = true; +} + +void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +	if (!p_texture.is_valid()) { +		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { +			default_texture_params[p_name].erase(p_index); + +			if (default_texture_params[p_name].is_empty()) { +				default_texture_params.erase(p_name); +			} +		} +	} else { +		if (!default_texture_params.has(p_name)) { +			default_texture_params[p_name] = Map<int, RID>(); +		} +		default_texture_params[p_name][p_index] = p_texture; +	} +} + +void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +	Map<int, StringName> order; + +	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { +		if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { +			continue; +		} + +		if (E.value.texture_order >= 0) { +			order[E.value.texture_order + 100000] = E.key; +		} else { +			order[E.value.order] = E.key; +		} +	} + +	for (const KeyValue<int, StringName> &E : order) { +		PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); +		pi.name = E.value; +		p_param_list->push_back(pi); +	} +} + +void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { +	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { +		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { +			continue; +		} + +		RendererMaterialStorage::InstanceShaderParam p; +		p.info = ShaderLanguage::uniform_to_property_info(E.value); +		p.info.name = E.key; //supply name +		p.index = E.value.instance_index; +		p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); +		p_param_list->push_back(p); +	} +} + +bool ParticlesStorage::ParticlesShaderData::is_param_texture(const StringName &p_param) const { +	if (!uniforms.has(p_param)) { +		return false; +	} + +	return uniforms[p_param].texture_order >= 0; +} + +bool ParticlesStorage::ParticlesShaderData::is_animated() const { +	return false; +} + +bool ParticlesStorage::ParticlesShaderData::casts_shadows() const { +	return false; +} + +Variant ParticlesStorage::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const { +	if (uniforms.has(p_parameter)) { +		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; +		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; +		return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); +	} +	return Variant(); +} + +RS::ShaderNativeSourceCode ParticlesStorage::ParticlesShaderData::get_native_source_code() const { +	return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version); +} + +ParticlesStorage::ParticlesShaderData::ParticlesShaderData() { +	valid = false; +} + +ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() { +	//pipeline variants will clear themselves if shader is gone +	if (version.is_valid()) { +		ParticlesStorage::get_singleton()->particles_shader.shader.version_free(version); +	} +} + +ShaderData *ParticlesStorage::_create_particles_shader_func() { +	ParticlesShaderData *shader_data = memnew(ParticlesShaderData); +	return shader_data; +} + +bool ParticlesStorage::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); +} + +ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() { +	free_parameters_uniform_set(uniform_set); +} + +MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { +	ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); +	material_data->shader_data = p_shader; +	//update will happen later anyway so do nothing. +	return material_data; +} +//////// + +/* PARTICLES COLLISION API */ + +RID ParticlesStorage::particles_collision_allocate() { +	return particles_collision_owner.allocate_rid(); +} +void ParticlesStorage::particles_collision_initialize(RID p_rid) { +	particles_collision_owner.initialize_rid(p_rid, ParticlesCollision()); +} + +void ParticlesStorage::particles_collision_free(RID p_rid) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid); + +	if (particles_collision->heightfield_texture.is_valid()) { +		RD::get_singleton()->free(particles_collision->heightfield_texture); +	} +	particles_collision->dependency.deleted_notify(p_rid); +	particles_collision_owner.free(p_rid); +} + +RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND_V(!particles_collision, RID()); +	ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID()); + +	if (particles_collision->heightfield_texture == RID()) { +		//create +		int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 }; +		Size2i size; +		if (particles_collision->extents.x > particles_collision->extents.z) { +			size.x = resolutions[particles_collision->heightfield_resolution]; +			size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x); +		} else { +			size.y = resolutions[particles_collision->heightfield_resolution]; +			size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y); +		} + +		RD::TextureFormat tf; +		tf.format = RD::DATA_FORMAT_D32_SFLOAT; +		tf.width = size.x; +		tf.height = size.y; +		tf.texture_type = RD::TEXTURE_TYPE_2D; +		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + +		particles_collision->heightfield_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + +		Vector<RID> fb_tex; +		fb_tex.push_back(particles_collision->heightfield_texture); +		particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex); +		particles_collision->heightfield_fb_size = size; +	} + +	return particles_collision->heightfield_fb; +} + +void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	if (p_type == particles_collision->type) { +		return; +	} + +	if (particles_collision->heightfield_texture.is_valid()) { +		RD::get_singleton()->free(particles_collision->heightfield_texture); +		particles_collision->heightfield_texture = RID(); +	} +	particles_collision->type = p_type; +	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); +	particles_collision->cull_mask = p_cull_mask; +} + +void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	particles_collision->radius = p_radius; +	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	particles_collision->extents = p_extents; +	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	particles_collision->attractor_strength = p_strength; +} + +void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	particles_collision->attractor_directionality = p_directionality; +} + +void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	particles_collision->attractor_attenuation = p_curve; +} + +void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); + +	particles_collision->field_texture = p_texture; +} + +void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); +	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); +} + +void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND(!particles_collision); +	ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX); + +	if (particles_collision->heightfield_resolution == p_resolution) { +		return; +	} + +	particles_collision->heightfield_resolution = p_resolution; + +	if (particles_collision->heightfield_texture.is_valid()) { +		RD::get_singleton()->free(particles_collision->heightfield_texture); +		particles_collision->heightfield_texture = RID(); +	} +} + +AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const { +	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND_V(!particles_collision, AABB()); + +	switch (particles_collision->type) { +		case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: +		case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: { +			AABB aabb; +			aabb.position = -Vector3(1, 1, 1) * particles_collision->radius; +			aabb.size = Vector3(2, 2, 2) * particles_collision->radius; +			return aabb; +		} +		default: { +			AABB aabb; +			aabb.position = -particles_collision->extents; +			aabb.size = particles_collision->extents * 2; +			return aabb; +		} +	} + +	return AABB(); +} + +Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const { +	const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND_V(!particles_collision, Vector3()); +	return particles_collision->extents; +} + +bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const { +	const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); +	ERR_FAIL_COND_V(!particles_collision, false); +	return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE; +} + +RID ParticlesStorage::particles_collision_instance_create(RID p_collision) { +	ParticlesCollisionInstance pci; +	pci.collision = p_collision; +	return particles_collision_instance_owner.make_rid(pci); +} + +void ParticlesStorage::particles_collision_instance_free(RID p_rid) { +	particles_collision_instance_owner.free(p_rid); +} + +void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) { +	ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance); +	ERR_FAIL_COND(!pci); +	pci->transform = p_transform; +} + +void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { +	ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance); +	ERR_FAIL_COND(!pci); +	pci->active = p_active; +} diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h new file mode 100644 index 0000000000..7764af08f2 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -0,0 +1,565 @@ +/*************************************************************************/ +/*  particles_storage.h                                                  */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#ifndef PARTICLES_STORAGE_RD_H +#define PARTICLES_STORAGE_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering/shader_compiler.h" +#include "servers/rendering/storage/particles_storage.h" + +namespace RendererRD { + +/* PARTICLES */ + +struct ParticleData { +	float xform[16]; +	float velocity[3]; +	uint32_t active; +	float color[4]; +	float custom[3]; +	float lifetime; +}; + +struct ParticlesFrameParams { +	enum { +		MAX_ATTRACTORS = 32, +		MAX_COLLIDERS = 32, +		MAX_3D_TEXTURES = 7 +	}; + +	enum AttractorType { +		ATTRACTOR_TYPE_SPHERE, +		ATTRACTOR_TYPE_BOX, +		ATTRACTOR_TYPE_VECTOR_FIELD, +	}; + +	struct Attractor { +		float transform[16]; +		float extents[3]; //exents or radius +		uint32_t type; + +		uint32_t texture_index; //texture index for vector field +		float strength; +		float attenuation; +		float directionality; +	}; + +	enum CollisionType { +		COLLISION_TYPE_SPHERE, +		COLLISION_TYPE_BOX, +		COLLISION_TYPE_SDF, +		COLLISION_TYPE_HEIGHT_FIELD, +		COLLISION_TYPE_2D_SDF, + +	}; + +	struct Collider { +		float transform[16]; +		float extents[3]; //exents or radius +		uint32_t type; + +		uint32_t texture_index; //texture index for vector field +		real_t scale; +		uint32_t pad[2]; +	}; + +	uint32_t emitting; +	float system_phase; +	float prev_system_phase; +	uint32_t cycle; + +	real_t explosiveness; +	real_t randomness; +	float time; +	float delta; + +	uint32_t frame; +	uint32_t pad0; +	uint32_t pad1; +	uint32_t pad2; + +	uint32_t random_seed; +	uint32_t attractor_count; +	uint32_t collider_count; +	float particle_size; + +	float emission_transform[16]; + +	Attractor attractors[MAX_ATTRACTORS]; +	Collider colliders[MAX_COLLIDERS]; +}; + +struct ParticleEmissionBufferData { +}; + +struct ParticleEmissionBuffer { +	struct Data { +		float xform[16]; +		float velocity[3]; +		uint32_t flags; +		float color[4]; +		float custom[4]; +	}; + +	int32_t particle_count; +	int32_t particle_max; +	uint32_t pad1; +	uint32_t pad2; +	Data data[1]; //its 2020 and empty arrays are still non standard in C++ +}; + +struct Particles { +	RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; +	bool inactive = true; +	double inactive_time = 0.0; +	bool emitting = false; +	bool one_shot = false; +	int amount = 0; +	double lifetime = 1.0; +	double pre_process_time = 0.0; +	real_t explosiveness = 0.0; +	real_t randomness = 0.0; +	bool restart_request = false; +	AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); +	bool use_local_coords = true; +	bool has_collision_cache = false; + +	bool has_sdf_collision = false; +	Transform2D sdf_collision_transform; +	Rect2 sdf_collision_to_screen; +	RID sdf_collision_texture; + +	RID process_material; +	uint32_t frame_counter = 0; +	RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; + +	RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; + +	Vector<RID> draw_passes; +	Vector<Transform3D> trail_bind_poses; +	bool trail_bind_poses_dirty = false; +	RID trail_bind_pose_buffer; +	RID trail_bind_pose_uniform_set; + +	RID particle_buffer; +	RID particle_instance_buffer; +	RID frame_params_buffer; + +	uint32_t userdata_count = 0; + +	RID particles_material_uniform_set; +	RID particles_copy_uniform_set; +	RID particles_transforms_buffer_uniform_set; +	RID collision_textures_uniform_set; + +	RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; +	uint32_t collision_3d_textures_used = 0; +	RID collision_heightmap_texture; + +	RID particles_sort_buffer; +	RID particles_sort_uniform_set; + +	bool dirty = false; +	Particles *update_list = nullptr; + +	RID sub_emitter; + +	double phase = 0.0; +	double prev_phase = 0.0; +	uint64_t prev_ticks = 0; +	uint32_t random_seed = 0; + +	uint32_t cycle_number = 0; + +	double speed_scale = 1.0; + +	int fixed_fps = 30; +	bool interpolate = true; +	bool fractional_delta = false; +	double frame_remainder = 0; +	real_t collision_base_size = 0.01; + +	bool clear = true; + +	bool force_sub_emit = false; + +	Transform3D emission_transform; + +	Vector<uint8_t> emission_buffer_data; + +	ParticleEmissionBuffer *emission_buffer = nullptr; +	RID emission_storage_buffer; + +	Set<RID> collisions; + +	RendererStorage::Dependency dependency; + +	double trail_length = 1.0; +	bool trails_enabled = false; +	LocalVector<ParticlesFrameParams> frame_history; +	LocalVector<ParticlesFrameParams> trail_params; + +	Particles() { +	} +}; + +/* Particles Collision */ + +struct ParticlesCollision { +	RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; +	uint32_t cull_mask = 0xFFFFFFFF; +	float radius = 1.0; +	Vector3 extents = Vector3(1, 1, 1); +	float attractor_strength = 1.0; +	float attractor_attenuation = 1.0; +	float attractor_directionality = 0.0; +	RID field_texture; +	RID heightfield_texture; +	RID heightfield_fb; +	Size2i heightfield_fb_size; + +	RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; + +	RendererStorage::Dependency dependency; +}; + +struct ParticlesCollisionInstance { +	RID collision; +	Transform3D transform; +	bool active = false; +}; + +class ParticlesStorage : public RendererParticlesStorage { +private: +	static ParticlesStorage *singleton; + +	/* PARTICLES */ + +	void _particles_process(Particles *p_particles, double p_delta); +	void _particles_allocate_emission_buffer(Particles *particles); +	void _particles_free_data(Particles *particles); +	void _particles_update_buffers(Particles *particles); + +	struct ParticlesShader { +		struct PushConstant { +			float lifetime; +			uint32_t clear; +			uint32_t total_particles; +			uint32_t trail_size; + +			uint32_t use_fractional_delta; +			uint32_t sub_emitter_mode; +			uint32_t can_emit; +			uint32_t trail_pass; +		}; + +		ParticlesShaderRD shader; +		ShaderCompiler compiler; + +		RID default_shader; +		RID default_material; +		RID default_shader_rd; + +		RID base_uniform_set; + +		struct CopyPushConstant { +			float sort_direction[3]; +			uint32_t total_particles; + +			uint32_t trail_size; +			uint32_t trail_total; +			float frame_delta; +			float frame_remainder; + +			float align_up[3]; +			uint32_t align_mode; + +			uint32_t order_by_lifetime; +			uint32_t lifetime_split; +			uint32_t lifetime_reverse; +			uint32_t copy_mode_2d; + +			float inv_emission_transform[16]; +		}; + +		enum { +			MAX_USERDATAS = 6 +		}; +		enum { +			COPY_MODE_FILL_INSTANCES, +			COPY_MODE_FILL_SORT_BUFFER, +			COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER, +			COPY_MODE_MAX, +		}; + +		ParticlesCopyShaderRD copy_shader; +		RID copy_shader_version; +		RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)]; + +		LocalVector<float> pose_update_buffer; + +	} particles_shader; + +	Particles *particle_update_list = nullptr; + +	mutable RID_Owner<Particles, true> particles_owner; + +	/* Particle Shader */ + +	struct ParticlesShaderData : public ShaderData { +		bool valid; +		RID version; +		bool uses_collision = false; + +		//PipelineCacheRD pipelines[SKY_VERSION_MAX]; +		Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; +		Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; + +		Vector<uint32_t> ubo_offsets; +		uint32_t ubo_size; + +		String path; +		String code; +		Map<StringName, Map<int, RID>> default_texture_params; + +		RID pipeline; + +		bool uses_time = false; + +		bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {}; +		uint32_t userdata_count = 0; + +		virtual void set_code(const String &p_Code); +		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); +		virtual void get_param_list(List<PropertyInfo> *p_param_list) const; +		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; +		virtual bool is_param_texture(const StringName &p_param) const; +		virtual bool is_animated() const; +		virtual bool casts_shadows() const; +		virtual Variant get_default_parameter(const StringName &p_parameter) const; +		virtual RS::ShaderNativeSourceCode get_native_source_code() const; + +		ParticlesShaderData(); +		virtual ~ParticlesShaderData(); +	}; + +	ShaderData *_create_particles_shader_func(); +	static ShaderData *_create_particles_shader_funcs() { +		return ParticlesStorage::get_singleton()->_create_particles_shader_func(); +	} + +	struct ParticlesMaterialData : public MaterialData { +		ParticlesShaderData *shader_data = nullptr; +		RID uniform_set; + +		virtual void set_render_priority(int p_priority) {} +		virtual void set_next_pass(RID p_pass) {} +		virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); +		virtual ~ParticlesMaterialData(); +	}; + +	MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); +	static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { +		return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); +	} + +	/* Particles Collision */ + +	mutable RID_Owner<ParticlesCollision, true> particles_collision_owner; + +	mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; + +public: +	static ParticlesStorage *get_singleton(); + +	ParticlesStorage(); +	virtual ~ParticlesStorage(); + +	/* PARTICLES */ + +	Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); } +	bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } + +	virtual RID particles_allocate() override; +	virtual void particles_initialize(RID p_particles_collision) override; +	virtual void particles_free(RID p_rid) override; + +	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; +	virtual void particles_set_emitting(RID p_particles, bool p_emitting) override; +	virtual void particles_set_amount(RID p_particles, int p_amount) override; +	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override; +	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override; +	virtual void particles_set_pre_process_time(RID p_particles, double p_time) override; +	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override; +	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override; +	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override; +	virtual void particles_set_speed_scale(RID p_particles, double p_scale) override; +	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override; +	virtual void particles_set_process_material(RID p_particles, RID p_material) override; +	virtual RID particles_get_process_material(RID p_particles) const override; + +	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override; +	virtual void particles_set_interpolate(RID p_particles, bool p_enable) override; +	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override; +	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override; +	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override; + +	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override; +	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override; + +	virtual void particles_restart(RID p_particles) override; +	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override; + +	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override; + +	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override; + +	virtual void particles_set_draw_passes(RID p_particles, int p_count) override; +	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override; + +	virtual void particles_request_process(RID p_particles) override; +	virtual AABB particles_get_current_aabb(RID p_particles) override; +	virtual AABB particles_get_aabb(RID p_particles) const override; + +	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override; + +	virtual bool particles_get_emitting(RID p_particles) override; +	virtual int particles_get_draw_passes(RID p_particles) const override; +	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override; + +	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override; + +	virtual bool particles_is_inactive(RID p_particles) const override; + +	_FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) { +		Particles *particles = particles_owner.get_or_null(p_particles); +		ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D); +		return particles->mode; +	} + +	_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) { +		Particles *particles = particles_owner.get_or_null(p_particles); +		ERR_FAIL_COND_V(!particles, 0); + +		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { +			r_trail_divisor = particles->trail_bind_poses.size(); +		} else { +			r_trail_divisor = 1; +		} + +		return particles->amount * r_trail_divisor; +	} + +	_FORCE_INLINE_ bool particles_has_collision(RID p_particles) { +		Particles *particles = particles_owner.get_or_null(p_particles); +		ERR_FAIL_COND_V(!particles, 0); + +		return particles->has_collision_cache; +	} + +	_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) { +		Particles *particles = particles_owner.get_or_null(p_particles); +		ERR_FAIL_COND_V(!particles, false); + +		return particles->use_local_coords; +	} + +	_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) { +		Particles *particles = particles_owner.get_or_null(p_particles); +		ERR_FAIL_COND_V(!particles, RID()); +		if (particles->particles_transforms_buffer_uniform_set.is_null()) { +			_particles_update_buffers(particles); + +			Vector<RD::Uniform> uniforms; + +			{ +				RD::Uniform u; +				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +				u.binding = 0; +				u.append_id(particles->particle_instance_buffer); +				uniforms.push_back(u); +			} + +			particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); +		} + +		return particles->particles_transforms_buffer_uniform_set; +	} + +	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override; +	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override; +	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override; + +	virtual void update_particles() override; + +	/* Particles Collision */ + +	ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); } +	bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); } + +	virtual RID particles_collision_allocate() override; +	virtual void particles_collision_initialize(RID p_particles_collision) override; +	virtual void particles_collision_free(RID p_rid) override; + +	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override; +	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override; +	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; //for spheres +	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; //for non-spheres +	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override; +	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override; +	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override; +	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; //for SDF and vector field, heightfield is dynamic +	virtual void particles_collision_height_field_update(RID p_particles_collision) override; //for SDF and vector field +	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; //for SDF and vector field +	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override; +	Vector3 particles_collision_get_extents(RID p_particles_collision) const; +	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; +	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; + +	//used from 2D and 3D +	ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); } +	bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); } + +	virtual RID particles_collision_instance_create(RID p_collision) override; +	virtual void particles_collision_instance_free(RID p_rid) override; +	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override; +	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override; +}; + +} // namespace RendererRD + +#endif // !PARTICLES_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index f87c5d6156..3b52a187f6 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -470,7 +470,7 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:  }  bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { -	RendererStorageRD *storage = RendererStorageRD::base_singleton; +	MaterialStorage *material_storage = MaterialStorage::get_singleton();  	CanvasTexture *ct = nullptr;  	Texture *t = get_texture(p_texture); @@ -552,7 +552,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;  			u.binding = 3; -			u.append_id(storage->sampler_rd_get_default(filter, repeat)); +			u.append_id(material_storage->sampler_rd_get_default(filter, repeat));  			uniforms.push_back(u);  		} diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index ef9530041d..55193a45f0 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -228,7 +228,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {  		voxel_gi->lights.insert(A);  	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {  		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data); -		RSG::storage->particles_add_collision(A->base, collision->instance); +		RSG::particles_storage->particles_add_collision(A->base, collision->instance);  	}  } @@ -344,7 +344,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {  		voxel_gi->lights.erase(A);  	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {  		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data); -		RSG::storage->particles_remove_collision(A->base, collision->instance); +		RSG::particles_storage->particles_remove_collision(A->base, collision->instance);  	}  } @@ -659,8 +659,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {  			} break;  			case RS::INSTANCE_PARTICLES_COLLISION: {  				InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData); -				collision->instance = RSG::storage->particles_collision_instance_create(p_base); -				RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible); +				collision->instance = RSG::particles_storage->particles_collision_instance_create(p_base); +				RSG::particles_storage->particles_collision_instance_set_active(collision->instance, instance->visible);  				instance->base_data = collision;  			} break;  			case RS::INSTANCE_FOG_VOLUME: { @@ -941,7 +941,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {  	if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {  		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data); -		RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible); +		RSG::particles_storage->particles_collision_instance_set_active(collision->instance, p_visible);  	}  	if (instance->base_type == RS::INSTANCE_FOG_VOLUME) { @@ -1529,15 +1529,15 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {  		scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, p_instance->transform);  	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { -		RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); +		RSG::particles_storage->particles_set_emission_transform(p_instance->base, p_instance->transform);  	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {  		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);  		//remove materials no longer used and un-own them -		if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) { +		if (RSG::particles_storage->particles_collision_is_heightfield(p_instance->base)) {  			heightfield_particle_colliders_update_list.insert(p_instance);  		} -		RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform); +		RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);  	} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {  		InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);  		scene_render->fog_volume_instance_set_transform(volume->instance, p_instance->transform); @@ -1864,12 +1864,12 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {  			if (p_instance->custom_aabb) {  				new_aabb = *p_instance->custom_aabb;  			} else { -				new_aabb = RSG::storage->particles_get_aabb(p_instance->base); +				new_aabb = RSG::particles_storage->particles_get_aabb(p_instance->base);  			}  		} break;  		case RenderingServer::INSTANCE_PARTICLES_COLLISION: { -			new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base); +			new_aabb = RSG::particles_storage->particles_collision_get_aabb(p_instance->base);  		} break;  		case RenderingServer::INSTANCE_FOG_VOLUME: { @@ -2714,14 +2714,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul  						mesh_visible = true;  					} else if (base_type == RS::INSTANCE_PARTICLES) {  						//particles visible? process them -						if (RSG::storage->particles_is_inactive(idata.base_rid)) { +						if (RSG::particles_storage->particles_is_inactive(idata.base_rid)) {  							//but if nothing is going on, don't do it.  							keep = false;  						} else {  							cull_data.cull->lock.lock(); -							RSG::storage->particles_request_process(idata.base_rid); +							RSG::particles_storage->particles_request_process(idata.base_rid);  							cull_data.cull->lock.unlock(); -							RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized()); +							RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());  							//particles visible? request redraw  							RenderingServerDefault::redraw_request();  						} @@ -3592,7 +3592,7 @@ void RendererSceneCull::render_particle_colliders() {  	while (heightfield_particle_colliders_update_list.front()) {  		Instance *hfpc = heightfield_particle_colliders_update_list.front()->get(); -		if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) { +		if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::particles_storage->particles_collision_is_heightfield(hfpc->base)) {  			//update heightfield  			instance_cull_result.clear();  			scene_cull_result.geometry_instances.clear(); @@ -3686,7 +3686,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {  		if (p_instance->base_type == RS::INSTANCE_PARTICLES) {  			// update the process material dependency -			RID particle_material = RSG::storage->particles_get_process_material(p_instance->base); +			RID particle_material = RSG::particles_storage->particles_get_process_material(p_instance->base);  			if (particle_material.is_valid()) {  				RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);  			} @@ -3776,10 +3776,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {  				} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {  					bool cast_shadows = false; -					int dp = RSG::storage->particles_get_draw_passes(p_instance->base); +					int dp = RSG::particles_storage->particles_get_draw_passes(p_instance->base);  					for (int i = 0; i < dp; i++) { -						RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); +						RID mesh = RSG::particles_storage->particles_get_draw_pass_mesh(p_instance->base, i);  						if (!mesh.is_valid()) {  							continue;  						} diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 49e7cd4f5e..ab7dbb87a3 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -163,84 +163,6 @@ public:  	virtual uint32_t voxel_gi_get_version(RID p_probe) = 0; -	/* PARTICLES */ - -	virtual RID particles_allocate() = 0; -	virtual void particles_initialize(RID p_rid) = 0; -	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0; - -	virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; -	virtual bool particles_get_emitting(RID p_particles) = 0; - -	virtual void particles_set_amount(RID p_particles, int p_amount) = 0; -	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0; -	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; -	virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0; -	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0; -	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0; -	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; -	virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0; -	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; -	virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; -	virtual RID particles_get_process_material(RID p_particles) const = 0; -	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; -	virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0; -	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; -	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0; - -	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0; - -	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0; -	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0; - -	virtual void particles_restart(RID p_particles) = 0; -	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0; -	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0; - -	virtual bool particles_is_inactive(RID p_particles) const = 0; - -	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0; - -	virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; -	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; - -	virtual void particles_request_process(RID p_particles) = 0; -	virtual AABB particles_get_current_aabb(RID p_particles) = 0; -	virtual AABB particles_get_aabb(RID p_particles) const = 0; - -	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; - -	virtual int particles_get_draw_passes(RID p_particles) const = 0; -	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; - -	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0; - -	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0; -	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0; - -	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0; - -	virtual void update_particles() = 0; - -	/* PARTICLES COLLISION */ - -	virtual RID particles_collision_allocate() = 0; -	virtual void particles_collision_initialize(RID p_rid) = 0; - -	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0; -	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0; -	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres -	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres -	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0; -	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0; -	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0; -	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic -	virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field -	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field -	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0; -	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0; -	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0; -  	/* FOG VOLUMES */  	virtual RID fog_volume_allocate() = 0; @@ -262,11 +184,6 @@ public:  	virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;  	virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0; -	//used from 2D and 3D -	virtual RID particles_collision_instance_create(RID p_collision) = 0; -	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0; -	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0; -  	virtual RS::InstanceType get_base_type(RID p_rid) const = 0;  	virtual bool free(RID p_rid) = 0; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index de626092b1..e42034dbb9 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -84,7 +84,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {  	frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0; -	RSG::storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered +	RSG::particles_storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered  	RSG::scene->render_probes(); @@ -401,6 +401,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :  	RSG::light_storage = RSG::rasterizer->get_light_storage();  	RSG::material_storage = RSG::rasterizer->get_material_storage();  	RSG::mesh_storage = RSG::rasterizer->get_mesh_storage(); +	RSG::particles_storage = RSG::rasterizer->get_particles_storage();  	RSG::texture_storage = RSG::rasterizer->get_texture_storage();  	RSG::storage = RSG::rasterizer->get_storage();  	RSG::canvas_render = RSG::rasterizer->get_canvas(); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 8e9dda34de..8dfb5985f8 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -459,6 +459,12 @@ public:  	/* PARTICLES */ +#undef ServerName +#undef server_name + +#define ServerName RendererParticlesStorage +#define server_name RSG::particles_storage +  	FUNCRIDSPLIT(particles)  	FUNC2(particles_set_mode, RID, ParticlesMode) @@ -514,6 +520,12 @@ public:  	/* FOG VOLUME */ +#undef ServerName +#undef server_name + +#define ServerName RendererStorage +#define server_name RSG::storage +  	FUNCRIDSPLIT(fog_volume)  	FUNC2(fog_volume_set_shape, RID, FogVolumeShape) diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index 6bc38d654e..4d24dbf3b4 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -35,6 +35,7 @@ bool RenderingServerGlobals::threaded = false;  RendererLightStorage *RenderingServerGlobals::light_storage = nullptr;  RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;  RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr; +RendererParticlesStorage *RenderingServerGlobals::particles_storage = nullptr;  RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;  RendererStorage *RenderingServerGlobals::storage = nullptr;  RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index f01e9b3bf4..ce11fae9e8 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -37,6 +37,7 @@  #include "servers/rendering/storage/light_storage.h"  #include "servers/rendering/storage/material_storage.h"  #include "servers/rendering/storage/mesh_storage.h" +#include "servers/rendering/storage/particles_storage.h"  #include "servers/rendering/storage/texture_storage.h"  class RendererCanvasCull; @@ -50,6 +51,7 @@ public:  	static RendererLightStorage *light_storage;  	static RendererMaterialStorage *material_storage;  	static RendererMeshStorage *mesh_storage; +	static RendererParticlesStorage *particles_storage;  	static RendererTextureStorage *texture_storage;  	static RendererStorage *storage;  	static RendererCanvasRender *canvas_render; diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h new file mode 100644 index 0000000000..268b5473e2 --- /dev/null +++ b/servers/rendering/storage/particles_storage.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/*  particles_storage.h                                                  */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#ifndef PARTICLES_STORAGE_H +#define PARTICLES_STORAGE_H + +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering_server.h" + +class RendererParticlesStorage { +public: +	virtual ~RendererParticlesStorage() {} + +	/* PARTICLES */ + +	virtual RID particles_allocate() = 0; +	virtual void particles_initialize(RID p_rid) = 0; +	virtual void particles_free(RID p_rid) = 0; + +	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0; + +	virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; +	virtual bool particles_get_emitting(RID p_particles) = 0; + +	virtual void particles_set_amount(RID p_particles, int p_amount) = 0; +	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0; +	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; +	virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0; +	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0; +	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0; +	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; +	virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0; +	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; +	virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; +	virtual RID particles_get_process_material(RID p_particles) const = 0; +	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; +	virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0; +	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; +	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0; + +	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0; + +	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0; +	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0; + +	virtual void particles_restart(RID p_particles) = 0; +	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0; +	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0; + +	virtual bool particles_is_inactive(RID p_particles) const = 0; + +	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0; + +	virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; +	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; + +	virtual void particles_request_process(RID p_particles) = 0; +	virtual AABB particles_get_current_aabb(RID p_particles) = 0; +	virtual AABB particles_get_aabb(RID p_particles) const = 0; + +	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; + +	virtual int particles_get_draw_passes(RID p_particles) const = 0; +	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; + +	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0; + +	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0; +	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0; + +	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0; + +	virtual void update_particles() = 0; + +	/* PARTICLES COLLISION */ + +	virtual RID particles_collision_allocate() = 0; +	virtual void particles_collision_initialize(RID p_rid) = 0; +	virtual void particles_collision_free(RID p_rid) = 0; + +	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0; +	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0; +	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres +	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres +	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0; +	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0; +	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0; +	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic +	virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field +	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field +	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0; +	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0; +	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0; + +	//used from 2D and 3D +	virtual RID particles_collision_instance_create(RID p_collision) = 0; +	virtual void particles_collision_instance_free(RID p_rid) = 0; +	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0; +	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0; +}; + +#endif // !PARTICLES_STORAGE_H  |