C++

DX12 Deferred Rendering

For a more detailed explanation of my deferred rendering system, please read the following PDF

View PDF

Graphics Memory

My DirectX12 engine uses a LinearAllocator to manage temporary memory for constant buffers and upload buffers (to transfer data to long-term storage). Each allocation from a LinearAllocatorPage increments a reference counter while the allocation's destruction reduces the reference count. Once a page no longer has any references, a memory fence is signaled on the command queue and its value is stored within the page. For each frame, we check the memory fence's current value. For any pending pages which have fence values lower than the current value, those pages are re-added to the page pool as a clean page ready to be used again.

Material System

Within the engine, each graphics object contains two materials: Material and MaterialTexture. The material system includes support for texture mapping; diffuse, normals and specular highlights. Using overloading functions, the user can use colors or textures (or both!). Using both sets of materials allows for the ability to uniquely tint each graphics object while using the same diffuse, normal, or specular textures for different objects.

Geometry Buffer

Every deferred rendering system needs a geometry buffer (or G-Buffer). My engine's G-Buffer includes a texture for the NDC Z-depth, world position, diffuse color, and normals. Each deferred graphics object is rendered to the G-Buffer in the first pass. On the following pass, lighting effects are processed and stored in a temporary texture. Finally, any post-processing effects are applied and then transferred to the swapchain's back buffer.

Dual Render System

This DirectX12 render engine supports to ability to render both deferred-rendered graphics objects and forward-rendered graphics objects in a single scene. It also supports sprites and fonts (using forward-rendering). The deferred objects are rendered first and written to the swapchain's back buffer. The forward renderer shares the same depth buffer as the deferred render allowing for deferred objects to occlude any forward-rendered objects in the scene.

Edge Detection & Deferred/Forward Rendering Demo

Light Volumes

Along with deferred rendering, my DirectX12 engine using Blinn-Phong lighting with light volumes. Each light source can be considered as a bounding volume, where the size of the volume corresponds to the amount of area that the light can affect the scene. This allows the ability to support an unlimited amount of lights without the need for bottomless arrays or shaders that need to know the amount of lights in each scene. Each light is rendered individually (and inside out). Using the G-Buffer, each pixel that reaches the pixel shader stage indexes into the G-Buffer and calculates its light influence on the scene. The output merger stage use an additive blend state, which allows for each light to compound its light influence to the render target texture. Directional lights affect the entire scene and therefore uses a quad that covers the entire viewport. Point lights use a sphere where its radius is directly tied to the range. Spot lights use a pyramid with a rounded base; their dimensions are calculated by the range and the cone's aperture.

Shadows Demo (3x3 and Poisson)

Depth of Field Demo