Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPUParticles collisions shader code seems broken. Creates jittery bounces when bounce > 0.0 #65707

Closed
benbot opened this issue Sep 12, 2022 · 4 comments · Fixed by #65714
Closed

Comments

@benbot
Copy link

benbot commented Sep 12, 2022

Godot version

4.0.alpha15

System information

Arch Linux, Vulkan

Issue description

GPUParicles bounce is very jittery and doesn't respond well to collision_bounce being increased.

When checking the gdshader that was generated from the particle process resource, i noticed 2 different places where velocity was being calculated after a collision.

removing the 2nd one appeared to fix the issue, but made collision_friction affect the height of the bounce, which it probably shouldn't do.

Steps to reproduce

Create a GPUParticle3d node, rigid body, and height field

ensure that the rigid body is inside of the height field, but the particle emitter is not.

set the particle's collision mode to "rigid" and bounce to 1.0

observe the jittery behavior when the particles land on the rigid body

Minimal reproduction project

minimal.tar.gz

@benbot
Copy link
Author

benbot commented Sep 12, 2022

snipped from the generated shader.

    if (COLLIDED) {
        if (length(VELOCITY) > 3.0) {
            TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;
            VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * 2.0;
            VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));
        } else {
            VELOCITY = vec3(0.0);
        }
    }

// some code that scales TRANSFORM based on tex_scale (which is set to 1.0)

    if (COLLIDED) {
        TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;
        VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);
        VELOCITY = mix(VELOCITY,vec3(0.0), collision_friction * DELTA * 100.0);
    }

I poked around for a bit and found out that removing the 2nd if statement seemed to fix the issue for me.

Then @celyk proposed this which fixes some friction weirdness

if (COLLIDED) {
TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;
vec3 v = COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY);
VELOCITY -= v;
VELOCITY = mix(VELOCITY, vec3(0.0), collision_friction * DELTA);

@Calinou
Copy link
Member

Calinou commented Sep 12, 2022

Related to #57249 (possible duplicate?).

See #61245 which addresses this.

@Calinou Calinou added this to the 4.0 milestone Sep 12, 2022
@Calinou Calinou changed the title GPU Particle collisions shader code seems broken. Creates jittery bounces when bounce > 0.0 GPUParticles collisions shader code seems broken. Creates jittery bounces when bounce > 0.0 Sep 12, 2022
@benbot
Copy link
Author

benbot commented Sep 12, 2022

@Calinou I'm not sure this is addressed by #61246.
I'm seeing this strange jittery behavior even if i increase my projects framerate and the particle velocity.

@benbot
Copy link
Author

benbot commented Sep 12, 2022

This is the last ~25 lines of the result of converting the particle process into a gdshader.

	TRANSFORM[0].xyz = normalize(TRANSFORM[0].xyz);
	TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz);
	TRANSFORM[2].xyz = normalize(TRANSFORM[2].xyz);
	if (COLLIDED) {
		if (length(VELOCITY) > 3.0) {
			TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;
			VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);
			VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));
		} else {
			VELOCITY = vec3(0.0);
		}
	}
	float base_scale = mix(scale_min, scale_max, scale_rand);
	base_scale = sign(base_scale) * max(abs(base_scale), 0.001);
	TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);
	TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);
	TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);
	if (COLLIDED) {
		TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;
		VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);
		VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);
	}
	if (CUSTOM.y > CUSTOM.w) {
		ACTIVE = false;
	}

the collision_bounce and collision_friction calculations are being applied to the velocity twice.
Event at higher velocities and framerates, removing that 2nd if(COLLIDED) block seemed to resolve the issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants