diff --git a/projects/wobble_bobble/shaders/update_grid_forces.comp b/projects/wobble_bobble/shaders/update_grid_forces.comp
index 7277e586fc746006f121dd7a439e4ff46ead3971..bf1c8a17c2173e846b43009d5290c5a5ce68efd3 100644
--- a/projects/wobble_bobble/shaders/update_grid_forces.comp
+++ b/projects/wobble_bobble/shaders/update_grid_forces.comp
@@ -1,6 +1,45 @@
 #version 450
+#extension GL_GOOGLE_include_directive : enable
 
-layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+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( push_constant ) uniform constants {
+    float t;
+    float dt;
+};
 
 void main()	{
+    vec4 gridSample = imageLoad(
+        gridImage,
+        ivec3(gl_GlobalInvocationID)
+    );
+
+    vec3 velocity = gridSample.xyz;
+    float mass = gridSample.w;
+
+    velocity += vec3(0.0f, 0.0f, 0.0f) * dt;
+
+    bvec3 lowerID = lessThanEqual(gl_GlobalInvocationID, ivec3(0));
+    bvec3 negativeVelocity = lessThan(velocity, vec3(0.0f));
+
+    bvec3 greaterID = greaterThanEqual(gl_GlobalInvocationID + ivec3(1), imageSize(gridImage));
+    bvec3 positiveVelocity = greaterThan(velocity, vec3(0.0f));
+
+    bvec3 invert = bvec3(
+        (lowerID.x && negativeVelocity.x) || (greaterID.x && positiveVelocity.x),
+        (lowerID.y && negativeVelocity.y) || (greaterID.y && positiveVelocity.y),
+        (lowerID.z && negativeVelocity.z) || (greaterID.z && positiveVelocity.z)
+    );
+
+    velocity = mix(velocity, -velocity, invert);
+
+    imageStore(
+        gridImage,
+        ivec3(gl_GlobalInvocationID),
+        vec4(velocity, mass)
+    );
 }
\ No newline at end of file
diff --git a/projects/wobble_bobble/shaders/update_particle_deformation.comp b/projects/wobble_bobble/shaders/update_particle_deformation.comp
index 7277e586fc746006f121dd7a439e4ff46ead3971..f38e17784b93b25231ebaec9cf3ca34407746165 100644
--- a/projects/wobble_bobble/shaders/update_particle_deformation.comp
+++ b/projects/wobble_bobble/shaders/update_particle_deformation.comp
@@ -1,6 +1,33 @@
 #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) buffer particleBuffer {
+    Particle particles [];
+};
+
+layout(set=0, binding=1) uniform texture3D gridTextureIn;
+layout(set=0, binding=2) uniform sampler gridSampler;
+
+layout( push_constant ) uniform constants {
+    float t;
+    float dt;
+};
+
 void main()	{
+    ParticleMinimal particle = particles[gl_GlobalInvocationID.x].minimal;
+    mat3 deformation = mat3(particles[gl_GlobalInvocationID.x].deformation);
+
+    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
+    );
+
+    mat3 deformation_elastic = (mat3(1.0f) + grad_velocity * dt) * deformation;
+
+    particles[gl_GlobalInvocationID.x].deformation = mat4(deformation_elastic);
 }
\ No newline at end of file
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 3327893333788cfd032ca6a708d9b5a2f45f48cc..674af9b124c9fa2bd55047f47e1c3f3a33b3c995 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -47,6 +47,7 @@ void distributeParticles(Particle *particles, size_t count, const glm::vec3& cen
 	
 	for (size_t i = 0; i < count; i++) {
 		particles[i].mass = (mass * particles[i].size / volume);
+		particles[i].deformation = glm::mat4(1.0f);
 	}
 }
 
@@ -210,6 +211,12 @@ int main(int argc, const char **argv) {
 			updateGridForcesSets
 	);
 	
+	{
+		vkcv::DescriptorWrites writes;
+		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(0, grid.getHandle()));
+		core.writeDescriptorSet(updateGridForcesSets[0], writes);
+	}
+	
 	std::vector<vkcv::DescriptorSetHandle> updateGridVelocitiesSets;
 	vkcv::ComputePipelineHandle updateGridVelocitiesPipeline = createComputePipeline(
 			core, compiler,
@@ -232,6 +239,14 @@ int main(int argc, const char **argv) {
 			updateParticleDeformationSets
 	);
 	
+	{
+		vkcv::DescriptorWrites writes;
+		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particles.getHandle()));
+		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(1, tmpGrid.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,
@@ -501,8 +516,10 @@ int main(int argc, const char **argv) {
 				cmdStream,
 				updateGridForcesPipeline,
 				dispatchSizeGrid,
-				{},
-				vkcv::PushConstants(0)
+				{ vkcv::DescriptorSetUsage(
+						0, core.getDescriptorSet(updateGridForcesSets[0]).vulkanHandle
+				) },
+				timePushConstants
 		);
 		core.recordEndDebugLabel(cmdStream);
 		
@@ -524,18 +541,22 @@ int main(int argc, const char **argv) {
 		core.recordEndDebugLabel(cmdStream);
 		
 		core.recordBeginDebugLabel(cmdStream, "UPDATE PARTICLE DEFORMATION", { 0.78f, 0.89f, 0.94f, 1.0f });
+		core.prepareImageForSampling(cmdStream, tmpGrid.getHandle());
+		
 		core.recordComputeDispatchToCmdStream(
 				cmdStream,
 				updateParticleDeformationPipeline,
 				dispatchSizeParticles,
-				{},
-				vkcv::PushConstants(0)
+				{ vkcv::DescriptorSetUsage(
+						0, core.getDescriptorSet(updateParticleDeformationSets[0]).vulkanHandle
+				) },
+				timePushConstants
 		);
+		
+		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, tmpGrid.getHandle());
-		
 		core.recordComputeDispatchToCmdStream(
 				cmdStream,
 				updateParticleVelocitiesPipeline,