diff --git a/.vscode/settings.json b/.vscode/settings.json
index e0d9a2fb5875753b0afa5ca6c4873f670c1f8925..ee1494255b4955ee3cc39f76afcdca381b7d3dc9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,6 @@
 {
   "files.associations": {
+    "*.mb": "markdown",
     "ratio": "cpp",
     "system_error": "cpp",
     "type_traits": "cpp",
@@ -50,7 +51,15 @@
     "utility": "cpp",
     "algorithm": "cpp",
     "cerrno": "cpp",
-    "memory": "cpp"
+    "memory": "cpp",
+    "bitset": "cpp",
+    "complex": "cpp",
+    "condition_variable": "cpp",
+    "list": "cpp",
+    "unordered_set": "cpp",
+    "iomanip": "cpp",
+    "optional": "cpp",
+    "string_view": "cpp"
   },
   "C_Cpp.configurationWarnings": "Disabled",
   "python.autoComplete.extraPaths": [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bfabcb68f004504215e2886c10183c21472bb4e3..708d6b7ce0b6c98c3f15190d4f9da2f5b06ab9bb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,6 +32,7 @@ target_sources(scigl_render PRIVATE
   src/gl_context.cpp
   src/render/frame_buffer.cpp
   src/render/offscreen_render.cpp
+  src/render/onscreen_render.cpp
   src/render/texture_fullscreen_render.cpp
   src/scene/cv_camera.cpp
   src/scene/diffuse_light.cpp
diff --git a/include/scigl_render/example/example_render.hpp b/include/scigl_render/example/example_render.hpp
index 9a29f069d3cf4c7397e971946a2431ca03c83f89..dbb12cc62158fbd40e3f9eb6886fe6c8dd2bfce3 100644
--- a/include/scigl_render/example/example_render.hpp
+++ b/include/scigl_render/example/example_render.hpp
@@ -7,7 +7,6 @@
 #include <scigl_render/scene/model.hpp>
 #include <scigl_render/shader/shader.hpp>
 #include <memory>
-#include <string>
 #include <vector>
 
 namespace scigl_render
diff --git a/include/scigl_render/render/onscreen_render.hpp b/include/scigl_render/render/onscreen_render.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c442bd826d8c33388376f012d82907ee744cd3ae
--- /dev/null
+++ b/include/scigl_render/render/onscreen_render.hpp
@@ -0,0 +1,35 @@
+#pragma once
+#include <memory>
+#include <scigl_render/scene/cv_camera.hpp>
+#include <scigl_render/scene/diffuse_light.hpp>
+#include <scigl_render/gl_context.hpp>
+#include <scigl_render/scene/model.hpp>
+#include <scigl_render/shader/shader.hpp>
+
+namespace scigl_render
+{
+/*!
+Simple rendering of a scene right on the screen (GLContext window).
+*/
+class OnscreenRender
+{
+public:
+  /*!
+  Configures the rendering environment and loads the models.
+  \param context the opengl context
+  \param shader how to render the scene
+  */
+  OnscreenRender(std::shared_ptr<GLContext> context, Shader shader);
+
+  /*!
+  Renders the next frame onto the screen.
+  */
+  void next_frame(const CvCamera &camera, const Model &model,
+                  const DiffuseLight &light);
+
+private:
+  std::shared_ptr<GLContext> gl_context;
+  // renders the 3D scene
+  Shader shader;
+};
+} // namespace scigl_render
\ No newline at end of file
diff --git a/src/example/scigl_viewer.cpp b/src/example/scigl_viewer.cpp
index f649fbd30790d8f7e1b8b77efe5ec928c8432668..ac6a7bf2d7a01ed1f6d6f293807230c551e15f00 100644
--- a/src/example/scigl_viewer.cpp
+++ b/src/example/scigl_viewer.cpp
@@ -5,6 +5,7 @@
 #include <iostream>
 #include <scigl_render/gl_context.hpp>
 #include <scigl_render/example/example_render.hpp>
+#include <scigl_render/render/onscreen_render.hpp>
 #include <scigl_render/scene/cv_camera.hpp>
 #include <scigl_render/scene/diffuse_light.hpp>
 #include <scigl_render/shader/single_texture_shader.hpp>
@@ -46,6 +47,7 @@ int main(int argc, char *argv[])
       std::make_shared<GLContext>(true, false, WIDTH, HEIGHT);
   ExampleRender render(context, SingleTextureShader::create_shader(),
                        GL_BGR, GL_UNSIGNED_BYTE, GL_RGB8, 3);
+  // OnscreenRender render(context, SingleTextureShader::create_shader());
   // Intrinsics of my shitty webcam
   CameraIntrinsics camera_intrinsics;
   camera_intrinsics.near = 0.01;
@@ -56,11 +58,6 @@ int main(int argc, char *argv[])
   camera_intrinsics.c_y = 310;
   camera_intrinsics.f_x = 511;
   camera_intrinsics.f_y = 513;
-  camera_intrinsics.s = 50;
-  // camera_intrinsics.f_x = 250;
-  // camera_intrinsics.f_y = 250;
-  // camera_intrinsics.c_x = 320;
-  // camera_intrinsics.c_y = 240;
   CvCamera camera(camera_intrinsics);
   // Test if Cartesian -> Quaternion works
   CartesianPose camera_pose = {glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)};
diff --git a/src/render/onscreen_render.cpp b/src/render/onscreen_render.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e77ac0f9bdac7d2c6f1b74a43ecce54b8be20a43
--- /dev/null
+++ b/src/render/onscreen_render.cpp
@@ -0,0 +1,30 @@
+#include <scigl_render/check_gl_error.hpp>
+#include <scigl_render/render/onscreen_render.hpp>
+
+namespace scigl_render
+{
+OnscreenRender::OnscreenRender(std::shared_ptr<GLContext> context,
+                               Shader shader)
+    : gl_context(context), shader(std::move(shader))
+{
+  // Configure the global rendering settings
+  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+  check_gl_error("onscreen render created");
+}
+
+void OnscreenRender::next_frame(const CvCamera &camera, const Model &model,
+                                const DiffuseLight &light)
+{
+  glClearColor(0, 0, 0, 0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glEnable(GL_DEPTH_TEST);
+  camera.set_in_shader(shader);
+  light.set_in_shader(shader);
+  model.draw(shader);
+
+  glfwSwapBuffers(gl_context->get_window());
+  check_gl_error("next frame");
+}
+
+} // namespace scigl_render
\ No newline at end of file