Renderer Architecture

Overview

Lightning Engine's renderer has been designed in a way suitable to implement any rendering method, present or future. There is no fixed-function pipeline in the sense that the rendering method used (being either forward rendering with multiple passes or deffered rendering) isn't hardcoded inside the engine. This is achieved by using plugins defining the rendering path which should be used in any particular situation.
High-level view of the Renderer Architecture
High-level view of the Renderer Architecture

The flow graph above presents a high-level view of the renderer architecture. It is clear that the actual rendering method used isn't predefined by the engine. In this case, the render path with the red arrows may use HDR deffered shading with shadows from multiple lights, suitable for rendering with latest hardware, and the blue render path may use forward rendering with one light per-pass with limited shadows, suitable for rendering with older hardware.

More information about the shader system can be found here.

Render Paths and Effects

A render path is defined as a list of passes executed in a predefined order. Different render paths may be used for controlling the way a scene is rendered based on hardware capabilities (e.g. HDR vs LDR rendering), or based on the what the application wants to render (e.g. wireframe, shading only or full effect rendering). All render paths have the ability to return the textures/surfaces they have used as render targets, in order to support hierarchical rendering, full-screen effects as well as run-time texture generation. Due to the abstract design, the application is free to switch between supported (based on hardware caps) render paths at run-time, without writing any special case code.
Connection between Effects and Render Paths
Connection between Effects and Render Paths

Each effect in Lightning engine keeps a list of shaders for each pass of each render path. From this list the first shader supported by the current hardware is used when rendering the specific pass. This way the renderer knows how to render every mesh based on current context. For example, a per-pixel displacement mapping effect may be rendered with a simple normalmapping shader when rendering to a dynamic cubemap.