From d6752ceb3ca7b05c384f3c330dddf73bb41bdb56 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Mon, 31 Jan 2022 01:14:04 +0100
Subject: [PATCH] Adjusted shaders to fix deformation

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 projects/wobble_bobble/shaders/grid.frag      |  2 +-
 projects/wobble_bobble/shaders/particle.inc   | 18 ++++----
 .../shaders/transform_particles_to_grid.comp  | 11 ++++-
 .../shaders/update_grid_forces.comp           | 42 ++++++++++-------
 .../shaders/update_particle_deformation.comp  | 46 +++++++++++++------
 .../shaders/update_particle_velocities.comp   | 11 +++--
 projects/wobble_bobble/src/main.cpp           | 30 ++++++++++--
 7 files changed, 109 insertions(+), 51 deletions(-)

diff --git a/projects/wobble_bobble/shaders/grid.frag b/projects/wobble_bobble/shaders/grid.frag
index 00c405d1..c3dc1fb2 100644
--- a/projects/wobble_bobble/shaders/grid.frag
+++ b/projects/wobble_bobble/shaders/grid.frag
@@ -19,7 +19,7 @@ void main()	{
         vec3 surface = vec3(passPos.x + 0.5f, passPos.y + 0.5f, z * 2.0f);
         vec3 velocity = vec3(0.5f) + 0.5f * normalize(passVelocity.xyz);
 
-        outColor = surface;
+        outColor = velocity;
     } else {
         discard;
     }
diff --git a/projects/wobble_bobble/shaders/particle.inc b/projects/wobble_bobble/shaders/particle.inc
index 6ce314ab..ae584f1a 100644
--- a/projects/wobble_bobble/shaders/particle.inc
+++ b/projects/wobble_bobble/shaders/particle.inc
@@ -41,14 +41,14 @@ float weight_C(float x) {
 	}
 }
 
-float voxel_particle_weight(vec3 voxel, ParticleMinimal particle) {
+vec3 voxel_particle_weight(vec3 voxel, ParticleMinimal particle) {
 	if (particle.size <= 0.0f) {
-		return 0.0f;
+		return vec3(0.0f);
 	}
 	
 	vec3 delta = abs(particle.position - voxel) / particle.size;
 	
-	return weight_C(delta.x) * weight_C(delta.y) * weight_C(delta.z);
+	return vec3(weight_C(delta.x), weight_C(delta.y), weight_C(delta.z));
 }
 
 float grad_weight_A(float x) {
@@ -78,9 +78,9 @@ float grad_weight_C(float x) {
 	}
 }
 
-float voxel_particle_grad_weight(vec3 voxel, ParticleMinimal particle) {
+vec3 voxel_particle_grad_weight(vec3 voxel, ParticleMinimal particle) {
 	if (particle.size <= 0.0f) {
-		return 0.0f;
+		return vec3(0.0f);
 	}
 	
 	vec3 sign_delta = (particle.position - voxel) / particle.size;
@@ -88,12 +88,12 @@ float voxel_particle_grad_weight(vec3 voxel, ParticleMinimal particle) {
 	vec3 sign = sign(sign_delta);
 	
 	vec3 weight = vec3(
-		weight_C(delta.x),
-		weight_C(delta.y),
-		weight_C(delta.z)
+		grad_weight_C(delta.x),
+		grad_weight_C(delta.y),
+		grad_weight_C(delta.z)
 	);
 	
-	return dot(weight, sign);
+	return weight * sign;
 }
 
 #endif // PARTICLE_INC
\ No newline at end of file
diff --git a/projects/wobble_bobble/shaders/transform_particles_to_grid.comp b/projects/wobble_bobble/shaders/transform_particles_to_grid.comp
index bfd902b5..d582986d 100644
--- a/projects/wobble_bobble/shaders/transform_particles_to_grid.comp
+++ b/projects/wobble_bobble/shaders/transform_particles_to_grid.comp
@@ -10,6 +10,7 @@ layout(set=0, binding=0, std430) buffer particleBuffer {
 };
 
 layout(set=0, binding=1, rgba32f) restrict writeonly uniform image3D gridImage;
+layout(set=0, binding=2, rgba32f) restrict writeonly uniform image3D gridCopyImage;
 
 #define SHARED_PARTICLES_BATCH_SIZE 64
 
@@ -38,9 +39,11 @@ void main()	{
         memoryBarrierShared();
 
         for (uint i = 0; i < SHARED_PARTICLES_BATCH_SIZE; i++) {
+            vec3 weight = voxel_particle_weight(position, shared_particles[i]);
+
             gridValue += (
                 vec4(shared_particles[i].velocity, shared_particles[i].mass) *
-                voxel_particle_weight(position, shared_particles[i])
+                weight.x * weight.y * weight.z
             );
         }
     }
@@ -51,5 +54,11 @@ void main()	{
         gridValue
     );
 
+    imageStore(
+        gridCopyImage,
+        ivec3(gl_GlobalInvocationID),
+        gridValue
+    );
+
     memoryBarrierImage();
 }
\ No newline at end of file
diff --git a/projects/wobble_bobble/shaders/update_grid_forces.comp b/projects/wobble_bobble/shaders/update_grid_forces.comp
index 752c3eff..4ea302e7 100644
--- a/projects/wobble_bobble/shaders/update_grid_forces.comp
+++ b/projects/wobble_bobble/shaders/update_grid_forces.comp
@@ -7,8 +7,9 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
 
 #include "particle.inc"
 
-layout(set=0, binding=0, rgba32f) uniform image3D gridImage;
-layout(set=0, binding=1, std430) buffer particleBuffer {
+layout(set=0, binding=0, rgba32f) restrict readonly uniform image3D gridImage;
+layout(set=0, binding=1, rgba32f) restrict writeonly uniform image3D gridForceImage;
+layout(set=0, binding=2, std430) buffer particleBuffer {
     Particle particles [];
 };
 
@@ -23,7 +24,7 @@ shared Particle shared_particles [SHARED_PARTICLES_BATCH_SIZE];
 
 void main()	{
     const vec3 position = (vec3(gl_GlobalInvocationID) + vec3(0.5f)) / imageSize(gridImage);
-    const float elasticity_module = 1200.5f * 1000000.0f; // 10..15 = Wood
+    const float elasticity_module = 2.5f * 1000000.0f; // 10..15 = Wood
 
     memoryBarrierImage();
 
@@ -60,23 +61,30 @@ void main()	{
             float volume = 4.0f / 3.0f * PI * size * size * size;
             mat3 deformation = mat3(shared_particles[gl_LocalInvocationIndex].deformation);
 
-            mat3 epsilon = deformation - mat3(1.0f);
-            mat3 delta = elasticity_module * epsilon;
-            mat3 delta_cauchy = determinant(deformation) * delta * inverse(transpose(deformation));
+            float J = determinant(deformation);
 
-            vec3 weight_gradient = vec3(
-                voxel_particle_grad_weight(position, shared_particles[gl_LocalInvocationIndex].minimal)
-            );
+            if ((abs(J) > 0.0f) && (volume > 0.0f)) {
+                mat3 epsilon = deformation - mat3(1.0f);
+                mat3 delta = elasticity_module * epsilon;
+                mat3 delta_cauchy = J * delta * inverse(transpose(deformation));
 
-            force -= (
-                volume *
-                delta_cauchy *
-                weight_gradient
-            );
+                vec3 weight_gradient = voxel_particle_grad_weight(
+                    position,
+                    shared_particles[gl_LocalInvocationIndex].minimal
+                );
+
+                force -= (
+                    volume *
+                    delta_cauchy *
+                    weight_gradient
+                );
+            }
         }
     }
 
-    velocity += force * dt / mass;
+    if (mass > 0.0f) {
+        velocity += force * dt / mass;
+    }
 
     bvec3 lowerID = lessThanEqual(gl_GlobalInvocationID, ivec3(0));
     bvec3 negativeVelocity = lessThan(velocity, vec3(0.0f));
@@ -90,10 +98,10 @@ void main()	{
         (lowerID.z && negativeVelocity.z) || (greaterID.z && positiveVelocity.z)
     );
 
-    velocity = mix(velocity, -velocity, invert) - gridSample.xyz;
+    velocity = mix(velocity, -velocity, invert);
 
     imageStore(
-        gridImage,
+        gridForceImage,
         ivec3(gl_GlobalInvocationID),
         vec4(velocity, mass)
     );
diff --git a/projects/wobble_bobble/shaders/update_particle_deformation.comp b/projects/wobble_bobble/shaders/update_particle_deformation.comp
index 7bfc923b..9711d48a 100644
--- a/projects/wobble_bobble/shaders/update_particle_deformation.comp
+++ b/projects/wobble_bobble/shaders/update_particle_deformation.comp
@@ -9,30 +9,46 @@ layout(set=0, binding=0, std430) buffer particleBuffer {
     Particle particles [];
 };
 
-layout(set=0, binding=1) uniform texture3D gridTextureIn;
+layout(set=0, binding=1) uniform texture3D gridImage;
 layout(set=0, binding=2) uniform sampler gridSampler;
 
-layout( push_constant ) uniform constants {
-    float t;
-    float dt;
-};
-
 void main()	{
     memoryBarrierBuffer();
     memoryBarrierImage();
 
-    ParticleMinimal particle = particles[gl_GlobalInvocationID.x].minimal;
-    mat3 deformation = mat3(particles[gl_GlobalInvocationID.x].deformation);
+    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);
+
+        uint 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;
+
+                    if (length(offset) < minimal.size * 2.0f) {
+                        vec4 gridSample = texture(sampler3D(gridImage, gridSampler), voxel);
 
-    mat3 grad_velocity = mat3(
-        textureGrad(sampler3D(gridTextureIn, gridSampler), particle.position, vec3(1.0f, 0.0f, 0.0f), vec3(0.0f)).xyz,
-        textureGrad(sampler3D(gridTextureIn, gridSampler), particle.position, vec3(0.0f, 1.0f, 0.0f), vec3(0.0f)).xyz,
-        textureGrad(sampler3D(gridTextureIn, gridSampler), particle.position, vec3(0.0f, 0.0f, 1.0f), vec3(0.0f)).xyz
-    );
+                        velocity_gradient += outerProduct(
+                            gridSample.xyz,
+                            voxel_particle_grad_weight(voxel, minimal)
+                        );
+                    }
+                }
+            }
+        }
 
-    mat3 deformation_elastic = (mat3(1.0f) + grad_velocity * dt) * deformation;
+        mat3 deformation_elastic = (mat3(1.0f) + velocity_gradient) * deformation;
 
-    particles[gl_GlobalInvocationID.x].deformation = mat4(deformation_elastic);
+        particles[gl_GlobalInvocationID.x].deformation = mat4(deformation_elastic);
+    }
 
     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 2c4f9e4f..123ac83a 100644
--- a/projects/wobble_bobble/shaders/update_particle_velocities.comp
+++ b/projects/wobble_bobble/shaders/update_particle_velocities.comp
@@ -10,7 +10,8 @@ layout(set=0, binding=0, std430) buffer particleBuffer {
 };
 
 layout(set=0, binding=1) uniform texture3D gridImage;
-layout(set=0, binding=2) uniform sampler gridSampler;
+layout(set=0, binding=2) uniform texture3D gridOldImage;
+layout(set=0, binding=3) uniform sampler gridSampler;
 
 void main()	{
     memoryBarrierBuffer();
@@ -20,7 +21,7 @@ void main()	{
         ParticleMinimal minimal = particles[gl_GlobalInvocationID.x].minimal;
 
         ivec3 gridResolution = textureSize(sampler3D(gridImage, gridSampler), 0);
-        ivec3 gridWindow = ivec3(minimal.size * 4.0f * gridResolution);
+        ivec3 gridWindow = ivec3(minimal.size * 2.0f * gridResolution);
 
         vec3 velocity = vec3(minimal.velocity);
 
@@ -34,7 +35,11 @@ void main()	{
 
                     if (length(offset) < minimal.size * 2.0f) {
                         vec4 gridSample = texture(sampler3D(gridImage, gridSampler), voxel);
-                        velocity += voxel_particle_weight(voxel, minimal) * gridSample.xyz;
+                        vec4 gridOldSample = texture(sampler3D(gridOldImage, gridSampler), voxel);
+
+                        vec3 weight = voxel_particle_weight(voxel, minimal);
+
+                        velocity += (weight.x * weight.y * weight.z) * (gridSample.xyz - gridOldSample.xyz);
                     }
                 }
             }
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index b7ab85c6..f386cc15 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -40,7 +40,7 @@ void distributeParticles(Particle *particles, size_t count, const glm::vec3& cen
 		
 		particles[i].position = center + offset;
 		particles[i].size = size;
-		particles[i].velocity = glm::vec3(0.0f, 1.0f, 0.0f);
+		particles[i].velocity = glm::vec3(0.0f, 0.1f, 0.0f);
 		
 		volume += size;
 	}
@@ -153,6 +153,17 @@ int main(int argc, const char **argv) {
 	
 	grid.switchLayout(vk::ImageLayout::eGeneral);
 	
+	vkcv::Image gridCopy = core.createImage(
+			grid.getFormat(),
+			grid.getWidth(),
+			grid.getHeight(),
+			grid.getDepth(),
+			false,
+			true
+	);
+	
+	gridCopy.switchLayout(vk::ImageLayout::eGeneral);
+	
 	/* TODO: clear grid via compute shader?
 	std::vector<glm::vec4> grid_vec (grid.getWidth() * grid.getHeight() * grid.getDepth());
 	
@@ -185,6 +196,7 @@ int main(int argc, const char **argv) {
 		vkcv::DescriptorWrites writes;
 		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particles.getHandle()));
 		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(1, grid.getHandle()));
+		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(2, gridCopy.getHandle()));
 		core.writeDescriptorSet(transformParticlesToGridSets[0], writes);
 	}
 	
@@ -210,8 +222,9 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(0, grid.getHandle()));
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(1, particles.getHandle()));
+		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(0, gridCopy.getHandle()));
+		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(1, grid.getHandle()));
+		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(2, particles.getHandle()));
 		core.writeDescriptorSet(updateGridForcesSets[0], writes);
 	}
 	
@@ -241,7 +254,8 @@ int main(int argc, const char **argv) {
 		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));
+		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(2, gridCopy.getHandle()));
+		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(3, gridSampler));
 		core.writeDescriptorSet(updateParticleVelocitiesSets[0], writes);
 	}
 	
@@ -467,6 +481,7 @@ int main(int argc, const char **argv) {
 		
 		core.recordBeginDebugLabel(cmdStream, "TRANSFORM PARTICLES TO GRID", { 0.47f, 0.77f, 0.85f, 1.0f });
 		core.prepareImageForStorage(cmdStream, grid.getHandle());
+		core.prepareImageForStorage(cmdStream, gridCopy.getHandle());
 		
 		core.recordComputeDispatchToCmdStream(
 				cmdStream,
@@ -479,6 +494,7 @@ int main(int argc, const char **argv) {
 		);
 		
 		core.recordImageMemoryBarrier(cmdStream, grid.getHandle());
+		core.recordImageMemoryBarrier(cmdStream, gridCopy.getHandle());
 		core.recordEndDebugLabel(cmdStream);
 		
 		if (!initializedParticleVolumes) {
@@ -508,6 +524,8 @@ int main(int argc, const char **argv) {
 				) },
 				timePushConstants
 		);
+		
+		core.recordImageMemoryBarrier(cmdStream, grid.getHandle());
 		core.recordEndDebugLabel(cmdStream);
 		
 		core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE DEFORMATION", { 0.78f, 0.89f, 0.94f, 1.0f });
@@ -520,13 +538,15 @@ int main(int argc, const char **argv) {
 				{ vkcv::DescriptorSetUsage(
 						0, core.getDescriptorSet(updateParticleDeformationSets[0]).vulkanHandle
 				) },
-				timePushConstants
+				vkcv::PushConstants(0)
 		);
 		
 		core.recordBufferMemoryBarrier(cmdStream, particles.getHandle());
 		core.recordEndDebugLabel(cmdStream);
 		
 		core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE VELOCITIES", { 0.78f, 0.89f, 0.94f, 1.0f });
+		core.prepareImageForSampling(cmdStream, gridCopy.getHandle());
+		
 		core.recordComputeDispatchToCmdStream(
 				cmdStream,
 				updateParticleVelocitiesPipeline,
-- 
GitLab