Rendering / Graphics

Custom PBR Engine

A deep dive into building a physically based renderer from scratch using C++ and OpenGL. Featuring deferred shading, IBL, and high-performance instancing.

01

Foundations

Like many graphics engines, this project began with a single triangle. The goal was to build robust abstractions early to support complex features later.

  • Shader System: Hot-reloading support for rapid GLSL iteration.
  • Asset Pipeline: Integrated Assimp for loading complex OBJ/GLTF models.
  • State Management: Encapsulated depth, stencil, and blend states to prevent leaking OpenGL state.
02

Lighting & Shading

Started with standard Blinn-Phong shading to get visuals on screen. Implemented attenuation for Point and Spot lights.

Phong Lighting
Early test of multi-light attenuation.
03

Shadow Mapping

Lighting without occlusion lacks depth. I implemented two distinct shadow techniques:

  1. Directional: Orthographic projection mapping.
  2. Point Lights: Omnidirectional shadow mapping using geometry shaders and depth cubemaps.
04

Advanced Materials

To break the flat look of polygons, I implemented Normal Mapping for surface detail and Parallax Occlusion Mapping (POM) to simulate depth by raymarching height maps in the fragment shader.

05

Post-Processing

The post-processing stack includes an HDR Framebuffer, Tone Mapping (Reinhard/ACES), and a multi-pass Gaussian Blur for the Bloom effect.

06

Deferred Shading & SSAO

Transitioned the renderer architecture from Forward to Deferred. This involved creating a G-Buffer to store Albedo, Position, and Normal data, decoupling geometry processing from lighting calculations.

This also enabled SSAO (Screen Space Ambient Occlusion), adding soft contact shadows to crevices.

07

Physically Based Rendering

Implemented the Cook-Torrance BRDF. The engine now properly conserves energy and handles interactions between light and metallic/rough surfaces accurately.

PBR Rust
Rusted Iron PBR Material.
08

Image Based Lighting

To ground objects in their environment, I added IBL. This pipeline converts HDR equirectangular images into Cubemaps, then convolutes them to generate Irradiance and Prefilter maps.

IBL
Objects reflecting the HDR skybox.
09

GPU Instancing

Optimized for scenes with repeating geometry (foliage). By using glDrawElementsInstanced, the engine can render 100,000+ objects with minimal CPU overhead.

Instancing
100k Instance stress test.
10

Debugging Tools

Integrated ImGui for real-time shader uniform manipulation and visualizers for normals and shadow maps to diagnose artifacts.