LightsprintSDK 2021.08.08
Fireball, Architect

Realtime lighting using dynamic lights is a mainstream approach today, however its realism was always severely limited by lack of properly computed indirect light.
Fireball and Architect techniques solve this realtime global illumination problem (see samples), however, quality suffers in presence of certain geometry "errors", so you might have to clean up your geometry.
Following hints help you get good performance and quality in your projects.

For purpose of realtime GI calculation, we expect scene split in two parts, static and dynamic.

Static scene

Static scene is a scene skeleton, big objects that never move, e.g. walls. Number of triangles in static scene is the most important performance and memory footprint factor, so we recommend creating as lowpoly walls as possible, with eventual details baked into normal maps or height maps.

Huge unnecessary polygons (e.g. box around scene) reduce speed and quality, remove them.

To achieve the best quality and performance, keep triangle sizes similar (on the same order of magnitude), avoid mixing very small and very large triangles. If very large polygon must be present, and it reflects light, tessellate scene a bit, just to break huge triangles - GI quality will improve. Don't tessellate too much, both performance and quality would drop.

Realtime GI consists of several components mixed together: per-pixel direct lighting, per-pixel indirect lighting and per-vertex indirect lighting. Because of per-vertex component, all static meshes must satisfy one simple rule required by all engines with per-vertex lighting:
Two triangles are disjunct, share 1 vertex or share 1 edge and 2 vertices.
So in other words, it is not allowed to

  • overlap triangles
  • intersect triangles
  • place edge in the middle of other triangle
  • place vertex in the middle of other edge

See that all forbidden cases can be easily fixed. This operation can be automated.

It is also recommended to avoid 'needles', triangles with needle-like shape, as artifacts may appear in their proximity.

Dynamic scene

Dynamic scene is made of objects that freely move and of small objects. Number of triangles in dynamic scene has no impact on performance, so we recommend using as detailed models as suitable.

Realtime GI is fully per-pixel, so restrictions related to per-vertex lighting don't apply to dynamic objects.

Materials

All material types are supported. There's no need for any additional information, Lightsprint automatically converts your engine's native materials to Lightsprint materials used during calculation. Complex materials don't slow down GI calculation, so we recommend using as good looking materials as possible.

Lights

All light sources are supported - point, spot, directional, emissive materials, sky (flat color, LDR or HDR texture) and they may arbitrarily change in realtime.

File formats

Lightsprint SDK does not lock your data in properietary formats. Instead, it supports 95+ standard file formats. In case you pick Collada, here's list of available Collada plugins.

Night scenes

When creating night scene, you might consider two options - reduce light intensity or make materials darker. Both have the same effect on direct illumination. But global illumination reveals dramatic difference - bright materials reflect lots of light and create rich indirect illumination with color bleeding; dark materials absorb light and hardly create any indirect illumination. So reducing light intensity simulates night in normal world; making all materials dark simulates day in world covered by black color. Of course we recommend keeping usual materials and reducing light intensity, results look better.

Problem examples

Above screenshots show realtime GI from skylight coming through ceiling opening. There are some quality issues vissible.

  • Floor lighting is completely flat, it is not darker in corners. Why? Indirect component of realtime GI is stored per-vertex, and the floor does not have sufficient number of vertices. Second screenshot with wireframe shows that there are only two vertices in corners. In order to get higher quality lighting that includes details like darker corners, you can pick one of these approaches:
    • split large polygons (preprocessing outside Lightsprint SDK)
    • precalculate light detail maps (preprocessing within Lightsprint SDK)
    • use one of many realtime ambient occlusion techniques (might be less accurate, but needs no preprocessing)
    • make the floor shiny and use Lightsprint renderer, automatic mirror reflection on flat objects has no problem with insufficient tessellation
  • There is lighter/darker pattern visible on the wall. Why? It's because floor intersects wall triangles, as can be seen on screenshot with wireframe. Upper parts of wall triangles are illuminated, bottom parts (under the floor) stay in the dark. Indirect component of realtime GI is stored per-vertex, so we can't change indirect lighting at the floor level, it is interpolated between darker vertices under the floor, and brighter vertices above the floor and unwanted pattern shows up. It can be fixed by better stitching floor and wall polygons, or by splitting triangles that intersect. Intersecting triangles are not allowed in static objects, as was mentioned earlier on this page.
  • Walls and ceiling are tessellated too much. This creates 'vertex noise' in renderings, if Fireball quality is not set high enough. It is not visible here, because sufficient 'quality' 10000 was set, but we can optimize performance by tessellating less, from 5x5 or 10x10 vertices per wall, rather than 20x20 here. It would give similar results at much lower Fireball quality, i.e. Fireball build (precalculation) would be faster, framerate with realtime GI would be bit higher and memory footprint lower.