Riko Ophorst
Rendering & Software Engineer
4+ years professional experience (incl. internships) Started working professionally in Sep 2018, including my initial internship at OTOY. Does not include internships from before that date.
Vulkan, Metal, D3D11/12, CUDA, CMake, RTX, Windows, macOS, Linux
Raytracing & pathtracing
Realtime 3D rendering
R&D in Emerging Technologies
Cross-platform & porting
GPU & CPU optimizations
2 shipped products
4 shipped games
5 game jams
Creative Media & Game Technologies (BSc, July 2019)
At Breda University in the Netherlands
  • Bloom post processing
  • First year project
  • C++ / OpenGL
  • Exposure based tonemapping
  • Custom memory allocators
What is Battleships?
Battleships is a school project made in 8 weeks in my first year. It was my first time working with OpenGL and doing any 3D graphics. It was a very useful project, as I learned a lot about rendering during this block.

It's the first time I build anything with lighting in it - and this has Blinn-phong lighting in it. It also features a bloom post processing effect and an exposure based tone mapping algorithm. Check out the video at the top of the page to see what it looked like.

In this project, I also build custom memory allocators. There really wasn't a reason to do that, but I wanted to gain some experience in working with low-level pointers and memory. Next to that, we were also assigned to build our own matrix & vector math in this project.
Technical specifications
  • 8 weeks of development time
  • C++ / OpenGL
  • Blinn-phong lighting with normal mapping
  • Bloom post processing
  • Exposure based tone mapping
  • Custom memory allocators
  • Custom matrix & vector math
View the source code on GitHub
First time using OpenGL 4.5 and GLFW
This is my first project doing anything with OpenGL and simultaneously doing anything with 3D graphics in general. I spend a lot of time studying how OpenGL works and how to go about using it.

You can checkout some interesting tid-bits here.

Blinn-phong lighting with normal mapping
I used Blinn-Phong lighting to achieve pseudo realistic shading in the engine. It supports the most common types of light sources:
  • Point lights
  • Spot lights
  • Dual cone spot lights
  • Directional lights

Added onto that, it also supports normal mapping, although in the videos above it is turned off because the meshes don't have normal maps.

You can checkout the Blinn-Phong shader here.

Bloom post processing
During the project, I wanted to implement some sort of post processing effects, the first of which is bloom. Bloom is an effect that actually simulates an issue that real life cameras have. Whenever an object is really bright, the object sort-of starts "bleeding" its colors - a.k.a. it starts to glow, to bloom.

Bloom works by taking the final rendered image, and looking for bright spots on the image. It's advised to use HDR buffers, but at the time I wasn't aware of that - so I used LDR buffers instead. You can checkout here how the shader is setup to filter out bright spots from an image.

After the bright spots are calculated and output onto another buffer, we take that output buffer and blur it. I choose to use a simple Gaussian blur for this, since it is very easy to implement. A Gaussian blur takes at least 2 passes: a horizontal pass, and a vertical pass. It averages out the neighbouring pixel's colors based on certain blend weights. You can checkout the shaders used for this here and here.

After that, all that is left to do is to additively blend together the blurred image and the normal, usual scene buffer. You can find the shader for that here.

Exposure-based tone mapping
Bloom is great and all, but if you don't apply tone mapping after the bloom has been blended into the final scene buffer, you're gonna have a bad time. Tone mapping does exactly what it implies: it maps all the tones of colors in a texture to a certain range. There are many ways to do that, but I choose to use an exposure-based approach. Exposure based tone mapping does what a camera's exposure timer does essentially. The longer a camera's sensor is exposed to light, the brighter everything will appear.

You can find the implementation of my tone-mapping shader here.

Custom memory allocators
During the Battleships project, I decided I wanted to dabble a bit into the deep unknown world of custom memory allocation. I built a couple of memory allocators:
  • Linear Allocator
  • Stack Allocator
  • Free List Allocator
  • Pool Allocator
You can find the implementation of these allocators here.

Custom Matrix & Vector math
Battleships was a school project, and during the project we were assigned to build our own matrix & vector math implementations. The goal was to understand how the underlying 3D math actually works - not to create an optimized math library.

You can find the implementation of this here.