diff --git a/CMakeLists.txt b/CMakeLists.txt
index 71e3f66f0693291e4a995f03943d5a020f8941fc..5d82d62ebc479996fd7eca4c974d6692fc55b821 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -412,11 +412,11 @@ add_subdirectory(${LIBLAVA_EXT_DIR}/assimp assimp)
 
 message("<<< assimp")
 
-message(">>> cgal")
+message("<<< boost")
 
-add_subdirectory(${LIBLAVA_EXT_DIR}/cgal cgal)
+add_subdirectory(${LIBLAVA_EXT_DIR}/boost boost)
 
-message("<<< cgal")
+message(">>> boost")
 
 option(LIBLAVA_TESTS "Enable Tests" TRUE)
 if(LIBLAVA_TESTS)
@@ -791,7 +791,7 @@ message("=======================================================================
                 strategy/mesh_based_reprojection/mesh_based_reprojection_indirect.frag
                 strategy/mesh_based_reprojection/mesh_based_reprojection_indirect_shadow.frag
                 strategy/mesh_based_reprojection/mesh_based_reprojection_edge_detection.comp
-				strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.vert
+                strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.vert
                 strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.frag
 
                 utility/deferred_lighting.vert
@@ -837,6 +837,35 @@ message("=======================================================================
         target_include_directories(${NAME} PUBLIC ${OPENVR_HEADER_DIR})
         target_link_libraries(${NAME} "${CMAKE_SOURCE_DIR}/ext/openvr/lib/win64/openvr_api.lib")
         target_link_libraries(${NAME} "${CMAKE_SOURCE_DIR}/ext/cudart/lib/x64/cuda.lib")
+        
+        #Moudles required by the CGAL Library
+        target_link_libraries(${NAME} lava::app Boost::config)
+        target_link_libraries(${NAME} lava::app Boost::container)
+        target_link_libraries(${NAME} lava::app Boost::iterator)
+        target_link_libraries(${NAME} lava::app Boost::mpl)
+        target_link_libraries(${NAME} lava::app Boost::foreach)
+        target_link_libraries(${NAME} lava::app Boost::variant)
+        target_link_libraries(${NAME} lava::app Boost::random)
+        target_link_libraries(${NAME} lava::app Boost::property_map)
+        target_link_libraries(${NAME} lava::app Boost::tuple)
+        target_link_libraries(${NAME} lava::app Boost::math)
+        target_link_libraries(${NAME} lava::app Boost::algorithm)
+        target_link_libraries(${NAME} lava::app Boost::multiprecision)
+        target_link_libraries(${NAME} lava::app Boost::type_traits)
+        
+        #CGAL Library
+        set(CGAL_LIBRARY_DIR ${LIBLAVA_EXT_DIR}/cgal)
+
+        file(GLOB CGAL_LIBRARY_PACKAGES RELATIVE ${CGAL_LIBRARY_DIR} "${CGAL_LIBRARY_DIR}/*")
+        list(REMOVE_ITEM CGAL_LIBRARY_PACKAGES .svn .git .reuse)
+
+        foreach(package ${CGAL_LIBRARY_PACKAGES})
+            if(IS_DIRECTORY "${CGAL_LIBRARY_DIR}/${package}")
+                if(EXISTS "${CGAL_LIBRARY_DIR}/${package}/package_info/${package}/maintainer")
+                    target_include_directories(${NAME} PUBLIC "${CGAL_LIBRARY_DIR}/${package}/include")
+                endif()
+            endif()
+        endforeach()
 
         if(MSVC)
             source_group("" FILES ${SRC_DIR}/main.cpp)
@@ -851,6 +880,49 @@ message("=======================================================================
             source_group("Strategy" REGULAR_EXPRESSION ${SRC_DIR}/strategy/*)
             source_group("Transport" REGULAR_EXPRESSION ${SRC_DIR}/transport/*)
             source_group("Utility" REGULAR_EXPRESSION ${SRC_DIR}/utility/*)
+            
+            set_target_properties(assimp PROPERTIES FOLDER "Extern")
+            set_target_properties(UpdateAssimpLibsDebugSymbolsAndDLLs PROPERTIES FOLDER "Extern")
+            set_target_properties(zlibstatic PROPERTIES FOLDER "Extern")
+            
+            set_target_properties(boost_assert PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_atomic PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_chrono PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_container PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_context PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_contract PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_core PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_coroutine PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_date_time PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_exception PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_fiber PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_fiber_numa PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_filesystem PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_graph PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_iostreams PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_json PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_locale PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_log PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_log_setup PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_nowide PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_prg_exec_monitor PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_program_options PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_random PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_serialization PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_stacktrace_basic PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_stacktrace_noop PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_stacktrace_windbg PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_stacktrace_windbg_cached PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_system PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_test_exec_monitor PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_thread PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_timer PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_type_erasure PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_unit_test_framework PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_url PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_variant2 PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_wave PROPERTIES FOLDER "Extern")
+            set_target_properties(boost_wserialization PROPERTIES FOLDER "Extern")
         endif()
 
         set_property(TARGET ${NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")
diff --git a/res/dpr/strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.vert b/res/dpr/strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.vert
index b573f79fcd694e1b481f73f2a7134a455c27a3f2..2fdcda3517042da4829d41b738295061ac23d6a2 100644
--- a/res/dpr/strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.vert
+++ b/res/dpr/strategy/mesh_based_reprojection/mesh_based_reprojection_edge_preview.vert
@@ -13,7 +13,7 @@ layout(push_constant) uniform Parameters
 
 void main()
 {
-    vec2 coord = inPos / parameters.layer_resolution;
+    vec2 coord = (inPos + vec2(0.5)) / parameters.layer_resolution;
 
     gl_Position = vec4(coord * 2.0 - 1.0, 0.0, 1.0);
 }
\ No newline at end of file
diff --git a/src/scene.cpp b/src/scene.cpp
index 11404f1237266739cdde19c509f05fd5f5777743..5eb9a53f6488386ce62def0bde7400641ea100f2 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -1197,19 +1197,19 @@ bool Scene::load_animations(const aiScene* scene, float scale, const std::map<st
             for (uint32_t frame_index = 0; frame_index < channel->mNumPositionKeys; frame_index++)
             {
                 const aiVectorKey key = channel->mPositionKeys[frame_index];
-                scene_channel.position_frames[frame_index] = std::make_pair((float)key.mTime / animation->mTicksPerSecond, glm::make_vec3(&key.mValue.x) * scale);
+                scene_channel.position_frames[frame_index] = std::make_pair((float)key.mTime / (float)animation->mTicksPerSecond, glm::make_vec3(&key.mValue.x) * scale);
             }
 
             for (uint32_t frame_index = 0; frame_index < channel->mNumRotationKeys; frame_index++)
             {
                 const aiQuatKey key = channel->mRotationKeys[frame_index];
-                scene_channel.rotation_frames[frame_index] = std::make_pair((float)key.mTime / animation->mTicksPerSecond, key.mValue);
+                scene_channel.rotation_frames[frame_index] = std::make_pair((float)key.mTime / (float)animation->mTicksPerSecond, key.mValue);
             }
 
             for (uint32_t frame_index = 0; frame_index < channel->mNumScalingKeys; frame_index++)
             {
                 const aiVectorKey key = channel->mScalingKeys[frame_index];
-                scene_channel.scaling_frames[frame_index] = std::make_pair((float)key.mTime / animation->mTicksPerSecond, glm::make_vec3(&key.mValue.x));
+                scene_channel.scaling_frames[frame_index] = std::make_pair((float)key.mTime / (float)animation->mTicksPerSecond, glm::make_vec3(&key.mValue.x));
             }
         }
     }
diff --git a/src/strategy/mesh_based_reprojection.cpp b/src/strategy/mesh_based_reprojection.cpp
index becc3e0ff0776a05a613aa2f2a7ec8caf75897f0..8aa20de721cebe623db6bd6f1e9b16d8039ad4ff 100644
--- a/src/strategy/mesh_based_reprojection.cpp
+++ b/src/strategy/mesh_based_reprojection.cpp
@@ -1,8 +1,15 @@
 #include "mesh_based_reprojection.hpp"
 #include "vr_application.hpp"
 
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Constrained_Delaunay_triangulation_2.h>
 #include <imgui.h>
 
+typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
+typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel, CGAL::Default, CGAL::Exact_predicates_tag> ConstrainedTriangulation;
+typedef ConstrainedTriangulation::Point_2 Point2;
+typedef ConstrainedTriangulation::Face_handle FaceHandle;
+
 namespace glsl
 {
     using namespace glm;
@@ -281,6 +288,9 @@ MeshBasedReprojection::MeshBasedReprojection() : worker_pool(1)
 {
     this->layer_descriptor_sets.fill(VK_NULL_HANDLE);
     this->edge_descriptor_sets.fill(VK_NULL_HANDLE);
+
+    this->edge_preview_count.fill(0);
+    this->triangle_preview_count.fill(0);
 }
 
 bool MeshBasedReprojection::on_setup_instance(lava::frame_config& config)
@@ -379,15 +389,17 @@ bool MeshBasedReprojection::on_interface()
     ImGui::SliderFloat("Edge Detection Laplacian Threshold", &this->edge_detection_laplacian_threshold, 0.0f, 1.0f);
     ImGui::SliderFloat("Edge Detection Normal Scale", &this->edge_detection_normal_scale, 0.0f, 2.0f);
 
-    ImGui::SliderFloat("Edge Detection Min Value", &this->edge_detection_min_value, 0.0f, 1.0f);
-    ImGui::SliderFloat("Edge Detection Min Distance", &this->edge_detection_min_distance, 0.0f, 5.0f);
+    ImGui::SliderInt("Edge Extraction Min Length", (int32_t*)&this->edge_extraction_min_length, 2, 20);
+    ImGui::SliderFloat("Edge Extraction Min Value", &this->edge_extraction_min_value, 0.0f, 1.0f);
+    ImGui::SliderFloat("Edge Extraction Min Distance", &this->edge_extraction_min_distance, 0.0f, 5.0f);
 
     std::vector<const char*> overlay_names =
     {
         "Color",
         "Normal",
         "Edge Detection",
-        "Edge Preview"
+        "Edge Preview",
+        "Triangle Preview"
     };
 
     ImGui::Combo("Overlay", (int32_t*) &this->overlay, overlay_names.data(), overlay_names.size());
@@ -404,7 +416,7 @@ bool MeshBasedReprojection::on_update(lava::delta delta_time)
     std::unique_lock<std::mutex> lock(this->edge_buffer_mutex);
     if (this->edge_buffer_process_count > 0)
     {
-        double edge_buffer_process_time = (double) this->edge_buffer_process_time_sum / this->edge_buffer_process_count;
+        double edge_buffer_process_time = (double)this->edge_buffer_process_time_sum / this->edge_buffer_process_count;
 
         this->statistic_edge_buffer_time->add_sample(edge_buffer_process_time);
 
@@ -540,6 +552,7 @@ const char* MeshBasedReprojection::get_name() const
 bool MeshBasedReprojection::create_buffers()
 {
     glm::uvec2 resolution = this->get_headset()->get_framebuffer_resolution();
+    uint32_t depth_image_buffer_size = resolution.x * resolution.y * sizeof(float);
     uint32_t edge_image_buffer_size = resolution.x * resolution.y * sizeof(float);
     uint32_t edge_preview_buffer_size = MESH_BASED_REPROJECTION_EDGE_PEWVIEW_BUFFER_SIZE * 2 * sizeof(glm::vec2);
 
@@ -628,15 +641,6 @@ bool MeshBasedReprojection::create_buffers()
 
     for (uint32_t index = 0; index < this->edge_buffers.size(); index++)
     {
-        lava::buffer::ptr image_buffer = lava::make_buffer();
-        
-        if (!image_buffer->create_mapped(this->get_device(), nullptr, edge_image_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU))
-        {
-            lava::log()->error("Mesh based Reprojection: Can't create image buffer!");
-
-            return false;
-        }
-
         VkSemaphoreCreateInfo semaphore_info;
         semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
         semaphore_info.pNext = nullptr;
@@ -660,10 +664,29 @@ bool MeshBasedReprojection::create_buffers()
             return false;
         }
 
+        lava::buffer::ptr depth_image_buffer = lava::make_buffer();
+
+        if (!depth_image_buffer->create_mapped(this->get_device(), nullptr, depth_image_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU))
+        {
+            lava::log()->error("Mesh based Reprojection: Can't create depth image buffer!");
+
+            return false;
+        }
+
+        lava::buffer::ptr edge_image_buffer = lava::make_buffer();
+        
+        if (!edge_image_buffer->create_mapped(this->get_device(), nullptr, edge_image_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU))
+        {
+            lava::log()->error("Mesh based Reprojection: Can't create edge image buffer!");
+
+            return false;
+        }
+
         MeshBasedReprojectionEdgeBuffer::Ptr edge_buffer = make_mesh_based_reprojection_edge_buffer();
-        edge_buffer->image_buffer = image_buffer;
         edge_buffer->semaphore = semaphore;
         edge_buffer->fence = fence;
+        edge_buffer->depth_image_buffer = depth_image_buffer;
+        edge_buffer->edge_image_buffer = edge_image_buffer;
         edge_buffer->quad_tree = make_mesh_based_reprojection_quad_tree(resolution);
 
         this->edge_buffers[index] = edge_buffer;
@@ -1201,6 +1224,131 @@ bool MeshBasedReprojection::create_edge_preview_pipeline()
     return true;
 }
 
+bool MeshBasedReprojection::create_triangle_preview_pass()
+{
+    lava::attachment::ptr color_attachment = lava::make_attachment(this->get_headset()->get_format());
+    color_attachment->set_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE);
+    color_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE);
+    color_attachment->set_layouts(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+    lava::subpass::ptr subpass = lava::make_subpass();
+    subpass->set_color_attachment(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+
+    lava::subpass_dependency::ptr subpass_begin_dependency = lava::make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0);
+    subpass_begin_dependency->set_stage_mask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+    subpass_begin_dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
+
+    lava::subpass_dependency::ptr subpass_end_dependency = lava::make_subpass_dependency(0, VK_SUBPASS_EXTERNAL);
+    subpass_end_dependency->set_stage_mask( VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+    subpass_end_dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
+
+    this->triangle_preview_pass = lava::make_render_pass(this->get_device());
+    this->triangle_preview_pass->add(subpass);
+    this->triangle_preview_pass->add(subpass_begin_dependency);
+    this->triangle_preview_pass->add(subpass_end_dependency);
+    this->triangle_preview_pass->add(color_attachment);
+
+    lava::rect framebuffer_area =
+    {
+        glm::vec2(0.0f),
+        this->get_headset()->get_framebuffer_resolution()
+    };
+
+    lava::VkAttachments framebuffer_views =
+    {
+        { this->get_headset()->get_framebuffer(EYE_LEFT)->get_view() },
+        { this->get_headset()->get_framebuffer(EYE_RIGHT)->get_view() }
+    };
+
+    if (!this->triangle_preview_pass->create(framebuffer_views, framebuffer_area))
+    {
+        lava::log()->error("Mesh Based Reprojection: Can't create triangle preview pass!");
+
+        return false;
+    }
+
+    return true;
+}
+
+bool MeshBasedReprojection::create_triangle_preview_pipeline()
+{
+    VkPushConstantRange constant_range;
+    constant_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+    constant_range.offset = 0;
+    //constant_range.size = sizeof(glsl::MeshBasedReprojectionTrianglePreviewParameters);
+
+    this->triangle_preview_pipeline_layout = lava::make_pipeline_layout();
+    this->triangle_preview_pipeline_layout->add(constant_range);
+    
+    if (!this->edge_preview_pipeline_layout->create(this->get_device()))
+    {
+        lava::log()->error("Mesh Based Reprojection: Can't create edge preview pipeline layout!");
+
+        return false;
+    }
+    
+    VkVertexInputBindingDescription vertex_binding;
+    vertex_binding.binding = 0;
+    vertex_binding.stride = sizeof(glm::vec2);
+    vertex_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
+    VkVertexInputAttributeDescription vertex_attribute;
+    vertex_attribute.location = 0;
+    vertex_attribute.binding = 0;
+    vertex_attribute.format = VK_FORMAT_R32G32_SFLOAT;
+    vertex_attribute.offset = 0;
+
+    VkPipelineColorBlendAttachmentState blend_state;
+    blend_state.blendEnable = VK_FALSE;
+    blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
+    blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
+    blend_state.colorBlendOp = VK_BLEND_OP_ADD;
+    blend_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+    blend_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+    blend_state.alphaBlendOp = VK_BLEND_OP_ADD;
+    blend_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+
+    this->edge_preview_pipeline = lava::make_graphics_pipeline(this->get_device());
+    this->edge_preview_pipeline->set_layout(this->edge_preview_pipeline_layout);
+    this->edge_preview_pipeline->set_input_assembly_topology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
+    this->edge_preview_pipeline->add_color_blend_attachment(blend_state);
+    this->edge_preview_pipeline->set_vertex_input_binding(vertex_binding);
+    this->edge_preview_pipeline->set_vertex_input_attributes(
+    { 
+        vertex_attribute
+    });
+
+    if (!this->edge_preview_pipeline->add_shader(lava::file_data("dpr/binary/mesh_based_reprojection_edge_preview_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT))
+    {
+        lava::log()->error("Mesh Based Reprojection: Can't load vertex shader for edge preview pipeline!");
+
+        return false;
+    }
+
+    if (!this->edge_preview_pipeline->add_shader(lava::file_data("dpr/binary/mesh_based_reprojection_edge_preview_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT))
+    {
+        lava::log()->error("Mesh Based Reprojection: Can't load fragment shader for edge preview pipeline!");
+
+        return false;
+    }
+
+    this->edge_preview_pipeline->on_process = [this](VkCommandBuffer command_buffer)
+    {
+        this->process_edge_preview_pass(command_buffer);
+    };
+
+    if (!this->edge_preview_pipeline->create(this->edge_preview_pass->get()))
+    {
+        lava::log()->error("Mesh Based Reprojection: Can't create edge preview pipeline!");
+
+        return false;
+    }
+
+    this->edge_preview_pass->add_front(this->edge_preview_pipeline);
+
+    return true;
+}
+
 bool MeshBasedReprojection::build_projection()
 {
     this->layer_resolution = glm::uvec2(0); //NOTE: Will be used later
@@ -1251,7 +1399,7 @@ bool MeshBasedReprojection::write_edge_preview(lava::index frame)
 
         edge_preview_buffer->flush();
 
-        this->edge_preview_line_count[layer] = edge_count;
+        this->edge_preview_count[layer] = edge_count;
     }
     
     return true;
@@ -1369,24 +1517,41 @@ bool MeshBasedReprojection::process_edge_buffer_copy(VkCommandBuffer command_buf
 {
     glm::uvec2 resolution = this->get_headset()->get_framebuffer_resolution();
 
-    std::array<VkImageMemoryBarrier, 2> image_barriers;
+    std::array<VkImageMemoryBarrier, 4> image_barriers;
 
     for (uint32_t layer = 0; layer < 2; layer++)
     {
-        image_barriers[layer].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
-        image_barriers[layer].pNext = nullptr;
-        image_barriers[layer].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
-        image_barriers[layer].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
-        image_barriers[layer].oldLayout = VK_IMAGE_LAYOUT_GENERAL;
-        image_barriers[layer].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
-        image_barriers[layer].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        image_barriers[layer].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        image_barriers[layer].image = this->layer_edge_buffers[layer]->get();
-        image_barriers[layer].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-        image_barriers[layer].subresourceRange.baseMipLevel = 0;
-        image_barriers[layer].subresourceRange.levelCount = 1;
-        image_barriers[layer].subresourceRange.baseArrayLayer = 0;
-        image_barriers[layer].subresourceRange.layerCount = 1;
+        VkImageMemoryBarrier& depth_barrier = image_barriers[layer * 2];
+        depth_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+        depth_barrier.pNext = nullptr;
+        depth_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        depth_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+        depth_barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+        depth_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+        depth_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        depth_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        depth_barrier.image = this->layer_depth_buffers[layer]->get();
+        depth_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+        depth_barrier.subresourceRange.baseMipLevel = 0;
+        depth_barrier.subresourceRange.levelCount = 1;
+        depth_barrier.subresourceRange.baseArrayLayer = 0;
+        depth_barrier.subresourceRange.layerCount = 1;
+
+        VkImageMemoryBarrier& edge_barrier = image_barriers[layer * 2 + 1];
+        edge_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+        edge_barrier.pNext = nullptr;
+        edge_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
+        edge_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+        edge_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
+        edge_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+        edge_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        edge_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        edge_barrier.image = this->layer_edge_buffers[layer]->get();
+        edge_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+        edge_barrier.subresourceRange.baseMipLevel = 0;
+        edge_barrier.subresourceRange.levelCount = 1;
+        edge_barrier.subresourceRange.baseArrayLayer = 0;
+        edge_barrier.subresourceRange.layerCount = 1;
     }
 
     vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, image_barriers.size(), image_barriers.data());
@@ -1402,35 +1567,42 @@ bool MeshBasedReprojection::process_edge_buffer_copy(VkCommandBuffer command_buf
             return true;
         }
 
-        VkBufferImageCopy image_copy;
-        image_copy.bufferOffset = 0;
-        image_copy.bufferRowLength = 0;
-        image_copy.bufferImageHeight = 0;
-        image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-        image_copy.imageSubresource.mipLevel = 0;
-        image_copy.imageSubresource.baseArrayLayer = 0;
-        image_copy.imageSubresource.layerCount = 1;
-        image_copy.imageOffset.x = 0;
-        image_copy.imageOffset.y = 0;
-        image_copy.imageOffset.z = 0;
-        image_copy.imageExtent.width = resolution.x;
-        image_copy.imageExtent.height = resolution.y;
-        image_copy.imageExtent.depth = 1;
-
-        vkCmdCopyImageToBuffer(command_buffer, this->layer_edge_buffers[layer]->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, edge_buffer->image_buffer->get(), 1, &image_copy);
-
-        VkBufferMemoryBarrier buffer_barrier;
-        buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
-        buffer_barrier.pNext = 0;
-        buffer_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
-        buffer_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
-        buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        buffer_barrier.buffer = edge_buffer->image_buffer->get();
-        buffer_barrier.offset = 0;
-        buffer_barrier.size = VK_WHOLE_SIZE;
-
-        vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1, &buffer_barrier, 0, nullptr);
+        VkBufferImageCopy depth_copy;
+        depth_copy.bufferOffset = 0;
+        depth_copy.bufferRowLength = 0;
+        depth_copy.bufferImageHeight = 0;
+        depth_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+        depth_copy.imageSubresource.mipLevel = 0;
+        depth_copy.imageSubresource.baseArrayLayer = 0;
+        depth_copy.imageSubresource.layerCount = 1;
+        depth_copy.imageOffset.x = 0;
+        depth_copy.imageOffset.y = 0;
+        depth_copy.imageOffset.z = 0;
+        depth_copy.imageExtent.width = resolution.x;
+        depth_copy.imageExtent.height = resolution.y;
+        depth_copy.imageExtent.depth = 1;
+
+        VkBufferImageCopy edge_copy = depth_copy;
+        edge_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+        vkCmdCopyImageToBuffer(command_buffer, this->layer_depth_buffers[layer]->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, edge_buffer->depth_image_buffer->get(), 1, &depth_copy);
+        vkCmdCopyImageToBuffer(command_buffer, this->layer_edge_buffers[layer]->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, edge_buffer->edge_image_buffer->get(), 1, &edge_copy);
+
+        std::array<VkBufferMemoryBarrier, 2> buffer_barriers;
+        buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+        buffer_barriers[0].pNext = 0;
+        buffer_barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+        buffer_barriers[0].dstAccessMask = VK_ACCESS_HOST_READ_BIT;
+        buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        buffer_barriers[0].buffer = edge_buffer->depth_image_buffer->get();
+        buffer_barriers[0].offset = 0;
+        buffer_barriers[0].size = VK_WHOLE_SIZE;
+
+        buffer_barriers[1] = buffer_barriers[0];
+        buffer_barriers[1].buffer = edge_buffer->edge_image_buffer->get();
+
+        vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, buffer_barriers.size(), buffer_barriers.data(), 0, nullptr);
         
         VkFence fence = edge_buffer->fence->get();
 
@@ -1485,7 +1657,7 @@ bool MeshBasedReprojection::process_edge_buffer_copy(VkCommandBuffer command_buf
 void MeshBasedReprojection::process_edge_preview_pass(VkCommandBuffer command_buffer)
 {
     uint32_t frame_index = this->get_application()->get_frame_index();
-    uint32_t edge_line_count = this->edge_preview_line_count[this->layer_index] * 2;
+    uint32_t edge_count = this->edge_preview_count[this->layer_index];
     VkBuffer edge_preview_buffer = this->edge_preview_buffers[this->layer_index][frame_index]->get();
 
     glsl::MeshBasedReprojectionEdgePreviewParameters parameters;
@@ -1496,7 +1668,7 @@ void MeshBasedReprojection::process_edge_preview_pass(VkCommandBuffer command_bu
     VkDeviceSize offset = 0;
     vkCmdBindVertexBuffers(command_buffer, 0, 1, &edge_preview_buffer, &offset);
 
-    vkCmdDraw(command_buffer, edge_line_count, 1, 0, 0);
+    vkCmdDraw(command_buffer, edge_count * 2, 1, 0, 0);
 }
 
 bool MeshBasedReprojection::acquire_edge_buffer(MeshBasedReprojectionEdgeBuffer::Ptr& edge_buffer)
@@ -1525,14 +1697,16 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
 {
     std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
 
-    if(!edge_buffer->quad_tree->fill(edge_buffer->image_buffer))
+    if(!edge_buffer->quad_tree->fill(edge_buffer->edge_image_buffer))
     {
         lava::log()->error("Mesh Based Reprojection: Can't fill quad tree!");
 
         return;
     }
 
+    std::vector<glm::ivec2> edge_points;
     edge_buffer->edges.clear();
+    edge_buffer->triangles.clear();
 
     while (true)
     {
@@ -1544,7 +1718,7 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
             break;
         }
 
-        if (value < this->edge_detection_min_value)
+        if (value < this->edge_extraction_min_value)
         {
             break;
         }
@@ -1554,7 +1728,7 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
             break;
         }
 
-        this->edge_points.clear();
+        edge_points.clear();
         glm::ivec2 end = start;
  
         while (true)
@@ -1566,7 +1740,7 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
                 break;
             }
 
-            if (value < this->edge_detection_min_value)
+            if (value < this->edge_extraction_min_value)
             {
                 break;
             }
@@ -1576,21 +1750,21 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
                 break;
             }
 
-            this->edge_points.push_back(next);
+            edge_points.push_back(next);
             end = next;
         }
 
-        if (this->edge_points.size() > 10)
+        if (edge_points.size() > this->edge_extraction_min_length)
         {
             int32_t start_index = 0;
             int32_t end_index = 0;
 
-            while (start_index < this->edge_points.size() - 1)
+            while (start_index < edge_points.size() - 1)
             {
-                for (end_index = this->edge_points.size() - 1; end_index > start_index; end_index--)
+                for (end_index = edge_points.size() - 1; end_index > start_index; end_index--)
                 {
-                    glm::ivec2 edge_start = this->edge_points[start_index];
-                    glm::ivec2 edge_end = this->edge_points[end_index];
+                    glm::ivec2 edge_start = edge_points[start_index];
+                    glm::ivec2 edge_end = edge_points[end_index];
 
                     glm::vec2 edge_direction = glm::normalize(glm::vec2(edge_end - edge_start));
                     glm::vec2 edge_normal = glm::vec2(-edge_direction.y, edge_direction.x);
@@ -1599,10 +1773,10 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
 
                     for (uint32_t check_index = start_index + 1; check_index < end_index - 1; check_index++)
                     {
-                        glm::ivec2 edge_point = this->edge_points[check_index];
+                        glm::ivec2 edge_point = edge_points[check_index];
                         float edge_distance = glm::abs(glm::dot(glm::vec2(edge_point - edge_start), edge_normal));
 
-                        if (edge_distance > this->edge_detection_min_distance)
+                        if (edge_distance > this->edge_extraction_min_distance)
                         {
                             outside = true;
 
@@ -1617,8 +1791,8 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
                 }
 
                 MeshBasedReprojectionEdge edge;
-                edge.start = this->edge_points[start_index];
-                edge.end = this->edge_points[end_index];
+                edge.start = edge_points[start_index];
+                edge.end = edge_points[end_index];
 
                 edge_buffer->edges.push_back(edge);
 
@@ -1627,17 +1801,53 @@ void MeshBasedReprojection::worker_process_edge_buffer(uint32_t layer, MeshBased
         }
     }
 
-    this->edge_points.clear();
+    glm::vec2 resolution = this->get_headset()->get_framebuffer_resolution();
+
+    Point2 border_point1 = Point2(0.0, 0.0);
+    Point2 border_point2 = Point2(0.0, resolution.y);
+    Point2 border_point3 = Point2(resolution.x, resolution.y);
+    Point2 border_point4 = Point2(resolution.x, 0.0);
+
+    ConstrainedTriangulation triangluation;
+    triangluation.insert_constraint(border_point1, border_point2);
+    triangluation.insert_constraint(border_point2, border_point3);
+    triangluation.insert_constraint(border_point3, border_point4);
+    triangluation.insert_constraint(border_point4, border_point1);
+
+    for (const MeshBasedReprojectionEdge& edge : edge_buffer->edges)
+    {
+        Point2 edge_start = Point2(edge.start.x, edge.start.y);
+        Point2 edge_end = Point2(edge.end.x, edge.end.y);
+
+        triangluation.insert_constraint(edge_start, edge_end);
+    }
+
+    for (FaceHandle face_handle : triangluation.all_face_handles())
+    {
+        Point2 point1 = face_handle->vertex(0)->point();
+        Point2 point2 = face_handle->vertex(1)->point();
+        Point2 point3 = face_handle->vertex(2)->point();
+
+        //TODO: Add depth
+
+        MeshBasedReprojectionTriangle triangle;
+        triangle.point1 = glm::vec3(point1.x(), point1.y(), 0.0f);
+        triangle.point2 = glm::vec3(point2.x(), point2.y(), 0.0f);
+        triangle.point3 = glm::vec3(point3.x(), point3.y(), 0.0f);
+
+        edge_buffer->triangles.push_back(triangle);
+    }
 
     std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
     double time = std::chrono::duration_cast<std::chrono::duration<double, std::chrono::milliseconds::period>>(end - start).count();
 
-    lava::log()->debug("Edge Count: " + std::to_string(edge_buffer->edges.size()));
-
     std::unique_lock<std::mutex> lock(this->edge_buffer_mutex);
     this->edge_preview_list[layer].clear();
     this->edge_preview_list[layer].insert(this->edge_preview_list[layer].begin(), edge_buffer->edges.begin(), edge_buffer->edges.end());
 
+    this->triangle_preview_list[layer].clear();
+    this->triangle_preview_list[layer].insert(this->triangle_preview_list[layer].begin(), edge_buffer->triangles.begin(), edge_buffer->triangles.end());
+
     this->edge_buffer_process_count += 1;
     this->edge_buffer_process_time_sum += time;
     lock.unlock();
diff --git a/src/strategy/mesh_based_reprojection.hpp b/src/strategy/mesh_based_reprojection.hpp
index 234efdb97974f5ec22ecdeb7157cfbe076442c67..cc5de2e122149d9c8463873c38598619733461d5 100644
--- a/src/strategy/mesh_based_reprojection.hpp
+++ b/src/strategy/mesh_based_reprojection.hpp
@@ -10,14 +10,15 @@
 #include "utility/statistic.hpp"
 
 #define MESH_BASED_REPROJECTION_EDGE_BUFFER_COUNT 32
-#define MESH_BASED_REPROJECTION_EDGE_PEWVIEW_BUFFER_SIZE 1024
+#define MESH_BASED_REPROJECTION_EDGE_PEWVIEW_BUFFER_SIZE 2048
 
 enum MeshBasedReprojectionOverlay
 {
     MESH_BASED_REPROJECTION_OVERLAY_COLOR,
     MESH_BASED_REPROJECTION_OVERLAY_NORMAL,
     MESH_BASED_REPROJECTION_OVERLAY_EDGE_DETECTION,
-    MESH_BASED_REPROJECTION_OVERLAY_EDGE_PREVIEW
+    MESH_BASED_REPROJECTION_OVERLAY_EDGE_PREVIEW,
+    MESH_BASED_REPROJECTION_OVERLAY_TRIANGLE_PREVIEW
 };
 
 struct MeshBasedReprojectionEdge
@@ -26,6 +27,13 @@ struct MeshBasedReprojectionEdge
     glm::ivec2 end;
 };
 
+struct MeshBasedReprojectionTriangle
+{
+    glm::vec3 point1;
+    glm::vec3 point2;
+    glm::vec3 point3;
+};
+
 class MeshBasedReprojectionQuadTreeLevel
 {
 public:
@@ -70,14 +78,16 @@ public:
     typedef std::shared_ptr<MeshBasedReprojectionEdgeBuffer> Ptr;
 
 public:
-    lava::buffer::ptr image_buffer;
-
     VkSemaphore semaphore = VK_NULL_HANDLE;
     ExternFence::Ptr fence;
 
-    std::vector<MeshBasedReprojectionEdge> edges;
+    lava::buffer::ptr depth_image_buffer;
+    lava::buffer::ptr edge_image_buffer;
 
     MeshBasedReprojectionQuadTree::Ptr quad_tree;
+
+    std::vector<MeshBasedReprojectionEdge> edges;
+    std::vector<MeshBasedReprojectionTriangle> triangles;
 };
 
 class MeshBasedReprojection : public StereoStrategy
@@ -110,15 +120,19 @@ private:
     bool create_edge_detection_pipeline();
     bool create_edge_preview_pass();
     bool create_edge_preview_pipeline();
+    bool create_triangle_preview_pass();
+    bool create_triangle_preview_pipeline();
 
     bool build_projection();
     bool write_transform(lava::index frame);
     bool write_edge_preview(lava::index frame);
+    bool write_triangle_preview(lava::index frame);
 
     void process_layer_pass(VkCommandBuffer command_buffer);
     void process_edge_detection_pass(VkCommandBuffer command_buffer);
     bool process_edge_buffer_copy(VkCommandBuffer command_buffer);
     void process_edge_preview_pass(VkCommandBuffer command_buffer);
+    void process_triangle_preview_pass(VkCommandBuffer command_buffer);
 
     bool acquire_edge_buffer(MeshBasedReprojectionEdgeBuffer::Ptr& edge_buffer);
     void release_edge_buffer(MeshBasedReprojectionEdgeBuffer::Ptr edge_buffer);
@@ -135,8 +149,9 @@ private:
     float edge_detection_laplacian_threshold = 0.01f;
     float edge_detection_normal_scale = 0.0f;
 
-    float edge_detection_min_value = 0.01f;
-    float edge_detection_min_distance = 1.0f;
+    uint32_t edge_extraction_min_length = 10;
+    float edge_extraction_min_value = 0.01f;
+    float edge_extraction_min_distance = 1.0f;
 
 private:
     asio::thread_pool worker_pool;
@@ -149,19 +164,21 @@ private:
 
     std::vector<lava::buffer::ptr> transform_buffers;
     std::array<std::vector<lava::buffer::ptr>, 2> edge_preview_buffers;
+    std::array<std::vector<lava::buffer::ptr>, 2> triangle_preview_buffers;
     std::array<lava::image::ptr, 2> layer_depth_buffers;
     std::array<lava::image::ptr, 2> layer_normal_buffers;
     std::array<lava::image::ptr, 2> layer_edge_buffers; 
 
     std::mutex edge_buffer_mutex;
     std::vector<MeshBasedReprojectionEdgeBuffer::Ptr> edge_buffers;
-    std::vector<MeshBasedReprojectionEdgeBuffer::Ptr> edge_buffer_pool;      //NOTE: Protected by edge_buffer_mutex
-    std::array<std::vector<MeshBasedReprojectionEdge>, 2> edge_preview_list; //NOTE: Protected by edge_buffer_mutex
-    std::vector<glm::ivec2> edge_points;                                     //NOTE: Owned by worker_thread
-    uint32_t edge_buffer_process_count = 0;                                  //NOTE: Protected by edge_buffer_mutex
-    double edge_buffer_process_time_sum = 0.0;                               //NOTE: Protected by edge_buffer_mutex
+    std::vector<MeshBasedReprojectionEdgeBuffer::Ptr> edge_buffer_pool;              //NOTE: Protected by edge_buffer_mutex
+    std::array<std::vector<MeshBasedReprojectionEdge>, 2> edge_preview_list;         //NOTE: Protected by edge_buffer_mutex
+    std::array<std::vector<MeshBasedReprojectionTriangle>, 2> triangle_preview_list; //NOTE: Protected by edge_buffer_mutex
+    uint32_t edge_buffer_process_count = 0;                                          //NOTE: Protected by edge_buffer_mutex
+    double edge_buffer_process_time_sum = 0.0;                                       //NOTE: Protected by edge_buffer_mutex
     
-    std::array<uint32_t, 2> edge_preview_line_count;
+    std::array<uint32_t, 2> edge_preview_count;
+    std::array<uint32_t, 2> triangle_preview_count;
 
     lava::descriptor::pool::ptr descriptor_pool;
     lava::descriptor::ptr transform_descriptor;
@@ -184,6 +201,10 @@ private:
     lava::pipeline_layout::ptr edge_preview_pipeline_layout;
     lava::graphics_pipeline::ptr edge_preview_pipeline;
 
+    lava::render_pass::ptr triangle_preview_pass;
+    lava::pipeline_layout::ptr triangle_preview_pipeline_layout;
+    lava::graphics_pipeline::ptr triangle_preview_pipeline;
+
 private:
     Statistic::Ptr statistic_edge_buffer_time;
 };