From 67cdbde243f3d7588994d790dcd30c28e6fcde0d Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Thu, 3 Feb 2022 04:35:01 +0100
Subject: [PATCH] Using MLS MPM to combine shaders and reduce sources of errors

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 projects/wobble_bobble/shaders/particle.inc   |  1 +
 .../shaders/transform_particles_to_grid.comp  |  6 ++
 .../shaders/update_grid_forces.comp           | 58 +-------------
 .../shaders/update_particle_deformation.comp  | 64 ---------------
 .../shaders/update_particle_positions.comp    | 51 ------------
 .../shaders/update_particle_velocities.comp   | 65 +++++++++++----
 projects/wobble_bobble/src/main.cpp           | 80 ++-----------------
 7 files changed, 66 insertions(+), 259 deletions(-)
 delete mode 100644 projects/wobble_bobble/shaders/update_particle_deformation.comp
 delete mode 100644 projects/wobble_bobble/shaders/update_particle_positions.comp

diff --git a/projects/wobble_bobble/shaders/particle.inc b/projects/wobble_bobble/shaders/particle.inc
index 595db9ab..77d2691e 100644
--- a/projects/wobble_bobble/shaders/particle.inc
+++ b/projects/wobble_bobble/shaders/particle.inc
@@ -14,6 +14,7 @@ struct ParticleMinimal {
 struct Particle {
     ParticleMinimal minimal;
     mat4 deformation;
+	mat4 mls;
 };
 
 const float PI = 3.1415926535897932384626433832795;
diff --git a/projects/wobble_bobble/shaders/transform_particles_to_grid.comp b/projects/wobble_bobble/shaders/transform_particles_to_grid.comp
index 9bae58ef..69154658 100644
--- a/projects/wobble_bobble/shaders/transform_particles_to_grid.comp
+++ b/projects/wobble_bobble/shaders/transform_particles_to_grid.comp
@@ -27,6 +27,12 @@ void main()	{
 
         if (localOffset < particles.length()) {
             shared_particles[gl_LocalInvocationIndex] = particles[localOffset].minimal;
+
+            vec3 distance = (position - shared_particles[gl_LocalInvocationIndex].position);
+
+            shared_particles[gl_LocalInvocationIndex].velocity += (
+                mat3(particles[localOffset].mls) * distance
+            );
         } else {
             shared_particles[gl_LocalInvocationIndex].position = vec3(0.0f);
             shared_particles[gl_LocalInvocationIndex].size = 0.0f;
diff --git a/projects/wobble_bobble/shaders/update_grid_forces.comp b/projects/wobble_bobble/shaders/update_grid_forces.comp
index 7db54625..9c0d0c07 100644
--- a/projects/wobble_bobble/shaders/update_grid_forces.comp
+++ b/projects/wobble_bobble/shaders/update_grid_forces.comp
@@ -14,6 +14,8 @@ layout(set=0, binding=2, std430) readonly buffer particleBuffer {
 layout( push_constant ) uniform constants {
     float lame1;
     float lame2;
+    float alpha;
+    float beta;
     float t;
     float dt;
 };
@@ -41,63 +43,11 @@ void main()	{
     vec3 velocity = gridSample.xyz;
     float mass = gridSample.w;
 
-    vec3 force = vec3(0.0f);
-    uint offset = 0;
-
     barrier();
     memoryBarrierBuffer();
 
-    for (offset = 0; offset < particles.length(); offset += SHARED_PARTICLES_BATCH_SIZE) {
-        uint localOffset = offset + gl_LocalInvocationIndex;
-
-        if (localOffset < particles.length()) {
-            shared_particles[gl_LocalInvocationIndex] = particles[localOffset];
-        } else {
-            shared_particles[gl_LocalInvocationIndex].minimal.position = vec3(0.0f);
-            shared_particles[gl_LocalInvocationIndex].minimal.size = 0.0f;
-            shared_particles[gl_LocalInvocationIndex].minimal.velocity = vec3(0.0f);
-            shared_particles[gl_LocalInvocationIndex].minimal.mass = 0.0f;
-            shared_particles[gl_LocalInvocationIndex].deformation = mat4(0.0f);
-        }
-
-        barrier();
-        memoryBarrierShared();
-
-        for (uint i = 0; i < SHARED_PARTICLES_BATCH_SIZE; i++) {
-            float volume = sphere_volume(shared_particles[i].minimal.size);
-            mat3 F = mat3(shared_particles[i].deformation);
-
-            float J = determinant(F);
-
-            if ((J > 0.0f) && (volume > 0.0f)) {
-                mat3 F_invT = inverse(transpose(F));
-
-                vec3 v = shared_particles[i].minimal.velocity;
-                float m = shared_particles[i].minimal.mass;
-
-                mat3 delta = lame2 * (F - F_invT) + lame1 * log(J) * F_invT;
-
-                vec3 weight_gradient = voxel_particle_grad_weight(
-                    position,
-                    shared_particles[i].minimal
-                );
-
-                force -= (
-                    volume *
-                    delta * transpose(F) *
-                    weight_gradient
-                );
-            }
-        }
-
-        barrier();
-        memoryBarrierShared();
-    }
-
-    if (dt > 0.0f) {
-        if (mass > 0.0f) {
-            velocity += force * dt / mass;
-        }
+    if (mass > 0.0f) {
+        velocity += vec3(0.0f, -9.81f * dt * 0.0f, 0.0f);
     }
 
     bvec3 lowerID = lessThanEqual(gl_GlobalInvocationID, ivec3(0));
diff --git a/projects/wobble_bobble/shaders/update_particle_deformation.comp b/projects/wobble_bobble/shaders/update_particle_deformation.comp
deleted file mode 100644
index a8a89bc5..00000000
--- a/projects/wobble_bobble/shaders/update_particle_deformation.comp
+++ /dev/null
@@ -1,64 +0,0 @@
-#version 450
-#extension GL_GOOGLE_include_directive : enable
-
-layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
-
-#include "particle.inc"
-
-layout(set=0, binding=0, std430) restrict buffer particleBuffer {
-    Particle particles [];
-};
-
-layout(set=0, binding=1) uniform texture3D gridImage;
-layout(set=0, binding=2) uniform sampler gridSampler;
-
-layout( push_constant ) uniform constants {
-    float K;
-    float E;
-    float t;
-    float dt;
-};
-
-void main()	{
-    if (gl_GlobalInvocationID.x < particles.length()) {
-        ParticleMinimal minimal = particles[gl_GlobalInvocationID.x].minimal;
-        mat3 deformation = mat3(particles[gl_GlobalInvocationID.x].deformation);
-
-        ivec3 gridResolution = textureSize(sampler3D(gridImage, gridSampler), 0);
-        ivec3 gridWindow = ivec3(minimal.size * 2.0f * gridResolution);
-
-        mat3 velocity_gradient = mat3(0.0f);
-
-        int i, j, k;
-
-        for (i = -gridWindow.x; i <= gridWindow.x; i++) {
-            for (j = -gridWindow.y; j <= gridWindow.y; j++) {
-                for (k = -gridWindow.z; k <= gridWindow.z; k++) {
-                    vec3 offset = vec3(i, j, k) / gridResolution;
-                    vec3 voxel = minimal.position + offset;
-
-                    vec4 gridSample = texture(sampler3D(gridImage, gridSampler), voxel);
-
-                    velocity_gradient += outerProduct(
-                        gridSample.xyz,
-                        voxel_particle_grad_weight(voxel, minimal)
-                    );
-                }
-            }
-        }
-
-        barrier();
-        memoryBarrierBuffer();
-
-        mat3 deformation_elastic = deformation;
-
-        if (dt > 0.0f) {
-            deformation_elastic = (mat3(1.0f) + dt * velocity_gradient) * deformation;
-        }
-
-        barrier();
-        memoryBarrierBuffer();
-
-        particles[gl_GlobalInvocationID.x].deformation = mat4(deformation_elastic);
-    }
-}
\ No newline at end of file
diff --git a/projects/wobble_bobble/shaders/update_particle_positions.comp b/projects/wobble_bobble/shaders/update_particle_positions.comp
deleted file mode 100644
index 5e012f40..00000000
--- a/projects/wobble_bobble/shaders/update_particle_positions.comp
+++ /dev/null
@@ -1,51 +0,0 @@
-#version 450
-#extension GL_GOOGLE_include_directive : enable
-
-layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
-
-#include "particle.inc"
-
-layout(set=0, binding=0, std430) restrict buffer particleBuffer {
-    Particle particles [];
-};
-
-layout( push_constant ) uniform constants {
-    float K;
-    float E;
-    float t;
-    float dt;
-};
-
-void main()	{
-    memoryBarrierBuffer();
-
-    if (gl_GlobalInvocationID.x < particles.length()) {
-        vec3 position = particles[gl_GlobalInvocationID.x].minimal.position;
-        float size = particles[gl_GlobalInvocationID.x].minimal.size;
-        vec3 velocity = particles[gl_GlobalInvocationID.x].minimal.velocity;
-
-        if (dt > 0.0f) {
-            position = position + velocity * dt;
-        }
-
-        for (uint i = 0; i < 3; i++) {
-            if (position[i] - size < 0.0f) {
-                position[i] = -position[i] + 2.0f * size;
-                velocity[i] *= -1.0f;
-            } else
-            if (position[i] + size > 1.0f) {
-                position[i] = 2.0f * (1.0f - size) - position[i];
-                velocity[i] *= -1.0f;
-            }
-        }
-
-        barrier();
-        memoryBarrierBuffer();
-
-        particles[gl_GlobalInvocationID.x].minimal.position = position;
-        particles[gl_GlobalInvocationID.x].minimal.velocity = velocity;
-    }
-
-    barrier();
-    memoryBarrierBuffer();
-}
\ No newline at end of file
diff --git a/projects/wobble_bobble/shaders/update_particle_velocities.comp b/projects/wobble_bobble/shaders/update_particle_velocities.comp
index d29b22e1..e8d671e5 100644
--- a/projects/wobble_bobble/shaders/update_particle_velocities.comp
+++ b/projects/wobble_bobble/shaders/update_particle_velocities.comp
@@ -15,8 +15,12 @@ layout(set=0, binding=2) uniform texture3D gridOldImage;
 layout(set=0, binding=3) uniform sampler gridSampler;
 
 layout( push_constant ) uniform constants {
+    float lame1;
+    float lame2;
     float alpha;
     float beta;
+    float t;
+    float dt;
 };
 
 void main()	{
@@ -24,16 +28,21 @@ void main()	{
     memoryBarrierImage();
 
     if (gl_GlobalInvocationID.x < particles.length()) {
-        ParticleMinimal minimal = particles[gl_GlobalInvocationID.x].minimal;
+        Particle particle = particles[gl_GlobalInvocationID.x];
+
+        vec3 position = particle.minimal.position;
+        float size = particle.minimal.size;
+        float volume = sphere_volume(size);
+        float mass = particle.minimal.mass;
 
         ivec3 gridResolution = textureSize(sampler3D(gridImage, gridSampler), 0);
-        ivec3 gridWindow = ivec3(minimal.size * 2.0f * gridResolution);
+        ivec3 gridWindow = ivec3(size * 2.0f * gridResolution);
 
         mat3 affine_D = mat3(0.0f);
         mat3 affine_B = mat3(0.0f);
 
         vec3 velocity_pic = vec3(0.0f);
-        vec3 velocity_flip = vec3(minimal.velocity);
+        vec3 velocity_flip = vec3(particle.minimal.velocity);
 
         int i, j, k;
 
@@ -41,12 +50,12 @@ void main()	{
             for (j = -gridWindow.y; j <= gridWindow.y; j++) {
                 for (k = -gridWindow.z; k <= gridWindow.z; k++) {
                     vec3 offset = vec3(i, j, k) / gridResolution;
-                    vec3 voxel = minimal.position + offset;
+                    vec3 voxel = position + offset;
 
                     vec4 gridSample = texture(sampler3D(gridImage, gridSampler), voxel);
                     vec4 gridOldSample = texture(sampler3D(gridOldImage, gridSampler), voxel);
 
-                    float weight = voxel_particle_weight(voxel, minimal);
+                    float weight = voxel_particle_weight(voxel, particle.minimal);
                     vec3 velocity = gridSample.xyz * weight;
 
                     affine_D += outerProduct(weight * offset, offset);
@@ -61,30 +70,52 @@ void main()	{
         barrier();
         memoryBarrierBuffer();
 
+        mat3 mls_Q = mat3(0.0f);
         mat3 affine_C = mat3(0.0f);
-        vec3 velocity_apic = vec3(0.0f);
+
+        mat3 F = mat3(particle.deformation);
 
         if (abs(determinant(affine_D)) > 0.0f) {
-            affine_C = affine_B * inverse(affine_D);
+            mat3 D_inv = inverse(affine_D);
+            float J = determinant(F);
+
+            if ((J > 0.0f) && (mass > 0.0f)) {
+                mat3 F_T = transpose(F);
+                mat3 F_invT = inverse(F_T);
+
+                mat3 delta = lame2 * (F - F_invT) + lame1 * log(J) * F_invT;
+
+                //mls_Q += beta * dt * volume * particle.minimal.weight_sum * delta * F_T * D_inv / mass;
+            }
+
+            affine_C = affine_B * D_inv;
+            mls_Q += beta * affine_C;
         }
 
-        for (i = -gridWindow.x; i <= gridWindow.x; i++) {
-            for (j = -gridWindow.y; j <= gridWindow.y; j++) {
-                for (k = -gridWindow.z; k <= gridWindow.z; k++) {
-                    vec3 offset = vec3(i, j, k) / gridResolution;
+        F = (mat3(1.0f) + dt * affine_C) * F;
 
-                    velocity_apic += affine_C * offset;
-                }
+        vec3 velocity = mix(velocity_pic, velocity_flip, alpha);
+
+        position = position + velocity * dt;
+
+        for (uint i = 0; i < 3; i++) {
+            if (position[i] - size < 0.0f) {
+                position[i] = -position[i] + 2.0f * size;
+                velocity[i] *= -1.0f;
+            } else
+            if (position[i] + size > 1.0f) {
+                position[i] = 2.0f * (1.0f - size) - position[i];
+                velocity[i] *= -1.0f;
             }
         }
 
         barrier();
         memoryBarrierBuffer();
 
-        vec3 velocity_alpha = mix(velocity_pic, velocity_flip, alpha);
-        vec3 velocity_beta = mix(velocity_alpha, velocity_apic, beta);
-
-        particles[gl_GlobalInvocationID.x].minimal.velocity = velocity_beta;
+        particles[gl_GlobalInvocationID.x].minimal.position = position;
+        particles[gl_GlobalInvocationID.x].minimal.velocity = velocity;
+        particles[gl_GlobalInvocationID.x].deformation = mat4(F);
+        particles[gl_GlobalInvocationID.x].mls = mat4(mls_Q);
     }
 
     barrier();
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index fab2ae31..9f41267a 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -17,18 +17,16 @@ struct Particle {
 	float weight_sum;
 	
 	glm::mat4 deformation;
+	glm::mat4 mls;
 };
 
 struct Physics {
 	float lame1;
     float lame2;
-	float t;
-	float dt;
-};
-
-struct Tweaks {
 	float alpha;
 	float beta;
+	float t;
+	float dt;
 };
 
 float sphere_volume(float radius) {
@@ -80,6 +78,8 @@ void distributeParticles(Particle *particles, size_t count, const glm::vec3& cen
 		
 		particles[i].pad = glm::vec3(0.0f);
 		particles[i].weight_sum = 1.0f;
+		
+		particles[i].mls = glm::mat4(0.0f);
 	}
 }
 
@@ -268,21 +268,6 @@ int main(int argc, const char **argv) {
 		core.writeDescriptorSet(updateGridForcesSets[0], writes);
 	}
 	
-	std::vector<vkcv::DescriptorSetHandle> updateParticleDeformationSets;
-	vkcv::ComputePipelineHandle updateParticleDeformationPipeline = createComputePipeline(
-			core, compiler,
-			"shaders/update_particle_deformation.comp",
-			updateParticleDeformationSets
-	);
-	
-	{
-		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particles.getHandle()));
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(1, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(2, gridSampler));
-		core.writeDescriptorSet(updateParticleDeformationSets[0], writes);
-	}
-	
 	std::vector<vkcv::DescriptorSetHandle> updateParticleVelocitiesSets;
 	vkcv::ComputePipelineHandle updateParticleVelocitiesPipeline = createComputePipeline(
 			core, compiler,
@@ -299,19 +284,6 @@ int main(int argc, const char **argv) {
 		core.writeDescriptorSet(updateParticleVelocitiesSets[0], writes);
 	}
 	
-	std::vector<vkcv::DescriptorSetHandle> updateParticlePositionsSets;
-	vkcv::ComputePipelineHandle updateParticlePositionsPipeline = createComputePipeline(
-			core, compiler,
-			"shaders/update_particle_positions.comp",
-			updateParticlePositionsSets
-	);
-	
-	{
-		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particles.getHandle()));
-		core.writeDescriptorSet(updateParticlePositionsSets[0], writes);
-	}
-	
 	vkcv::ShaderProgram gfxProgramGrid;
 	
 	compiler.compile(
@@ -600,19 +572,14 @@ int main(int argc, const char **argv) {
 		Physics physics;
 		physics.lame1 = material.m_lame1;
 		physics.lame2 = material.m_lame2;
+		physics.alpha = alpha;
+		physics.beta = beta;
 		physics.t = static_cast<float>(0.000001 * static_cast<double>(time.count()));
 		physics.dt = static_cast<float>(0.000001 * static_cast<double>(deltatime.count()));
 		
 		vkcv::PushConstants physicsPushConstants (sizeof(physics));
 		physicsPushConstants.appendDrawcall(physics);
 		
-		Tweaks tweaks;
-		tweaks.alpha = alpha;
-		tweaks.beta = beta;
-		
-		vkcv::PushConstants tweakPushConstants (sizeof(tweaks));
-		tweakPushConstants.appendDrawcall(tweaks);
-		
 		cameraManager.update(physics.dt);
 
 		glm::mat4 mvp = cameraManager.getActiveCamera().getMVP();
@@ -676,23 +643,6 @@ int main(int argc, const char **argv) {
 		core.recordImageMemoryBarrier(cmdStream, grid.getHandle());
 		core.recordEndDebugLabel(cmdStream);
 		
-		core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE DEFORMATION", { 0.78f, 0.89f, 0.94f, 1.0f });
-		core.recordBufferMemoryBarrier(cmdStream, particles.getHandle());
-		core.prepareImageForSampling(cmdStream, grid.getHandle());
-		
-		core.recordComputeDispatchToCmdStream(
-				cmdStream,
-				updateParticleDeformationPipeline,
-				dispatchSizeParticles,
-				{ vkcv::DescriptorSetUsage(
-						0, core.getDescriptorSet(updateParticleDeformationSets[0]).vulkanHandle
-				) },
-				physicsPushConstants
-		);
-		
-		core.recordBufferMemoryBarrier(cmdStream, particles.getHandle());
-		core.recordEndDebugLabel(cmdStream);
-		
 		core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE VELOCITIES", { 0.78f, 0.89f, 0.94f, 1.0f });
 		core.recordBufferMemoryBarrier(cmdStream, particles.getHandle());
 		core.prepareImageForSampling(cmdStream, grid.getHandle());
@@ -705,22 +655,6 @@ int main(int argc, const char **argv) {
 				{ vkcv::DescriptorSetUsage(
 						0, core.getDescriptorSet(updateParticleVelocitiesSets[0]).vulkanHandle
 				) },
-				tweakPushConstants
-		);
-		
-		core.recordBufferMemoryBarrier(cmdStream, particles.getHandle());
-		core.recordEndDebugLabel(cmdStream);
-		
-		core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE POSITIONS", { 0.78f, 0.89f, 0.94f, 1.0f });
-		core.recordBufferMemoryBarrier(cmdStream, particles.getHandle());
-		
-		core.recordComputeDispatchToCmdStream(
-				cmdStream,
-				updateParticlePositionsPipeline,
-				dispatchSizeParticles,
-				{ vkcv::DescriptorSetUsage(
-						0, core.getDescriptorSet(updateParticlePositionsSets[0]).vulkanHandle
-				) },
 				physicsPushConstants
 		);
 		
-- 
GitLab