#version 450
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
struct InstanceData {
mat4 model;
vec4 color;
vec4 mat_props;
vec4 velocity;
vec4 angular_velocity;
vec4 physic_props;
};
layout(set = 0, binding = 0) buffer ReadBuf {
InstanceData data[];
} read_buf;
layout(set = 0, binding = 1) buffer WriteBuf {
InstanceData data[];
} write_buf;
layout(push_constant) uniform PushConstants {
float dt;
uint total_objects;
uint offset;
uint count;
uint num_big_objects;
uint _pad[3];
vec4 global_gravity;
} pc;
mat3 skew(vec3 v) {
return mat3(0.0, -v.z, v.y, v.z, 0.0, -v.x, -v.y, v.x, 0.0);
}
void main() {
uint i = gl_GlobalInvocationID.x + pc.offset;
if (i >= pc.offset + pc.count) return;
write_buf.data[i] = read_buf.data[i];
InstanceData me = read_buf.data[i];
vec3 pos = me.model[3].xyz;
vec3 vel = me.velocity.xyz;
vec3 ang_vel = me.angular_velocity.xyz;
float type = me.physic_props.x;
float mass = me.physic_props.y;
float gravity_scale = me.physic_props.z;
if (mass <= 0.0) return;
vel += pc.global_gravity.xyz * gravity_scale * pc.dt;
pos += vel * pc.dt;
vec3 scale = vec3(length(me.model[0].xyz), length(me.model[1].xyz), length(me.model[2].xyz));
vec3 half_extents = scale * 0.5;
mat3 rot = mat3(me.model[0].xyz / scale.x, me.model[1].xyz / scale.y, me.model[2].xyz / scale.z);
if (length(ang_vel) > 0.001) {
rot += skew(ang_vel) * rot * pc.dt;
vec3 c0 = normalize(rot[0]);
vec3 c1 = normalize(rot[1] - dot(c0, rot[1]) * c0);
vec3 c2 = cross(c0, c1);
rot = mat3(c0, c1, c2);
}
float lowest_y = (type > 0.5)
? scale.x
: (half_extents.x * abs(rot[0].y) + half_extents.y * abs(rot[1].y) + half_extents.z * abs(rot[2].y));
if (pos.y < lowest_y) {
pos.y = lowest_y;
if (vel.y < 0.0) {
vel.y *= -me.velocity.w;
float damping = clamp(1.0 - me.angular_velocity.w, 0.0, 1.0);
vel.xz *= damping;
ang_vel *= damping;
}
}
me.model[0] = vec4(rot[0] * scale.x, 0.0);
me.model[1] = vec4(rot[1] * scale.y, 0.0);
me.model[2] = vec4(rot[2] * scale.z, 0.0);
me.model[3].xyz = pos;
me.velocity.xyz = vel;
me.angular_velocity.xyz = ang_vel;
write_buf.data[i] = me;
}