summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd/renderer_storage_rd.cpp
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2021-05-24 12:49:34 +0200
committerGitHub <noreply@github.com>2021-05-24 12:49:34 +0200
commit9cf1d034a7f08c37f3c7f4660c50c8784864daa3 (patch)
tree0cb583f7005b6ba13dfe83d95f24c9e78ed3f982 /servers/rendering/renderer_rd/renderer_storage_rd.cpp
parent08491ec5432577dffcaccda161df4cca8c141c30 (diff)
parent789713b00883e7c9d3a912d1b088441ab17c1244 (diff)
Merge pull request #48894 from reduz/gpu-particles-2d-2
Support for 2D particles to collide against SDF
Diffstat (limited to 'servers/rendering/renderer_rd/renderer_storage_rd.cpp')
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp85
1 files changed, 83 insertions, 2 deletions
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index f419875d58..26ddd74a80 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -4305,6 +4305,15 @@ void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_partic
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.getornull(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, float p_delta) {
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;
@@ -4410,6 +4419,50 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
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.getornull(E->get());
@@ -4657,6 +4710,8 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
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);
@@ -4740,6 +4795,11 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
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;
@@ -5019,6 +5079,10 @@ void RendererStorageRD::update_particles() {
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();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->mode == RS::PARTICLES_MODE_2D ? ParticlesShader::COPY_MODE_FILL_INSTANCES_2D : ParticlesShader::COPY_MODE_FILL_INSTANCES]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
@@ -5049,6 +5113,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
valid = false;
ubo_size = 0;
uniforms.clear();
+ uses_collision = false;
if (code == String()) {
return; //just invalid, but no error
@@ -5068,6 +5133,8 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
*/
+ actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
actions.uniforms = &uniforms;
Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
@@ -7133,6 +7200,20 @@ Rect2i RendererStorageRD::render_target_get_sdf_rect(RID p_render_target) const
return _render_target_get_sdf_rect(rt);
}
+void RendererStorageRD::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->sdf_enabled = p_enabled;
+}
+
+bool RendererStorageRD::render_target_is_sdf_enabled(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->sdf_enabled;
+}
+
RID RendererStorageRD::render_target_get_sdf_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
@@ -7200,7 +7281,7 @@ void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
rt->process_size.x = MAX(rt->process_size.x, 1);
rt->process_size.y = MAX(rt->process_size.y, 1);
- tformat.format = RD::DATA_FORMAT_R16G16_UINT;
+ tformat.format = RD::DATA_FORMAT_R16G16_SINT;
tformat.width = rt->process_size.width;
tformat.height = rt->process_size.height;
tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -7208,7 +7289,7 @@ void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- tformat.format = RD::DATA_FORMAT_R16_UNORM;
+ tformat.format = RD::DATA_FORMAT_R16_SNORM;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());