| 1 | /**************************************************************************/ |
| 2 | /* particles_storage.h */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #ifndef PARTICLES_STORAGE_RD_H |
| 32 | #define PARTICLES_STORAGE_RD_H |
| 33 | |
| 34 | #include "core/templates/local_vector.h" |
| 35 | #include "core/templates/rid_owner.h" |
| 36 | #include "core/templates/self_list.h" |
| 37 | #include "servers/rendering/renderer_rd/effects/sort_effects.h" |
| 38 | #include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" |
| 39 | #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" |
| 40 | #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" |
| 41 | #include "servers/rendering/shader_compiler.h" |
| 42 | #include "servers/rendering/storage/particles_storage.h" |
| 43 | #include "servers/rendering/storage/utilities.h" |
| 44 | |
| 45 | namespace RendererRD { |
| 46 | |
| 47 | class ParticlesStorage : public RendererParticlesStorage { |
| 48 | private: |
| 49 | static ParticlesStorage *singleton; |
| 50 | |
| 51 | /* EFFECTS */ |
| 52 | SortEffects *sort_effects = nullptr; |
| 53 | |
| 54 | /* PARTICLES */ |
| 55 | |
| 56 | enum { |
| 57 | BASE_UNIFORM_SET, |
| 58 | MATERIAL_UNIFORM_SET, |
| 59 | COLLISION_TEXTURTES_UNIFORM_SET, |
| 60 | }; |
| 61 | |
| 62 | const int SAMPLERS_BINDING_FIRST_INDEX = 3; |
| 63 | |
| 64 | struct ParticleData { |
| 65 | float xform[16]; |
| 66 | float velocity[3]; |
| 67 | uint32_t active; |
| 68 | float color[4]; |
| 69 | float custom[4]; |
| 70 | }; |
| 71 | |
| 72 | struct ParticlesFrameParams { |
| 73 | enum { |
| 74 | MAX_ATTRACTORS = 32, |
| 75 | MAX_COLLIDERS = 32, |
| 76 | MAX_3D_TEXTURES = 7 |
| 77 | }; |
| 78 | |
| 79 | enum AttractorType { |
| 80 | ATTRACTOR_TYPE_SPHERE, |
| 81 | ATTRACTOR_TYPE_BOX, |
| 82 | ATTRACTOR_TYPE_VECTOR_FIELD, |
| 83 | }; |
| 84 | |
| 85 | struct Attractor { |
| 86 | float transform[16]; |
| 87 | float extents[3]; //exents or radius |
| 88 | uint32_t type; |
| 89 | |
| 90 | uint32_t texture_index; //texture index for vector field |
| 91 | float strength; |
| 92 | float attenuation; |
| 93 | float directionality; |
| 94 | }; |
| 95 | |
| 96 | enum CollisionType { |
| 97 | COLLISION_TYPE_SPHERE, |
| 98 | COLLISION_TYPE_BOX, |
| 99 | COLLISION_TYPE_SDF, |
| 100 | COLLISION_TYPE_HEIGHT_FIELD, |
| 101 | COLLISION_TYPE_2D_SDF, |
| 102 | |
| 103 | }; |
| 104 | |
| 105 | struct Collider { |
| 106 | float transform[16]; |
| 107 | float extents[3]; //exents or radius |
| 108 | uint32_t type; |
| 109 | |
| 110 | uint32_t texture_index; //texture index for vector field |
| 111 | float scale; |
| 112 | uint32_t pad[2]; |
| 113 | }; |
| 114 | |
| 115 | uint32_t emitting; |
| 116 | float system_phase; |
| 117 | float prev_system_phase; |
| 118 | uint32_t cycle; |
| 119 | |
| 120 | float explosiveness; |
| 121 | float randomness; |
| 122 | float time; |
| 123 | float delta; |
| 124 | |
| 125 | uint32_t frame; |
| 126 | uint32_t pad0; |
| 127 | uint32_t pad1; |
| 128 | uint32_t pad2; |
| 129 | |
| 130 | uint32_t random_seed; |
| 131 | uint32_t attractor_count; |
| 132 | uint32_t collider_count; |
| 133 | float particle_size; |
| 134 | |
| 135 | float emission_transform[16]; |
| 136 | |
| 137 | Attractor attractors[MAX_ATTRACTORS]; |
| 138 | Collider colliders[MAX_COLLIDERS]; |
| 139 | }; |
| 140 | |
| 141 | struct ParticleEmissionBuffer { |
| 142 | struct Data { |
| 143 | float xform[16]; |
| 144 | float velocity[3]; |
| 145 | uint32_t flags; |
| 146 | float color[4]; |
| 147 | float custom[4]; |
| 148 | }; |
| 149 | |
| 150 | int32_t particle_count; |
| 151 | int32_t particle_max; |
| 152 | uint32_t pad1; |
| 153 | uint32_t pad2; |
| 154 | Data data[1]; //its 2020 and empty arrays are still non standard in C++ |
| 155 | }; |
| 156 | |
| 157 | struct Particles { |
| 158 | RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; |
| 159 | bool inactive = true; |
| 160 | double inactive_time = 0.0; |
| 161 | bool emitting = false; |
| 162 | bool one_shot = false; |
| 163 | int amount = 0; |
| 164 | double lifetime = 1.0; |
| 165 | double pre_process_time = 0.0; |
| 166 | real_t explosiveness = 0.0; |
| 167 | real_t randomness = 0.0; |
| 168 | bool restart_request = false; |
| 169 | AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); |
| 170 | bool use_local_coords = false; |
| 171 | bool has_collision_cache = false; |
| 172 | |
| 173 | bool has_sdf_collision = false; |
| 174 | Transform2D sdf_collision_transform; |
| 175 | Rect2 sdf_collision_to_screen; |
| 176 | RID sdf_collision_texture; |
| 177 | |
| 178 | RID process_material; |
| 179 | uint32_t frame_counter = 0; |
| 180 | RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; |
| 181 | |
| 182 | RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; |
| 183 | |
| 184 | Vector<RID> draw_passes; |
| 185 | Vector<Transform3D> trail_bind_poses; |
| 186 | bool trail_bind_poses_dirty = false; |
| 187 | RID trail_bind_pose_buffer; |
| 188 | RID trail_bind_pose_uniform_set; |
| 189 | |
| 190 | RID particle_buffer; |
| 191 | RID particle_instance_buffer; |
| 192 | RID frame_params_buffer; |
| 193 | |
| 194 | uint32_t userdata_count = 0; |
| 195 | |
| 196 | RID particles_material_uniform_set; |
| 197 | RID particles_copy_uniform_set; |
| 198 | RID particles_transforms_buffer_uniform_set; |
| 199 | RID collision_textures_uniform_set; |
| 200 | |
| 201 | RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; |
| 202 | uint32_t collision_3d_textures_used = 0; |
| 203 | RID collision_heightmap_texture; |
| 204 | |
| 205 | RID particles_sort_buffer; |
| 206 | RID particles_sort_uniform_set; |
| 207 | |
| 208 | bool dirty = false; |
| 209 | Particles *update_list = nullptr; |
| 210 | |
| 211 | RID sub_emitter; |
| 212 | |
| 213 | double phase = 0.0; |
| 214 | double prev_phase = 0.0; |
| 215 | uint64_t prev_ticks = 0; |
| 216 | uint32_t random_seed = 0; |
| 217 | |
| 218 | uint32_t cycle_number = 0; |
| 219 | |
| 220 | double speed_scale = 1.0; |
| 221 | |
| 222 | int fixed_fps = 30; |
| 223 | bool interpolate = true; |
| 224 | bool fractional_delta = false; |
| 225 | double frame_remainder = 0; |
| 226 | real_t collision_base_size = 0.01; |
| 227 | |
| 228 | uint32_t instance_motion_vectors_current_offset = 0; |
| 229 | uint32_t instance_motion_vectors_previous_offset = 0; |
| 230 | uint64_t instance_motion_vectors_last_change = -1; |
| 231 | bool instance_motion_vectors_enabled = false; |
| 232 | |
| 233 | bool clear = true; |
| 234 | |
| 235 | bool force_sub_emit = false; |
| 236 | |
| 237 | Transform3D emission_transform; |
| 238 | |
| 239 | Vector<uint8_t> emission_buffer_data; |
| 240 | |
| 241 | ParticleEmissionBuffer *emission_buffer = nullptr; |
| 242 | RID emission_storage_buffer; |
| 243 | |
| 244 | HashSet<RID> collisions; |
| 245 | |
| 246 | Dependency dependency; |
| 247 | |
| 248 | double trail_lifetime = 0.3; |
| 249 | bool trails_enabled = false; |
| 250 | LocalVector<ParticlesFrameParams> frame_history; |
| 251 | LocalVector<ParticlesFrameParams> trail_params; |
| 252 | |
| 253 | Particles() { |
| 254 | } |
| 255 | }; |
| 256 | |
| 257 | void _particles_process(Particles *p_particles, double p_delta); |
| 258 | void _particles_allocate_emission_buffer(Particles *particles); |
| 259 | void _particles_free_data(Particles *particles); |
| 260 | void _particles_update_buffers(Particles *particles); |
| 261 | |
| 262 | struct ParticlesShader { |
| 263 | struct PushConstant { |
| 264 | float lifetime; |
| 265 | uint32_t clear; |
| 266 | uint32_t total_particles; |
| 267 | uint32_t trail_size; |
| 268 | |
| 269 | uint32_t use_fractional_delta; |
| 270 | uint32_t sub_emitter_mode; |
| 271 | uint32_t can_emit; |
| 272 | uint32_t trail_pass; |
| 273 | }; |
| 274 | |
| 275 | ParticlesShaderRD shader; |
| 276 | ShaderCompiler compiler; |
| 277 | |
| 278 | RID default_shader; |
| 279 | RID default_material; |
| 280 | RID default_shader_rd; |
| 281 | |
| 282 | RID base_uniform_set; |
| 283 | |
| 284 | struct CopyPushConstant { |
| 285 | float sort_direction[3]; |
| 286 | uint32_t total_particles; |
| 287 | |
| 288 | uint32_t trail_size; |
| 289 | uint32_t trail_total; |
| 290 | float frame_delta; |
| 291 | float frame_remainder; |
| 292 | |
| 293 | float align_up[3]; |
| 294 | uint32_t align_mode; |
| 295 | |
| 296 | uint32_t lifetime_split; |
| 297 | uint32_t lifetime_reverse; |
| 298 | uint32_t motion_vectors_current_offset; |
| 299 | struct { |
| 300 | uint32_t order_by_lifetime : 1; |
| 301 | uint32_t copy_mode_2d : 1; |
| 302 | }; |
| 303 | |
| 304 | float inv_emission_transform[16]; |
| 305 | }; |
| 306 | |
| 307 | enum { |
| 308 | MAX_USERDATAS = 6 |
| 309 | }; |
| 310 | enum { |
| 311 | COPY_MODE_FILL_INSTANCES, |
| 312 | COPY_MODE_FILL_SORT_BUFFER, |
| 313 | COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER, |
| 314 | COPY_MODE_MAX, |
| 315 | }; |
| 316 | |
| 317 | ParticlesCopyShaderRD copy_shader; |
| 318 | RID copy_shader_version; |
| 319 | RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)]; |
| 320 | |
| 321 | LocalVector<float> pose_update_buffer; |
| 322 | |
| 323 | } particles_shader; |
| 324 | |
| 325 | Particles *particle_update_list = nullptr; |
| 326 | |
| 327 | mutable RID_Owner<Particles, true> particles_owner; |
| 328 | |
| 329 | /* Particle Shader */ |
| 330 | |
| 331 | struct ParticlesShaderData : public MaterialStorage::ShaderData { |
| 332 | bool valid = false; |
| 333 | RID version; |
| 334 | bool uses_collision = false; |
| 335 | |
| 336 | Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; |
| 337 | |
| 338 | Vector<uint32_t> ubo_offsets; |
| 339 | uint32_t ubo_size = 0; |
| 340 | |
| 341 | String code; |
| 342 | |
| 343 | RID pipeline; |
| 344 | |
| 345 | bool uses_time = false; |
| 346 | |
| 347 | bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {}; |
| 348 | uint32_t userdata_count = 0; |
| 349 | |
| 350 | virtual void set_code(const String &p_Code); |
| 351 | virtual bool is_animated() const; |
| 352 | virtual bool casts_shadows() const; |
| 353 | virtual RS::ShaderNativeSourceCode get_native_source_code() const; |
| 354 | |
| 355 | ParticlesShaderData() {} |
| 356 | virtual ~ParticlesShaderData(); |
| 357 | }; |
| 358 | |
| 359 | MaterialStorage::ShaderData *_create_particles_shader_func(); |
| 360 | static MaterialStorage::ShaderData *_create_particles_shader_funcs() { |
| 361 | return ParticlesStorage::get_singleton()->_create_particles_shader_func(); |
| 362 | } |
| 363 | |
| 364 | struct ParticleProcessMaterialData : public MaterialStorage::MaterialData { |
| 365 | ParticlesShaderData *shader_data = nullptr; |
| 366 | RID uniform_set; |
| 367 | |
| 368 | virtual void set_render_priority(int p_priority) {} |
| 369 | virtual void set_next_pass(RID p_pass) {} |
| 370 | virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); |
| 371 | virtual ~ParticleProcessMaterialData(); |
| 372 | }; |
| 373 | |
| 374 | MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); |
| 375 | static MaterialStorage::MaterialData *_create_particles_material_funcs(MaterialStorage::ShaderData *p_shader) { |
| 376 | return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); |
| 377 | } |
| 378 | |
| 379 | /* Particles Collision */ |
| 380 | |
| 381 | struct ParticlesCollision { |
| 382 | RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; |
| 383 | uint32_t cull_mask = 0xFFFFFFFF; |
| 384 | float radius = 1.0; |
| 385 | Vector3 extents = Vector3(1, 1, 1); |
| 386 | float attractor_strength = 1.0; |
| 387 | float attractor_attenuation = 1.0; |
| 388 | float attractor_directionality = 0.0; |
| 389 | RID field_texture; |
| 390 | RID heightfield_texture; |
| 391 | RID heightfield_fb; |
| 392 | Size2i heightfield_fb_size; |
| 393 | |
| 394 | RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; |
| 395 | |
| 396 | Dependency dependency; |
| 397 | }; |
| 398 | |
| 399 | struct ParticlesCollisionInstance { |
| 400 | RID collision; |
| 401 | Transform3D transform; |
| 402 | bool active = false; |
| 403 | }; |
| 404 | |
| 405 | mutable RID_Owner<ParticlesCollision, true> particles_collision_owner; |
| 406 | |
| 407 | mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; |
| 408 | |
| 409 | public: |
| 410 | static ParticlesStorage *get_singleton(); |
| 411 | |
| 412 | ParticlesStorage(); |
| 413 | virtual ~ParticlesStorage(); |
| 414 | |
| 415 | bool free(RID p_rid); |
| 416 | |
| 417 | /* PARTICLES */ |
| 418 | |
| 419 | bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } |
| 420 | |
| 421 | virtual RID particles_allocate() override; |
| 422 | virtual void particles_initialize(RID p_rid) override; |
| 423 | virtual void particles_free(RID p_rid) override; |
| 424 | |
| 425 | virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; |
| 426 | virtual void particles_set_emitting(RID p_particles, bool p_emitting) override; |
| 427 | virtual void particles_set_amount(RID p_particles, int p_amount) override; |
| 428 | virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override; |
| 429 | virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override; |
| 430 | virtual void particles_set_pre_process_time(RID p_particles, double p_time) override; |
| 431 | virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override; |
| 432 | virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override; |
| 433 | virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override; |
| 434 | virtual void particles_set_speed_scale(RID p_particles, double p_scale) override; |
| 435 | virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override; |
| 436 | virtual void particles_set_process_material(RID p_particles, RID p_material) override; |
| 437 | virtual RID particles_get_process_material(RID p_particles) const override; |
| 438 | |
| 439 | virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override; |
| 440 | virtual void particles_set_interpolate(RID p_particles, bool p_enable) override; |
| 441 | virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override; |
| 442 | virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override; |
| 443 | virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override; |
| 444 | |
| 445 | virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override; |
| 446 | virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override; |
| 447 | |
| 448 | virtual void particles_restart(RID p_particles) override; |
| 449 | 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; |
| 450 | |
| 451 | virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override; |
| 452 | |
| 453 | virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override; |
| 454 | |
| 455 | virtual void particles_set_draw_passes(RID p_particles, int p_count) override; |
| 456 | virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override; |
| 457 | |
| 458 | virtual void particles_request_process(RID p_particles) override; |
| 459 | virtual AABB particles_get_current_aabb(RID p_particles) override; |
| 460 | virtual AABB particles_get_aabb(RID p_particles) const override; |
| 461 | |
| 462 | virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override; |
| 463 | |
| 464 | virtual bool particles_get_emitting(RID p_particles) override; |
| 465 | virtual int particles_get_draw_passes(RID p_particles) const override; |
| 466 | virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override; |
| 467 | |
| 468 | virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override; |
| 469 | |
| 470 | virtual bool particles_is_inactive(RID p_particles) const override; |
| 471 | |
| 472 | _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) { |
| 473 | Particles *particles = particles_owner.get_or_null(p_particles); |
| 474 | ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D); |
| 475 | return particles->mode; |
| 476 | } |
| 477 | |
| 478 | _FORCE_INLINE_ uint32_t particles_get_frame_counter(RID p_particles) { |
| 479 | Particles *particles = particles_owner.get_or_null(p_particles); |
| 480 | ERR_FAIL_COND_V(!particles, false); |
| 481 | return particles->frame_counter; |
| 482 | } |
| 483 | |
| 484 | _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) { |
| 485 | Particles *particles = particles_owner.get_or_null(p_particles); |
| 486 | ERR_FAIL_COND_V(!particles, 0); |
| 487 | |
| 488 | if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { |
| 489 | r_trail_divisor = particles->trail_bind_poses.size(); |
| 490 | } else { |
| 491 | r_trail_divisor = 1; |
| 492 | } |
| 493 | |
| 494 | return particles->amount * r_trail_divisor; |
| 495 | } |
| 496 | |
| 497 | _FORCE_INLINE_ bool particles_has_collision(RID p_particles) { |
| 498 | Particles *particles = particles_owner.get_or_null(p_particles); |
| 499 | ERR_FAIL_COND_V(!particles, 0); |
| 500 | |
| 501 | return particles->has_collision_cache; |
| 502 | } |
| 503 | |
| 504 | _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) { |
| 505 | Particles *particles = particles_owner.get_or_null(p_particles); |
| 506 | ERR_FAIL_COND_V(!particles, false); |
| 507 | |
| 508 | return particles->use_local_coords; |
| 509 | } |
| 510 | |
| 511 | _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) { |
| 512 | Particles *particles = particles_owner.get_or_null(p_particles); |
| 513 | ERR_FAIL_COND_V(!particles, RID()); |
| 514 | if (particles->particles_transforms_buffer_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(particles->particles_transforms_buffer_uniform_set)) { |
| 515 | _particles_update_buffers(particles); |
| 516 | Vector<RD::Uniform> uniforms; |
| 517 | |
| 518 | { |
| 519 | RD::Uniform u; |
| 520 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 521 | u.binding = 0; |
| 522 | u.append_id(particles->particle_instance_buffer); |
| 523 | uniforms.push_back(u); |
| 524 | } |
| 525 | |
| 526 | particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); |
| 527 | } |
| 528 | |
| 529 | return particles->particles_transforms_buffer_uniform_set; |
| 530 | } |
| 531 | |
| 532 | void particles_get_instance_buffer_motion_vectors_offsets(RID p_particles, uint32_t &r_current_offset, uint32_t &r_prev_offset); |
| 533 | |
| 534 | virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override; |
| 535 | virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override; |
| 536 | void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture); |
| 537 | |
| 538 | virtual void update_particles() override; |
| 539 | |
| 540 | void particles_update_dependency(RID p_particles, DependencyTracker *p_instance); |
| 541 | Dependency *particles_get_dependency(RID p_particles) const; |
| 542 | |
| 543 | /* Particles Collision */ |
| 544 | |
| 545 | bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); } |
| 546 | |
| 547 | virtual RID particles_collision_allocate() override; |
| 548 | virtual void particles_collision_initialize(RID p_particles_collision) override; |
| 549 | virtual void particles_collision_free(RID p_rid) override; |
| 550 | |
| 551 | virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override; |
| 552 | virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override; |
| 553 | virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; //for spheres |
| 554 | virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; //for non-spheres |
| 555 | virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override; |
| 556 | virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override; |
| 557 | virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override; |
| 558 | virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; //for SDF and vector field, heightfield is dynamic |
| 559 | virtual void particles_collision_height_field_update(RID p_particles_collision) override; //for SDF and vector field |
| 560 | virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; //for SDF and vector field |
| 561 | virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override; |
| 562 | Vector3 particles_collision_get_extents(RID p_particles_collision) const; |
| 563 | virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; |
| 564 | RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const; |
| 565 | |
| 566 | Dependency *particles_collision_get_dependency(RID p_particles) const; |
| 567 | |
| 568 | //used from 2D and 3D |
| 569 | bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); } |
| 570 | |
| 571 | virtual RID particles_collision_instance_create(RID p_collision) override; |
| 572 | virtual void particles_collision_instance_free(RID p_rid) override; |
| 573 | virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override; |
| 574 | virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override; |
| 575 | }; |
| 576 | |
| 577 | } // namespace RendererRD |
| 578 | |
| 579 | #endif // PARTICLES_STORAGE_RD_H |
| 580 | |