diff --git a/CMakeLists.txt b/CMakeLists.txt
index d17699fdc0bfc37000c343769f5f215e170349f9..526401edd27d286f50fa3d589c6929c353527d4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,8 +30,11 @@ endif()
 add_subdirectory(qpong_core)
 include_directories(qpong_core)
 
-# Dear ImGui based application
-add_subdirectory(imgui_app)
+# Dear ImGui and SDL based application
+add_subdirectory(imgui_sdl_app)
+
+# Dear ImGui and GLFW based application
+add_subdirectory(imgui_glfw_app)
 
 # Add dir with gtk qpong app
 add_subdirectory(gtk_qpong_app)
diff --git a/README.md b/README.md
index 44b8087c6c5e910c074e8287dea7cb8a002208aa..2a2e31e28f742baec3a3ada1a00a3f0fedbe4f60 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,10 @@ Dependencies:
    * cmake
    * libgtkmm-3.0-dev
    * libfftw3-dev
+   * libsdl2-dev
+   * libglfw3-dev
+   * libglm-dev
+
 
 ---
 
diff --git a/imgui_glfw_app/CMakeLists.txt b/imgui_glfw_app/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a4bee75a9f5dbaa4b24df409505880d1a40b2a17
--- /dev/null
+++ b/imgui_glfw_app/CMakeLists.txt
@@ -0,0 +1,83 @@
+
+# Dear ImGui include dirs
+include_directories(
+    ../libs/imgui 
+    ../libs/imgui/examples 
+    ../libs/imgui/examples/libs/gl3w
+)
+
+# Main Dear ImGui src files.
+set(
+    dear_im_gui_srcs
+    ../libs/imgui/imgui.cpp
+    ../libs/imgui/imgui_draw.cpp
+    ../libs/imgui/imgui_widgets.cpp
+)
+
+# Impl files from Dear ImGui.
+set(
+    dear_im_gui_impl_srcs
+    ../libs/imgui/examples/imgui_impl_glfw.cpp
+    ../libs/imgui/examples/imgui_impl_opengl3.cpp
+)
+
+# Dear ImGui lib
+add_library(
+    dear_im_gui_glfw
+    ${dear_im_gui_srcs}
+    ${dear_im_gui_impl_srcs}
+    ../libs/imgui/examples/libs/gl3w/GL/gl3w.c
+)
+
+# Application base on Dear ImGui
+add_executable(
+    imgui_glfw_playground.app 
+    imgui_glfw_playground.cpp
+    LoadShaders.cpp
+)
+
+add_custom_command(TARGET imgui_glfw_playground.app PRE_BUILD
+                   COMMAND ${CMAKE_COMMAND} -E copy_directory
+                       ${CMAKE_SOURCE_DIR}/imgui_glfw_app/shaders $<TARGET_FILE_DIR:imgui_glfw_playground.app>)
+
+
+pkg_check_modules(GLFW glfw3)
+include_directories(${GLFW_INCLUDE_DIRS})
+message(${GLFW_LIBRARIES})
+
+# Link everything together
+target_link_libraries(
+    imgui_glfw_playground.app 
+    dear_im_gui_glfw
+    qpong_core
+    ${GLFW_LIBRARIES}
+)
+
+# Include macOS specific things.
+if(APPLE)
+    # dependencies for macOS
+    # brew install glfw
+    # brew install glm
+    find_library(COCOA_LIBRARY Cocoa REQUIRED)
+    find_library(IOKIT_LIBRARY IOKit REQUIRED)
+    find_library(COREVID_LIBRARY CoreVideo REQUIRED)
+    find_library(OPENGL_LIBRARY OpenGL REQUIRED)
+
+    message(${COCOA_LIBRARY})
+    message(${IOKIT_LIBRARY})
+    message(${COREVID_LIBRARY})
+    message(${OPENGL_LIBRARY})
+    
+    target_link_libraries(
+        imgui_glfw_playground.app
+        ${COCOA_LIBRARY}
+        ${IOKIT_LIBRARY}
+        ${COREVID_LIBRARY}
+        ${OPENGL_LIBRARY}
+    )
+else(APPLE)
+    find_package(OpenGL REQUIRED)
+    target_link_libraries(imgui_glfw_playground.app OpenGL::GL ${CMAKE_DL_LIBS})
+endif()
+
+
diff --git a/imgui_glfw_app/LoadShaders.cpp b/imgui_glfw_app/LoadShaders.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..36feb49be346efb6fc1d3146eca0a575df8af3b9
--- /dev/null
+++ b/imgui_glfw_app/LoadShaders.cpp
@@ -0,0 +1,96 @@
+#include "LoadShaders.hpp"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <GL/gl3w.h>
+
+unsigned int LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
+
+	// Create the shaders
+	unsigned int VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
+	unsigned int FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
+
+	// Read the Vertex Shader code from the file
+	std::string VertexShaderCode;
+	std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
+	if(VertexShaderStream.is_open()){
+		std::stringstream sstr;
+		sstr << VertexShaderStream.rdbuf();
+		VertexShaderCode = sstr.str();
+		VertexShaderStream.close();
+	}else{
+		printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
+		getchar();
+		return 0;
+	}
+
+	// Read the Fragment Shader code from the file
+	std::string FragmentShaderCode;
+	std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
+	if(FragmentShaderStream.is_open()){
+		std::stringstream sstr;
+		sstr << FragmentShaderStream.rdbuf();
+		FragmentShaderCode = sstr.str();
+		FragmentShaderStream.close();
+	}
+
+	GLint Result = GL_FALSE;
+	int InfoLogLength;
+
+	// Compile Vertex Shader
+	printf("Compiling shader : %s\n", vertex_file_path);
+	char const * VertexSourcePointer = VertexShaderCode.c_str();
+	glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
+	glCompileShader(VertexShaderID);
+
+	// Check Vertex Shader
+	glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
+	glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+	if ( InfoLogLength > 0 ){
+		std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
+		glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
+		printf("%s\n", &VertexShaderErrorMessage[0]);
+	}
+
+	// Compile Fragment Shader
+	printf("Compiling shader : %s\n", fragment_file_path);
+	char const * FragmentSourcePointer = FragmentShaderCode.c_str();
+	glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
+	glCompileShader(FragmentShaderID);
+
+	// Check Fragment Shader
+	glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
+	glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+	if ( InfoLogLength > 0 ){
+		std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
+		glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
+		printf("%s\n", &FragmentShaderErrorMessage[0]);
+	}
+
+	// Link the program
+	printf("Linking program\n");
+	GLuint ProgramID = glCreateProgram();
+	glAttachShader(ProgramID, VertexShaderID);
+	glAttachShader(ProgramID, FragmentShaderID);
+	glLinkProgram(ProgramID);
+
+	// Check the program
+	glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
+	glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+	if ( InfoLogLength > 0 ){
+		std::vector<char> ProgramErrorMessage(InfoLogLength+1);
+		glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
+		printf("%s\n", &ProgramErrorMessage[0]);
+	}
+	
+	glDetachShader(ProgramID, VertexShaderID);
+	glDetachShader(ProgramID, FragmentShaderID);
+	
+	glDeleteShader(VertexShaderID);
+	glDeleteShader(FragmentShaderID);
+
+	return ProgramID;
+}
diff --git a/imgui_glfw_app/LoadShaders.hpp b/imgui_glfw_app/LoadShaders.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..69b61c6057829fd51044929d85afcddff800fa9b
--- /dev/null
+++ b/imgui_glfw_app/LoadShaders.hpp
@@ -0,0 +1,7 @@
+/// @brief LoadShader from filesystem.
+///
+/// @param vertex_file_path Path to the vertex shader file
+/// @param fragment_file_path Path to the fragment shader file
+/// @return Returns the id of the shader
+///
+unsigned int LoadShaders(const char * vertex_file_path,const char * fragment_file_path);
\ No newline at end of file
diff --git a/imgui_glfw_app/imgui_glfw_playground.cpp b/imgui_glfw_app/imgui_glfw_playground.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04a49d669852ba5eeb60941af78d776a0e975c6f
--- /dev/null
+++ b/imgui_glfw_app/imgui_glfw_playground.cpp
@@ -0,0 +1,348 @@
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_opengl3.h"
+#include <stdio.h>
+
+#include <GL/gl3w.h>            // Initialize with gl3wInit()
+#include <GLFW/glfw3.h>
+
+#include <iostream>
+
+#include "LoadShaders.hpp"
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+static void glfw_error_callback(int error, const char* description)
+{
+    fprintf(stderr, "Glfw Error %d: %s\n", error, description);
+}
+
+void drawGui()
+{
+    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+    static float f = 0.0f;
+    static int counter = 0;
+
+    ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.
+
+    ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)
+
+    ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f
+    ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+    if (ImGui::Button("Button")){                           // Buttons return true when clicked (most widgets return true when edited/activated)
+        counter++;
+    }
+    ImGui::SameLine();
+    ImGui::Text("counter = %d", counter);
+
+    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+    ImGui::End();
+}
+
+int main(int, char**)
+{
+    // Setup window
+    glfwSetErrorCallback(glfw_error_callback);
+    if (!glfwInit())
+        return 1;
+
+    // Decide GL+GLSL versions
+#if __APPLE__
+    // GL 3.2 + GLSL 150
+    const char* glsl_version = "#version 150";
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
+    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // Required on Mac
+#else
+    // GL 3.0 + GLSL 130
+    const char* glsl_version = "#version 130";
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+#endif
+
+    // Create window with graphics context
+    GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3 example", NULL, NULL);
+    if (window == NULL)
+        return 1;
+    glfwMakeContextCurrent(window);
+    glfwSwapInterval(1); // Enable vsync
+
+    // Initialize OpenGL loader
+    bool err = gl3wInit() != 0;
+    if (err)
+    {
+        fprintf(stderr, "Failed to initialize OpenGL loader!\n");
+        return 1;
+    }
+
+    // Setup Dear ImGui context
+    IMGUI_CHECKVERSION();
+    ImGui::CreateContext();
+    ImGuiIO& io = ImGui::GetIO(); (void)io;
+
+    // Setup Dear ImGui style
+    ImGui::StyleColorsDark();
+
+    // Setup Platform/Renderer bindings
+    ImGui_ImplGlfw_InitForOpenGL(window, true);
+    ImGui_ImplOpenGL3_Init(glsl_version);
+
+
+    // unsigned int vertexArrayId {};          // Store a vertex array id.
+    // glGenVertexArrays(1, &vertexArrayId);   // Receive a id.
+    // glBindVertexArray(vertexArrayId);       // Bind that id.
+
+    static const float g_vertex_buffer_data_triangle[] = {
+        -1.0f, -1.0f, 0.0f,
+        1.0f, -1.0f, 0.0f,
+        0.0f,  1.0f, 0.0f,
+    };
+
+    static GLfloat g_color_buffer_data_triangle[12*3*3];
+    for (int v = 0; v < 12*3 ; v++){
+        g_color_buffer_data_triangle[3*v+0] = 0.1f;
+        g_color_buffer_data_triangle[3*v+1] = 0.5f;
+        g_color_buffer_data_triangle[3*v+2] = 0.7f;
+    }
+
+    static const GLfloat g_vertex_buffer_data_cube[] = {
+    -1.0f,-1.0f,-1.0f, // triangle 1 : begin
+    -1.0f,-1.0f, 1.0f,
+    -1.0f, 1.0f, 1.0f, // triangle 1 : end
+    1.0f, 1.0f,-1.0f, // triangle 2 : begin
+    -1.0f,-1.0f,-1.0f,
+    -1.0f, 1.0f,-1.0f, // triangle 2 : end
+    1.0f,-1.0f, 1.0f,
+    -1.0f,-1.0f,-1.0f,
+    1.0f,-1.0f,-1.0f,
+    1.0f, 1.0f,-1.0f,
+    1.0f,-1.0f,-1.0f,
+    -1.0f,-1.0f,-1.0f,
+    -1.0f,-1.0f,-1.0f,
+    -1.0f, 1.0f, 1.0f,
+    -1.0f, 1.0f,-1.0f,
+    1.0f,-1.0f, 1.0f,
+    -1.0f,-1.0f, 1.0f,
+    -1.0f,-1.0f,-1.0f,
+    -1.0f, 1.0f, 1.0f,
+    -1.0f,-1.0f, 1.0f,
+    1.0f,-1.0f, 1.0f,
+    1.0f, 1.0f, 1.0f,
+    1.0f,-1.0f,-1.0f,
+    1.0f, 1.0f,-1.0f,
+    1.0f,-1.0f,-1.0f,
+    1.0f, 1.0f, 1.0f,
+    1.0f,-1.0f, 1.0f,
+    1.0f, 1.0f, 1.0f,
+    1.0f, 1.0f,-1.0f,
+    -1.0f, 1.0f,-1.0f,
+    1.0f, 1.0f, 1.0f,
+    -1.0f, 1.0f,-1.0f,
+    -1.0f, 1.0f, 1.0f,
+    1.0f, 1.0f, 1.0f,
+    -1.0f, 1.0f, 1.0f,
+    1.0f,-1.0f, 1.0f
+};
+
+static const GLfloat g_color_buffer_data_cube[] = {
+    0.583f,  0.771f,  0.014f,
+    0.609f,  0.115f,  0.436f,
+    0.327f,  0.483f,  0.844f,
+    0.822f,  0.569f,  0.201f,
+    0.435f,  0.602f,  0.223f,
+    0.310f,  0.747f,  0.185f,
+    0.597f,  0.770f,  0.761f,
+    0.559f,  0.436f,  0.730f,
+    0.359f,  0.583f,  0.152f,
+    0.483f,  0.596f,  0.789f,
+    0.559f,  0.861f,  0.639f,
+    0.195f,  0.548f,  0.859f,
+    0.014f,  0.184f,  0.576f,
+    0.771f,  0.328f,  0.970f,
+    0.406f,  0.615f,  0.116f,
+    0.676f,  0.977f,  0.133f,
+    0.971f,  0.572f,  0.833f,
+    0.140f,  0.616f,  0.489f,
+    0.997f,  0.513f,  0.064f,
+    0.945f,  0.719f,  0.592f,
+    0.543f,  0.021f,  0.978f,
+    0.279f,  0.317f,  0.505f,
+    0.167f,  0.620f,  0.077f,
+    0.347f,  0.857f,  0.137f,
+    0.055f,  0.953f,  0.042f,
+    0.714f,  0.505f,  0.345f,
+    0.783f,  0.290f,  0.734f,
+    0.722f,  0.645f,  0.174f,
+    0.302f,  0.455f,  0.848f,
+    0.225f,  0.587f,  0.040f,
+    0.517f,  0.713f,  0.338f,
+    0.053f,  0.959f,  0.120f,
+    0.393f,  0.621f,  0.362f,
+    0.673f,  0.211f,  0.457f,
+    0.820f,  0.883f,  0.371f,
+    0.982f,  0.099f,  0.879f
+};
+
+    unsigned int vertexBufferCube {};
+    glGenBuffers(1, &vertexBufferCube);
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferCube);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data_cube), g_vertex_buffer_data_cube, GL_STATIC_DRAW);
+
+    unsigned int colorBufferCube {};
+    glGenBuffers(1, &colorBufferCube);
+    glBindBuffer(GL_ARRAY_BUFFER, colorBufferCube);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data_cube), g_color_buffer_data_cube, GL_STATIC_DRAW);
+
+    unsigned int vertexBufferTriangle {};
+    glGenBuffers(1, &vertexBufferTriangle);
+    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferTriangle);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data_triangle), g_vertex_buffer_data_triangle, GL_STATIC_DRAW);
+
+    unsigned int colorBufferTriangle {};
+    glGenBuffers(1, &colorBufferTriangle);
+    glBindBuffer(GL_ARRAY_BUFFER, colorBufferTriangle);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data_triangle), g_color_buffer_data_triangle, GL_STATIC_DRAW);
+
+    unsigned int shaderId = LoadShaders("SimpleVertexShader.glsl", "FragmentShader.glsl");
+    
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LESS);
+
+
+    int width, height;
+    glfwGetFramebufferSize(window, &width, &height);
+
+    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
+    glm::mat4 Projection = glm::perspective(glm::radians(150.0f), (float) width / (float)height, 0.1f, 100.0f);
+    glm::mat4 ProjectionTriangle = glm::perspective(glm::radians(30.0f), (float) width / (float)height, 0.1f, 100.0f);
+    
+    // Camera matrix
+    glm::mat4 View = glm::lookAt(
+        glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
+        glm::vec3(0,0,0), // and looks at the origin
+        glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
+        );
+    
+    // Model matrix : an identity matrix (model will be at the origin)
+    glm::mat4 Model = glm::mat4(1.0f);
+    // Our ModelViewProjection : multiplication of our 3 matrices
+    glm::mat4 mvp = Projection * View * Model; // Remember, matrix multiplication is the other way around
+    glm::mat4 mvpTriangle = ProjectionTriangle * View * Model;
+
+    // Get a handle for our "MVP" uniform
+    // Only during the initialisation
+    // GLuint MatrixID = glGetUniformLocation(shaderId, "MVP");
+    // GLuint MatrixIDT = glGetUniformLocation(shaderId, "MVPT");
+
+
+    unsigned int MatrixIDCube = glGetUniformLocation(shaderId, "MVP");
+    unsigned int MatrixIDTriangle = glGetUniformLocation(shaderId, "MVPT");
+
+    // Main loop
+    while (!glfwWindowShouldClose(window))
+    {
+        glfwPollEvents();
+
+        // Start the Dear ImGui frame
+        ImGui_ImplOpenGL3_NewFrame();
+        ImGui_ImplGlfw_NewFrame();
+        ImGui::NewFrame();
+      
+        // Draw GUI with Dear ImGui. 
+        drawGui();
+        
+        // Rendering
+        ImGui::Render();
+        {
+            // int width, height;
+            glfwGetFramebufferSize(window, &width, &height);
+            glViewport(0, 0, width, height);
+            glClearColor(0.1f, 0.2f, 0.2f, 1.0f);
+            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+            
+            // Send our transformation to the currently bound shader, in the "MVP" uniform
+            // This is done in the main loop since each model will have a different MVP matrix (At least for the M part)
+            glUniformMatrix4fv(MatrixIDCube, 1, GL_FALSE, &mvp[0][0]);
+            glUseProgram(shaderId);
+
+            glEnableVertexAttribArray(0);
+            glBindBuffer(GL_ARRAY_BUFFER, vertexBufferCube);
+            glVertexAttribPointer(
+                0,
+                3,
+                GL_FLOAT,
+                GL_FALSE,
+                0,
+                (void*)0
+            );
+
+            glEnableVertexAttribArray(1);
+            glBindBuffer(GL_ARRAY_BUFFER, colorBufferCube);
+            glVertexAttribPointer(
+                1,
+                3,
+                GL_FLOAT,
+                GL_FALSE,
+                0,
+                (void*)0
+            );
+
+            // glUniformMatrix4fv(MatrixIDCube, 1, GL_FALSE, &mvp[0][0]);
+            glDrawArrays(GL_TRIANGLES, 0, sizeof(g_vertex_buffer_data_cube)/3);
+
+
+            // glDisableVertexAttribArray(0);
+            // glDisableVertexAttribArray(1);
+
+
+            // glUniformMatrix4fv(MatrixIDTriangle, 1, GL_FALSE, &mvpTriangle[0][0]);
+            // glUseProgram(shaderId);
+            // glEnableVertexAttribArray(0);
+
+            // glBindBuffer(GL_ARRAY_BUFFER, vertexBufferTriangle);
+            // glVertexAttribPointer(
+            //     0,
+            //     3,
+            //     GL_FLOAT,
+            //     GL_FALSE,
+            //     0,
+            //     (void*)0
+            // );
+            // glEnableVertexAttribArray(1);
+
+            // glBindBuffer(GL_ARRAY_BUFFER, colorBufferTriangle);
+            // glVertexAttribPointer(
+            //     1,
+            //     3,
+            //     GL_FLOAT,
+            //     GL_FALSE,
+            //     0,
+            //     (void*)0
+            // );
+
+           
+            // glDrawArrays(GL_TRIANGLES, 0, sizeof(g_vertex_buffer_data_triangle)/3);
+
+            glDisableVertexAttribArray(0);
+            glDisableVertexAttribArray(1);
+
+        }
+
+
+        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+        glfwSwapBuffers(window);
+    }
+
+    // Cleanup
+    ImGui_ImplOpenGL3_Shutdown();
+    ImGui_ImplGlfw_Shutdown();
+    ImGui::DestroyContext();
+
+    glfwDestroyWindow(window);
+    glfwTerminate();
+
+    return 0;
+}
diff --git a/imgui_glfw_app/shaders/FragmentShader.glsl b/imgui_glfw_app/shaders/FragmentShader.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9ed28d89d28b442abbc3d598478d388a6f079368
--- /dev/null
+++ b/imgui_glfw_app/shaders/FragmentShader.glsl
@@ -0,0 +1,8 @@
+#version 330
+
+in vec3 fragmentColor;
+out vec3 outColor;
+
+void main(){
+    outColor = fragmentColor;
+}
\ No newline at end of file
diff --git a/imgui_glfw_app/shaders/SimpleVertexShader.glsl b/imgui_glfw_app/shaders/SimpleVertexShader.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..0aca2dff189585b9a085795aaca380f0e09d5840
--- /dev/null
+++ b/imgui_glfw_app/shaders/SimpleVertexShader.glsl
@@ -0,0 +1,13 @@
+#version 330 core
+
+layout(location = 0) in vec3 vertexPosition_modelspace;
+layout(location = 1) in vec3 vertexColor;
+
+out vec3 fragmentColor;
+
+uniform mat4 MVP;
+
+void main(){
+    gl_Position = MVP * vec4(vertexPosition_modelspace, 1);
+    fragmentColor = vertexColor;
+}
\ No newline at end of file
diff --git a/imgui_app/CMakeLists.txt b/imgui_sdl_app/CMakeLists.txt
similarity index 94%
rename from imgui_app/CMakeLists.txt
rename to imgui_sdl_app/CMakeLists.txt
index 5ca9d7039b12694e85a549ca2b3b2ffe013ca315..dcbb8a88737022b7db925014fefb72f172e8610d 100644
--- a/imgui_app/CMakeLists.txt
+++ b/imgui_sdl_app/CMakeLists.txt
@@ -1,6 +1,4 @@
 
-add_definitions(-DIMGUI_IMPL_OPENGL_LOADER_GL3W) # Define OpenGL loader for Dear ImGui
-
 # Dear ImGui include dirs
 include_directories(
     ../libs/imgui 
diff --git a/imgui_app/imgui_playground.cpp b/imgui_sdl_app/imgui_playground.cpp
similarity index 50%
rename from imgui_app/imgui_playground.cpp
rename to imgui_sdl_app/imgui_playground.cpp
index 35ecb27c614ec5d5e4c1dd1fdf6fb21b3d26c78d..368f3688f0e639af6fda713c6b7547366227239d 100644
--- a/imgui_app/imgui_playground.cpp
+++ b/imgui_sdl_app/imgui_playground.cpp
@@ -3,74 +3,127 @@
 /// @brief  Working example for Dear ImGui with OpenGL3 and SDL2
 ///
 
+#include<iostream>
+
+#include <SDL.h>
+#include <GL/gl3w.h>
+
 #include "imgui.h"
 #include "imgui_impl_sdl.h"
 #include "imgui_impl_opengl3.h"
-#include <stdio.h>
-#include <SDL.h>
 
-#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
-#include <GL/gl3w.h>
-#endif
+
+void setSdlGlAttributesApple()
+{
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+}
+
+void setSdlGlAttributesLinux()
+{
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+}
+
+void setSdlGlAttributesCommon()
+{
+    // Create window with graphics context
+    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+}
+
+#include <vector>
+#include "ImageBuffer.hpp"
+const std::vector<QPong::QColor> colors {
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f},
+    {0.3f, 0.2f, 0.4f}
+};
+
+const std::vector<ImVec2> positions {
+    {0.0f, 0.0f},
+    {0.1f, 0.0f},
+    {0.2f, 0.0f},
+    {0.3f, 0.0f},
+    {0.4f, 0.0f},
+    {0.5f, 0.0f},
+    {0.6f, 0.0f},
+    {0.7f, 0.0f},
+    {0.8f, 0.0f},
+    {0.9f, 0.0f},
+    {0.0f, 0.1f},
+    {0.0f, 0.2f},
+    {0.0f, 0.3f},
+    {0.0f, 0.4f},
+    {0.0f, 0.5f},
+    {0.0f, 0.6f},
+    {0.0f, 0.7f},
+    {0.0f, 0.8f},
+    {0.0f, 0.9f},
+    {0.0f, 0.9f},
+    {0.5f, 0.5f}
+};
+
+void displayPoints()
+{
+}
 
 int main(void)
 {
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
     {
-        printf("Error: %s\n", SDL_GetError());
+        std::cerr << "Error: " << SDL_GetError() << '\n'; 
         return -1;
     }
 
-
     // Decide GL+GLSL versions
     #if __APPLE__
         // GL 3.2 Core + GLSL 150
         const char* glsl_version = "#version 150";
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+        setSdlGlAttributesApple();
     #else
         // GL 3.0 + GLSL 130
         const char* glsl_version = "#version 130";
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+        setSdlGlAttributesLinux();
     #endif
 
+    setSdlGlAttributesCommon();
 
-      // Create window with graphics context
-    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
-    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-    SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+    SDL_WindowFlags window_flags = static_cast<SDL_WindowFlags>(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
     SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
     SDL_GLContext gl_context = SDL_GL_CreateContext(window);
     SDL_GL_MakeCurrent(window, gl_context);
     SDL_GL_SetSwapInterval(1); // Enable vsync
 
     // Initialize OpenGL loader
-    #if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
-        bool err = gl3wInit() != 0;
-    #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
-        bool err = glewInit() != GLEW_OK;
-    #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
-        bool err = gladLoadGL() == 0;
-    #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
-        bool err = false;
-        glbinding::Binding::initialize();
-    #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
-        bool err = false;
-        glbinding::initialize([](const char* name) { return (glbinding::ProcAddress)SDL_GL_GetProcAddress(name); });
-    #else
-        bool err = false; // If you use IMGUI_IMPL_OPENGL_LOADER_CUSTOM, your loader is likely to requires some form of initialization.
-    #endif
-        if (err)
-        {
-            fprintf(stderr, "Failed to initialize OpenGL loader!\n");
-            return 1;
-        }
+    if (gl3wInit() != 0)
+    {
+        std::cerr << "Failed to initialize OpenGL loader!\n";
+        return 1;
+    }
 
     IMGUI_CHECKVERSION();
     ImGui::CreateContext();
@@ -79,50 +132,52 @@ int main(void)
     ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
     ImGui_ImplOpenGL3_Init(glsl_version);
 
-
     ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
     bool done = false;
     while (!done)
     {
-         SDL_Event event;
+        SDL_Event event {};
         while (SDL_PollEvent(&event))
         {
             ImGui_ImplSDL2_ProcessEvent(&event);
-            if (event.type == SDL_QUIT)
+            if (event.type == SDL_QUIT){
                 done = true;
-            if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+            }
+            else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)){
                 done = true;
+            }
         }
 
         ImGui_ImplOpenGL3_NewFrame();
         ImGui_ImplSDL2_NewFrame(window);
         ImGui::NewFrame();
 
-         {
+         {  // Config GUI
             static float f = 0.0f;
             static int counter = 0;
 
             ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.
-
             ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)
-          
             ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f
             ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
-
-            if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated)
+            if (ImGui::Button("Button")){                           // Buttons return true when clicked (most widgets return true when edited/activated)
                 counter++;
+            }                           
             ImGui::SameLine();
             ImGui::Text("counter = %d", counter);
-
             ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
             ImGui::End();
         }
 
-         // Rendering
+        // Rendering
         ImGui::Render();
-        glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
-        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
-        glClear(GL_COLOR_BUFFER_BIT);
+        
+        {   // own OpenGL code goes here like this background clearing.
+            glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+            glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
+            glClear(GL_COLOR_BUFFER_BIT);
+        }        
+        
         ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
         SDL_GL_SwapWindow(window);
     }
@@ -135,6 +190,5 @@ int main(void)
     SDL_DestroyWindow(window);
     SDL_Quit();
 
-
     return 0;
 }
\ No newline at end of file
diff --git a/qpong_core/ImageBuffer.cpp b/qpong_core/ImageBuffer.cpp
index b4a524b9b65cb2edcd870e0871c34c8e87511aed..7f4aa82e1f47955290c5c61b392e216b91f431c2 100644
--- a/qpong_core/ImageBuffer.cpp
+++ b/qpong_core/ImageBuffer.cpp
@@ -24,29 +24,26 @@ void ImageBuffer::updateAt(unsigned index, std::complex<double> v, double obs)
 const QColor ImageBuffer::getValue(unsigned index)
 {
     std::complex<double> val = m_complexBuffer[index];
-    double r = real(val);
-    double i = imag(val);
-    double obs = m_potbuf[index];
+    double r {real(val)};
+    double i {imag(val)};
+    double obs {m_potbuf[index]};
     
     QColor c {
-        static_cast<float>(obs + r*r),          //< red
-        static_cast<float>(r*r + i*i + obs/1.5),  //< green
-        static_cast<float>(i*i)                 //< blue
+        static_cast<float>(obs + r*r),              // red
+        static_cast<float>(r*r + i*i + obs/1.5f),   // green
+        static_cast<float>(i*i)                     // blue
     };
 
     constexpr double max = 0.81;
-    if (c.r > max)
-    {
+    if (c.r > max){
         c.r = max;
     }
 
-    if (c.g > max)
-    {
+    if (c.g > max){
         c.g = max;
     }
 
-    if (c.b > max)
-    {
+    if (c.b > max){
         c.b = max;
     }       
     return c;