diff --git a/projects/head_demo/CMakeLists.txt b/projects/head_demo/CMakeLists.txt
index 09e5f693d6c6ddc243d884a74981bdb980fb9065..bd7e48000320d4c1304a3b9f3b26fe54421f818c 100644
--- a/projects/head_demo/CMakeLists.txt
+++ b/projects/head_demo/CMakeLists.txt
@@ -13,7 +13,25 @@ add_executable(head_demo src/main.cpp)
 fix_project(head_demo)
 
 # including headers of dependencies and the VkCV framework
-target_include_directories(head_demo SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_scene_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include})
+target_include_directories(head_demo SYSTEM BEFORE PRIVATE
+		${vkcv_include}
+		${vkcv_includes}
+		${vkcv_asset_loader_include}
+		${vkcv_camera_include}
+		${vkcv_scene_include}
+		${vkcv_shader_compiler_include}
+		${vkcv_gui_include}
+		${vkcv_effects_include}
+		${vkcv_upscaling_include})
 
 # linking with libraries from all dependencies and the VkCV framework
-target_link_libraries(head_demo vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_scene vkcv_shader_compiler vkcv_gui)
+target_link_libraries(head_demo
+		vkcv
+		${vkcv_libraries}
+		vkcv_asset_loader
+		${vkcv_asset_loader_libraries}
+		vkcv_camera vkcv_scene
+		vkcv_shader_compiler
+		vkcv_gui
+		vkcv_effects
+		vkcv_upscaling)
diff --git a/projects/head_demo/assets/shaders/red.frag b/projects/head_demo/assets/shaders/red.frag
index 3991f9396323bb25c57f03e5ba7b5f9a280ed556..35735be779edd0bf88890638329dc53f6b691f57 100644
--- a/projects/head_demo/assets/shaders/red.frag
+++ b/projects/head_demo/assets/shaders/red.frag
@@ -2,9 +2,10 @@
 #extension GL_ARB_separate_shader_objects : enable
 
 layout(location = 0) in vec3 passNormal;
+layout(location = 1) in vec3 passEdge;
 
 layout(location = 0) out vec3 outColor;
 
 void main()	{
-    outColor = (vec3(0.3f, 0, 0) + max(dot(passNormal, vec3(1.0f, -1.0f, 0.5f)), 0.0f) * vec3(0.7f, 0, 0));
+    outColor = (0.1f + max(dot(passNormal, vec3(1.0f, -1.0f, 0.5f)), 0.0f) * 0.9f) * (passEdge + 0.5f);
 }
\ No newline at end of file
diff --git a/projects/head_demo/assets/shaders/wired.geom b/projects/head_demo/assets/shaders/wired.geom
index 0063360547b859fc7a305b5786532654b5b35f34..689e073dde7fd993d164cfea0b7ca777d79f8508 100644
--- a/projects/head_demo/assets/shaders/wired.geom
+++ b/projects/head_demo/assets/shaders/wired.geom
@@ -8,6 +8,7 @@ layout(points, max_vertices = 1) out;
 layout(location = 0) in vec3 geomNormal[];
 
 layout(location = 0) out vec3 passNormal;
+layout(location = 1) out vec3 passEdge;
 
 layout(set=1, binding=0) uniform clipBuffer {
     float clipLimit;
@@ -43,6 +44,7 @@ void main()	{
         if ((v0.x < clipLimit) || (v1.x < clipLimit) || (v2.x < clipLimit)) {
             gl_Position = (v0 + v1 + v2) / 3;
             passNormal = (geomNormal[0] + geomNormal[1] + geomNormal[2]) / 3;
+            passEdge = vec3(dx, dy, dz);
             EmitVertex();
 
             EndPrimitive();
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index c25ed49f989f47b63e4e7f828550016d6a2fbaeb..3eeec03a47d8051385523e8f3e3e146e0829aeda 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -7,6 +7,8 @@
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <vkcv/scene/Scene.hpp>
+#include <vkcv/effects/BloomAndFlaresEffect.hpp>
+#include <vkcv/upscaling/FSRUpscaling.hpp>
 
 int main(int argc, const char** argv) {
 	const char* applicationName = "First Scene";
@@ -20,7 +22,7 @@ int main(int argc, const char** argv) {
 			{vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute},
 			{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }
 	);
-	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false);
+	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true);
 	vkcv::Window& window = core.getWindow(windowHandle);
 	vkcv::camera::CameraManager cameraManager(window);
 	
@@ -38,10 +40,12 @@ int main(int argc, const char** argv) {
 			argc > 1 ? argv[1] : "assets/skull_scaled/scene.gltf"
 	));
 	
-	const vkcv::AttachmentDescription present_color_attachment0(
+	vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
+	
+	const vkcv::AttachmentDescription color_attachment0(
 			vkcv::AttachmentOperation::STORE,
 			vkcv::AttachmentOperation::CLEAR,
-			core.getSwapchain(windowHandle).getFormat()
+			colorFormat
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment0(
@@ -50,13 +54,10 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat
 	);
 	
-	vkcv::PassConfig scenePassDefinition({ present_color_attachment0, depth_attachment0 });
-	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
-	
-	const vkcv::AttachmentDescription present_color_attachment1(
+	const vkcv::AttachmentDescription color_attachment1(
 			vkcv::AttachmentOperation::STORE,
 			vkcv::AttachmentOperation::LOAD,
-			core.getSwapchain(windowHandle).getFormat()
+			colorFormat
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment1(
@@ -65,9 +66,12 @@ int main(int argc, const char** argv) {
 			vk::Format::eD32Sfloat
 	);
 	
-	vkcv::PassConfig linePassDefinition({ present_color_attachment1, depth_attachment1 });
+	vkcv::PassConfig linePassDefinition({ color_attachment0, depth_attachment0 });
 	vkcv::PassHandle linePass = core.createPass(linePassDefinition);
 	
+	vkcv::PassConfig scenePassDefinition({ color_attachment1, depth_attachment1 });
+	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
+	
 	if ((!scenePass) || (!linePass)) {
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
@@ -177,8 +181,18 @@ int main(int argc, const char** argv) {
 			swapchainExtent.height
 	).getHandle();
 	
+	vkcv::ImageHandle colorBuffer = core.createImage(
+			colorFormat,
+			swapchainExtent.width,
+			swapchainExtent.height,
+			1, false, true, true
+	).getHandle();
+	
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 	
+	vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core);
+	vkcv::upscaling::FSRUpscaling upscaling (core);
+	
 	auto start = std::chrono::system_clock::now();
 	while (vkcv::Window::hasOpenWindow()) {
 		vkcv::Window::pollEvents();
@@ -194,6 +208,13 @@ int main(int argc, const char** argv) {
 		if ((swapchainWidth != swapchainExtent.width) || ((swapchainHeight != swapchainExtent.height))) {
 			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle();
 			
+			colorBuffer = core.createImage(
+					colorFormat,
+					swapchainExtent.width,
+					swapchainExtent.height,
+					1, false, true, true
+			).getHandle();
+			
 			swapchainExtent.width = swapchainWidth;
 			swapchainExtent.height = swapchainHeight;
 		}
@@ -206,7 +227,7 @@ int main(int argc, const char** argv) {
 		
 		clipBuffer.fill({ clipLimit, -clipX, -clipY, -clipZ });
 		
-		const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
+		const std::vector<vkcv::ImageHandle> renderTargets = { colorBuffer, depthBuffer };
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 		
 		auto recordMesh = [&](const glm::mat4& MVP, const glm::mat4& M,
@@ -220,22 +241,28 @@ int main(int argc, const char** argv) {
 		
 		scene.recordDrawcalls(cmdStream,
 							  cameraManager.getActiveCamera(),
-							  scenePass,
-							  scenePipeline,
+							  linePass,
+							  linePipeline,
 							  sizeof(glm::mat4),
 							  recordMesh,
 							  renderTargets,
 							  windowHandle);
 		
+		bloomAndFlares.recordEffect(cmdStream, colorBuffer, colorBuffer);
+		
 		scene.recordDrawcalls(cmdStream,
 							  cameraManager.getActiveCamera(),
-							  linePass,
-							  linePipeline,
+							  scenePass,
+							  scenePipeline,
 							  sizeof(glm::mat4),
 							  recordMesh,
 							  renderTargets,
 							  windowHandle);
 		
+		core.prepareImageForSampling(cmdStream, colorBuffer);
+		core.prepareImageForStorage(cmdStream, swapchainInput);
+		upscaling.recordUpscaling(cmdStream, colorBuffer, swapchainInput);
+		
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);