Masters Final Project (GLSandbox)

GitHub Repository

Example image of the GLSandbox application

For the final project for my Masters course (MSComp Computer Science - Game Engineering 4th year), I made an application designed to allow the creation of full render-pipelines through a graph-based interface. Since I go over this project in a lot of detail with my dissertation I will mainly focus on getting across a general idea of the project and some implementation details on this page. A link to the full dissertation can be found below.

I received 74% (first class) for this submission.

Specification

The initial goal for the 8 week long project was to create an application which could support a simple deferred render-pipeline by solely using a graph-based editor to program it. This goal has since been refined into a list of requirements for a minimum specification as follows:

  • Must have an application window with a graph-editor panel and a space to render the final pipeline
  • Must be able to build a render-pipeline by linking relevant mesh, shader, and uniform nodes to a render-pass node
  • Must be able to handle any valid user-specified shader or mesh
  • Must have enough functionality to allow the creation of a (simple) deferred render-pipeline
  • Must have a systeme for handling sub-graphs
  • Must have a method of comparing performance of a graph with an equivalently hard-coded pipeline
  • Must include example scenes which can be used to showcase the utility and performance of the tool

These requirements are gone over in more detail in my dissertation.

Libraries

Dear ImGui GUI library for creating UI widgets on top of a window. Generally used for debug windows, but can be used for application layout (as I often do).
imgui-node-editor Wrapper library for Dear ImGui for handling displaying and interfacing with graph-based editors.
glad Library for interfacing with the GPU through OpenGL.
glm Utility library with useful data structures and functions for graphics and 3D maths, matching those seen in glsl (e.g. vec3, mat4, normalize).
SDL2 GUI library for C++, used to create the main application window and handle user input events. Often used for games and simulations.
nativefiledialog Utility library for creating platform-native file choose dialogs.
stb Utility library for reading and writing textures/images.

Examples

Showcase of a simple pipeline being created from scratch

Showcase of a deferred pipeline being configured live:

Showcase of how the input system works:

Implementation

Graph Editor

From a user perspective, a pipeline is created by adding, configuring, and linking nodes in the graph with each node representing a graphical component or logical operation. As of writing the project contains the following nodes:

Image showcasing all nodes
  • Entry - Entry point of the graph where flow-control begins.
  • Input - Value input for a sub-graph.
  • Output - Value output for a sub-graph.
  • Sub-Graph - Wrapper containing the functionality of an entire user-defined graph.
  • Render Pass - Single draw call containing at least a shader and a mesh.
  • Loop - For-style loop for logical flow control.
  • Arithmetic - Addition, subtraction, multiplication, and division of numerical data types.
  • Integer - Whole number data type.
  • IVecN - N-component integer vector (N = 2~4).
  • Float - Decimal number data type.
  • VecN - N-component float vector (N = 2~4).
  • MatrixN - NxN float matrix (N = 2~4)
  • UV - 2 component float vector with values clamped between 0-1, representing texture coordinates.
  • Colour - 3 component float vector with values clamped between 0-1, representing RGB colour.
  • Direction - 3 component float vector with values normalized into a direction vector (vector of length 1).
  • Model - 4x4 matrix representing the position, rotation, and scale of an object
  • View - 4x4 matrix representing the position, and rotation of the camera.
  • Projection - 4x4 matrix defining the perspective of the camera.
  • Mesh - Vertex data to be sent to the GPU, representing an object in the scene.
  • Shader - Program to be sent to the GPU to operate on a mesh.
  • Texture - Empty image, mainly for writing to (used frequently in deferred-rendering and post-processing)
  • Texture (from file) - Texture loaded from a file.
  • Framebuffer - For defining which textures to write to, or the backbuffer (screen) if not used.
  • Screen Bounds - Stays updated with the size of the window, allowing for dynamic calculations requiring aspect-ratio.

Sub-Graphs

Sub-graphs allow for complex functionality to be collapsed into a single node. The images below showcase how this can be helpful, with the image on the right using sub-graphs to simplify the constant parts of each render-pass (such as the shader and mesh) into a single node:

Image showcasing a deferred render-pipeline Image showcasing a deferred render-pipeline using sub-graphs

Implementing this proved surprisingly simple, since I had already implemented a system for serializing and deserializing graphs. All that needed doing was to load the second graph and link it's input nodes with the sub-graph node's ports.

Meshes

One of the design goals I set myself for this project was to allow the user complete control over each aspect of the pipeline, where possible. To abide this goal I created a custom format for writing meshes to a file with any attribute the user may want. For example, the more commonly used Wavefront .obj format supports positions, uvs, normals, and indices. If the user happens to require additional attributes like tangents, they can only calculate them from the existing data, without being able to save any per-vertex alterations needed for their application.

My custom format (stored as .msh) works by assigning each attribute a unique name and type, then saving those followed by the actual data. For example, a quad with position and texture coordinates may look like the following:

# GLSandbox MSH File: /home/blacktack2/Documents/Rep/GLSandbox/cmake-build-debug/Meshes/Mesh1.msh 4 0 1 position 3 f 0 1 1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 uv 2 f 1 1 1 0 1 1 0 0 0 # GLSandbox MSH File humanicated num-vertices num-indices type attr-name num-components data-type binding-index component-1... ...

Dissertation

view/download pdf here