OpenGL Framework

banner for open gl graphics framework showing parts of the gbuffer

This is an unnamed real time graphics renderer implemented in c++ and openGl.

The purpose of the project is having an easy starting point for future openGl graphics programming projects like games and tech demos. At the same time it can be used as an accessible testing environment for real time graphics, or specific parts like shaders can be reused in other projects.

It features a combination of deferred and forward rendering and an entity component system inspired by larger game engines such as unity.

It is implemented in Visual Studio and uses SDL2, GLM, DevIL, GLAD and Assimp.

Rendering

  • Deferred rendering with forward rendering on top
  • Postprocessing shader support
  • Environment mapping and skyboxes
  • Stereoscopic normal encoding for optimization
  • Multiple lights | inverse square falloff

Framework

  • Entity Component system
  • Scenegraph parent child hierachy
  • Factory pattern for content managment
  • Singleton pattern for context objects like Time, Camera, Input, window
  • Input manager using the observer pattern

Utility

  • Custom Mesh Loading
  • Mesh Filter builds vertex buffer depending on material requirements
  • Textures can be loaded in linear or sRGB mode
  • Tonemapping shader for gamma and exposure settings, HDR
  • gBuffer display mode
A screenshot showing deferred shading
The gbuffer for deferred rendering in opengl
sobol post processing filter for a toon shader


 

Implementation

Find the full code on Github->

 

Deferred Rendering

Whether or not an object is rendered deferred depends on the material settings. Foreward rendering is supported to accomodate special shaders that don't use the fixed shader workflow of the renderer, like for instance glass, emissive or toon shaders.

In a first pass, all deferred objects render into the g-buffer, which splits the data into 3 rgb textures. The layout of this buffer is shown below. It takes data for position, normal, base color, black and white specular, black and white AO, metalness and roughness - in other words its designed to support physically based rendering.

In order to use as little texture bandwidth as possible, the normal maps are encoded stereoscopically into two channels, and decoded in the second pass. An example of the first pass including normal map encoding can be found here.

In the second pass, all the information is extracted from the g-buffer (the normal maps are decoded again) and used for whatever form of shading is required, including lighting information. This step is applied on a framebuffer.

Once the deferred passes are complete, all objects with materials using forward rendering are rendered on top of this. In order tomake it look like they integrate seemlessly and are not just rendered on top, the z-buffer from the deferred render pass is copied so that the depth test fails if a forward rendered object is sitting behind a deferred rendered object. The rendering pipeline code is executed in the root draw of each scene.

 

Graphic showing the layout of the Gbuffer in the open gl framework

Shading with multiple lights

The shading part of the framework currently uses the blinn-phong specular approach taking multiple sources of light into account.

Currently it supports directional / sun lights and point lights with inverse square falloff. They are implemented as components of an entity, and when rendering the scene puts them in an array for use in the shader.

Also supported is environment mapping with fresnel fall off, which is added on top of the lit shading. The environment maps can also be visualized in the scene in form of a skybox.

Screenshot of the open gl shading with multiple lights

Postprocessing

The postprocessing step utilizes framebuffers with glsl shaders similar to the other 3d shaders, but on a screenspace plane. All prior render passes are rendered to the framebuffer textures until the last postprocessing step has been applied, which in turn renders to the backbuffer and presents.

This allows techniques such as high dynamic range rendering, which in turn enables adjusting the camera exposure. It could come in handy when dealing with high contrast environments such as indoor vs outdoor settings or space scenes with a bright planet and sun but rather dark starfield.

Further more gamma correction allows for a linear texture workflow for more accurate shading, and as a result all textures can be loaded either in srgb or linear rgb mode. Less common effects such as toon shading (for instance a sobel filter for outlines) can also be applied.

Screenshot of the open gl postprocessing with tonemapping (gamma | exposure)