diff --git a/projects/wobble_bobble/shaders/grid.frag b/projects/wobble_bobble/shaders/grid.frag
index c3dc1fb2f80667f5810d93c4c4927d48bf0e236e..8eb2fbc2173bbddb5bdc44c52ce81d2e5d52d389 100644
--- a/projects/wobble_bobble/shaders/grid.frag
+++ b/projects/wobble_bobble/shaders/grid.frag
@@ -17,7 +17,11 @@ void main()	{
 
     if (value < 0.5f) {
         vec3 surface = vec3(passPos.x + 0.5f, passPos.y + 0.5f, z * 2.0f);
-        vec3 velocity = vec3(0.5f) + 0.5f * normalize(passVelocity.xyz);
+        vec3 velocity = vec3(0.5f);
+
+        if (length(passVelocity) > 0.0f) {
+            velocity = vec3(0.5f) + 0.5f * normalize(passVelocity.xyz);
+        }
 
         outColor = velocity;
     } else {
diff --git a/projects/wobble_bobble/shaders/lines.frag b/projects/wobble_bobble/shaders/lines.frag
new file mode 100644
index 0000000000000000000000000000000000000000..37d79d30d2ce751a59b1b467764b2fe464aa5c17
--- /dev/null
+++ b/projects/wobble_bobble/shaders/lines.frag
@@ -0,0 +1,7 @@
+#version 450
+
+layout(location = 0) out vec3 outColor;
+
+void main() {
+    outColor = vec3(1.0f);
+}
\ No newline at end of file
diff --git a/projects/wobble_bobble/shaders/lines.vert b/projects/wobble_bobble/shaders/lines.vert
new file mode 100644
index 0000000000000000000000000000000000000000..b8e3b01c67986156ad980899697ffea05409b752
--- /dev/null
+++ b/projects/wobble_bobble/shaders/lines.vert
@@ -0,0 +1,11 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPos;
+
+layout( push_constant ) uniform constants{
+    mat4 mvp;
+};
+
+void main() {
+    gl_Position = mvp * vec4(vertexPos, 1);
+}
\ No newline at end of file
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 4e7635488a3c61d0f14e790a9b141fca0a578687..ee5dd9cd9e7c1a0d2e98d5ccd93d022e6633071e 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -308,6 +308,24 @@ int main(int argc, const char **argv) {
 			}
 	);
 	
+	vkcv::ShaderProgram gfxProgramLines;
+	
+	compiler.compile(
+			vkcv::ShaderStage::VERTEX,
+			"shaders/lines.vert",
+			[&gfxProgramLines](vkcv::ShaderStage stage, const std::filesystem::path& path) {
+				gfxProgramLines.addShader(stage, path);
+			}
+	);
+	
+	compiler.compile(
+			vkcv::ShaderStage::FRAGMENT,
+			"shaders/lines.frag",
+			[&gfxProgramLines](vkcv::ShaderStage stage, const std::filesystem::path& path) {
+				gfxProgramLines.addShader(stage, path);
+			}
+	);
+	
 	vkcv::PassConfig passConfigGrid ({
 		vkcv::AttachmentDescription(
 				vkcv::AttachmentOperation::STORE,
@@ -334,6 +352,19 @@ int main(int argc, const char **argv) {
 		)
 	});
 	
+	vkcv::PassConfig passConfigLines ({
+		vkcv::AttachmentDescription(
+				vkcv::AttachmentOperation::STORE,
+				vkcv::AttachmentOperation::LOAD,
+				core.getSwapchain(windowHandle).getFormat()
+		),
+		vkcv::AttachmentDescription(
+				vkcv::AttachmentOperation::STORE,
+				vkcv::AttachmentOperation::LOAD,
+				vk::Format::eD32Sfloat
+		)
+	});
+	
 	vkcv::DescriptorSetLayoutHandle gfxSetLayoutGrid = core.createDescriptorSetLayout(
 			gfxProgramGrid.getReflectedDescriptors().at(0)
 	);
@@ -361,6 +392,7 @@ int main(int argc, const char **argv) {
 	
 	vkcv::PassHandle gfxPassGrid = core.createPass(passConfigGrid);
 	vkcv::PassHandle gfxPassParticles = core.createPass(passConfigParticles);
+	vkcv::PassHandle gfxPassLines = core.createPass(passConfigLines);
 	
 	vkcv::VertexLayout vertexLayoutGrid ({
 		vkcv::VertexBinding(0, gfxProgramGrid.getVertexAttachments())
@@ -389,14 +421,29 @@ int main(int argc, const char **argv) {
 	gfxPipelineConfigParticles.m_DescriptorLayouts = { gfxSetLayoutParticles };
 	gfxPipelineConfigParticles.m_UseDynamicViewport = true;
 	
+	vkcv::VertexLayout vertexLayoutLines ({
+		vkcv::VertexBinding(0, gfxProgramLines.getVertexAttachments())
+	});
+	
+	vkcv::GraphicsPipelineConfig gfxPipelineConfigLines;
+	gfxPipelineConfigLines.m_ShaderProgram = gfxProgramLines;
+	gfxPipelineConfigLines.m_Width = windowWidth;
+	gfxPipelineConfigLines.m_Height = windowHeight;
+	gfxPipelineConfigLines.m_PassHandle = gfxPassLines;
+	gfxPipelineConfigLines.m_VertexLayout = vertexLayoutLines;
+	gfxPipelineConfigLines.m_DescriptorLayouts = {};
+	gfxPipelineConfigLines.m_UseDynamicViewport = true;
+	gfxPipelineConfigLines.m_PrimitiveTopology = vkcv::PrimitiveTopology::LineList;
+	
 	vkcv::GraphicsPipelineHandle gfxPipelineGrid = core.createGraphicsPipeline(gfxPipelineConfigGrid);
 	vkcv::GraphicsPipelineHandle gfxPipelineParticles = core.createGraphicsPipeline(gfxPipelineConfigParticles);
+	vkcv::GraphicsPipelineHandle gfxPipelineLines = core.createGraphicsPipeline(gfxPipelineConfigLines);
 	
 	vkcv::Buffer<glm::vec2> trianglePositions = core.createBuffer<glm::vec2>(vkcv::BufferType::VERTEX, 3);
 	trianglePositions.fill({
 		glm::vec2(-1.0f, -1.0f),
 		glm::vec2(+0.0f, +1.5f),
-		glm::vec2(+1.0f, -1.0f),
+		glm::vec2(+1.0f, -1.0f)
 	});
 	
 	vkcv::Buffer<uint16_t> triangleIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3);
@@ -410,6 +457,42 @@ int main(int argc, const char **argv) {
 			triangleIndices.getCount()
 	);
 	
+	vkcv::Buffer<glm::vec3> linesPositions = core.createBuffer<glm::vec3>(vkcv::BufferType::VERTEX, 8);
+	linesPositions.fill({
+		glm::vec3(0.0f, 0.0f, 0.0f),
+		glm::vec3(1.0f, 0.0f, 0.0f),
+		glm::vec3(0.0f, 1.0f, 0.0f),
+		glm::vec3(1.0f, 1.0f, 0.0f),
+		glm::vec3(0.0f, 0.0f, 1.0f),
+		glm::vec3(1.0f, 0.0f, +1.0f),
+		glm::vec3(0.0f, 1.0f, 1.0f),
+		glm::vec3(1.0f, 1.0f, 1.0f)
+	});
+	
+	vkcv::Buffer<uint16_t> linesIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 24);
+	linesIndices.fill({
+		0, 1,
+		1, 3,
+		3, 2,
+		2, 0,
+		
+		4, 5,
+		5, 7,
+		7, 6,
+		6, 4,
+		
+		0, 4,
+		1, 5,
+		2, 6,
+		3, 7
+	});
+	
+	vkcv::Mesh linesMesh (
+			{ vkcv::VertexBufferBinding(0, linesPositions.getVulkanHandle()) },
+			linesIndices.getVulkanHandle(),
+			linesIndices.getCount()
+	);
+	
 	std::vector<vkcv::DrawcallInfo> drawcallsGrid;
 	
 	drawcallsGrid.push_back(vkcv::DrawcallInfo(
@@ -426,6 +509,14 @@ int main(int argc, const char **argv) {
 			particles.getCount()
 	));
 	
+	std::vector<vkcv::DrawcallInfo> drawcallsLines;
+	
+	drawcallsLines.push_back(vkcv::DrawcallInfo(
+			linesMesh,
+			{},
+			1
+	));
+	
 	bool initializedParticleVolumes = false;
 	bool renderGrid = true;
 	
@@ -609,6 +700,20 @@ int main(int argc, const char **argv) {
 			core.recordEndDebugLabel(cmdStream);
 		}
 		
+		core.recordBeginDebugLabel(cmdStream, "RENDER LINES", { 0.13f, 0.20f, 0.22f, 1.0f });
+		
+		core.recordDrawcallsToCmdStream(
+				cmdStream,
+				gfxPassLines,
+				gfxPipelineLines,
+				cameraPushConstants,
+				drawcallsLines,
+				renderTargets,
+				windowHandle
+		);
+		
+		core.recordEndDebugLabel(cmdStream);
+		
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);