Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dæmon engine lighting [parent thread] #831

Open
illwieckz opened this issue Apr 4, 2023 · 1 comment
Open

Dæmon engine lighting [parent thread] #831

illwieckz opened this issue Apr 4, 2023 · 1 comment

Comments

@illwieckz
Copy link
Member

illwieckz commented Apr 4, 2023

There are multiple lighting mechanisms involved in a game running on the Dæmon engine. We will discuss both lighting, shadowing and application on textures.

This post is divided into 4 main parts:

  • Implemented and default features
  • Implemented and non-default features
  • Workarounds (usable to improve things until some features are implemented)
  • Feature requests

Implemented and default features

Dynamic lighting

It's operated by the engine at run time. The default implementation is a tiled renderer, it can support many lights in a scene and performance should not be bad.

It has one known minor rendering issue:

The dynamic lighting renderer requires OpenGL features newer than the minimal amount of features required by the engine. It may be possible to implement a Dæmon-based game only using dynamic lights, the Doom3 way, but that would exclude low-end or old hardware. To do that one should implement the spawning of dynamic lights from map entities/light emitting shaders, but no one did it yet because no one had the need, as world precomputed lightmaps (see below) have wider hardware support and better performance.

In Unvanquished, dynamic lighting is only used on special effects. When a Dæmon-based game doesn't make dynamic lighting required for gameplay the engine compatibility extends to OpenGL 2.1, including current low-end ARM boards like Raspberry Pi 4 and 20 years old PC hardware like Radeon 9700.

Note: The engine code also provides a dynamic forward rendered but it is now deprecated and not enabled by default since years. It is expected to be slower. It's not nuked yet as there are some features that were implemented with it we may want to port and it can be used as a reference. Since no one player uses it, it may become silently broken with time, if not already broken.

The old forward renderer may be dropped at some point:

Precomputed lighting

There are two kind of precomputed lighting involved:

  • Light mapping, used to lit surfaces of the world and paint projected shadows, those are basically light and shadow textures. It supports alpha shadowing (projected grate shadows) and rgb filtering (like the projected colors of stained glass) and dirt mapping (accumulation of shadowing in corners).
  • Grid lighting, used to lit surfaces of animated models, basically player models, buildables, weapons. This is a 3D grid with light color and intensity reference for every place of the game. The effect of it can be seen on the first person weapon while moving in a map.

The light maps and the light grid are generated at build time when compiling the maps with q3map2 (part of NetRadiant level editor). Improving lightmaps in game may require changes in both the engine and the map compiler.

The lightmaps are not bad per se. Games like Xonotic looks way better with lightmaps computed the Quake3 way than Quake 4 realtime lights, except Xonotic use sRGB colorspace (unlike Quake3 and Dæmon). To reach Xonotic lightmap quality we need sRGB lightmaps support implemented in engine (see below).

It is believed that like all games from the early 2000 (quake3 engine, source engine…) the engine suffers from a design flaw where linear lightmaps are applied on non-linear sRGB diffuse maps with linear computation, this may be fixed at the same time we implement sRGB lightmaps (see below):

It is believe that techniques like half-lambert lighting (first implemented in source engine) are actually a workarounds for this design error. The Dæmon engine applies half lambert lighting on grid lit models like players, buildables etc.

It is believed that techniques like wolf-lighting (implemented by q3map2 as an optional way to compute lightmaps) and used by games like Return to Castle Wolfenstein or Wolfenstein: Enemy Territory are a workaround for this design error. Basically the lightmap is wrongly computed in order to counteract the wrong renderer compute. The engine would load them without knowing, so they should look like they look in their original games, because we still use the legacy light color computation. Old maps from old games may have no bit to know which lighting computation was used by q3map2, making hard to select the related light computation at run time.

The light map process also produces deluxe maps to be used with normal maps. The q3map2 map compiler can produce both tengeant-space and world-space deluxemap, the Dæmon engine only supports word-space deluxemap, which is the most common implementation in games anyway.

The lightmaps currently suffer from color banding on low light conditions. This can be seen in maps like hangar28. Two solutions are possible: sRGB lightmaps and HDR lightmaps (see below). One workaround is available: _minLight (see below).

One can improve lightmap precision by tweaking the lightmap scale. The _lightmapscale property in map worldspawn entity before map compilation. This can be tweaked per func_group to use higher precision in some places and lower in some others (for example on distant outdoor), as increasing the precision increases the lightmap size and then map DPK size and game video memory usage. The smaller the number is, the more precise it is. It's a float, 1 is default precision, 0.5 doubles the precision.

For historical reasons (we use Quake3 BSP format to be compatible with Tremulous maps) some light direction data is not stored in the compiled map, so we restore it from the grid light, this is less good than what we can do if q3map2 would store the data in the BSP file but we would have to break the format to implement that.

Phong shading

This is a technique to apply light on textures.

The Dæmon engine implements Phong shading with specular maps, this is heavily used and no bugs are known.

Implemented and non-default features

Physically based rendering

The Dæmon engine implements Physical shading with PBR maps, it's not used yet by official assets so there may be bugs, and maybe strong ones. We may also need to fix the light computation first.

In fact the engine has support for this enabled by default, but none asset use it so it's a bit like it's not used by default, on asset side.

SSAO

Screen-space ambient occlusion is a technique to darken some corners. This is non-physical but that can help the player to read what's on screen. It's currently implemented and working, but disabled by default.

One issue is that this can be applied atop fog but this is inherent to the technique itself (it's applied once everything is already computed) so there may be no way to fix that, unless we use a depth-like fbo to mark what part of screen uses fog.

Workarounds

minLight

This is a workaround telling the map compiler to always paint a minimum of light in a map. With a good value, one may avoid obvious color banding and keep the atmosphere dark and gloomy. One wanting to actually reach pure black cannot use that, this may not be wanted in hangar28 for example.

This is not compatible with the black texture trick where the distant bottom of a dark corridor or pit is simply using a pitch black texture because surrounding shadow is already pitch black anyway: by making impossible for precomputed shadows to reach pitch black those black textures will be very visible (this can't be used in spacetracks for example).

Good values are:

_minlight 2
_mingridlight 4

This should be applied as properties of the worldspawn entity in a map before building it.

An alternative implementation to be done engine side is discussed there, it suffers from the same flaws but it may help to improve the rendering of some legacy maps without rebuilding them (especially when it's not possible when sources are lost):

Feature requests

See also (not all are light-related):

Dynamic shadows

Dynamic shadowing was implemented in the old forward lighting renderer. This feature is not ported to the tiled renderer yet, but the feature was already broken since years in the forward lighting renderer so not having ported it from the forward renderer to the tiled one is not a regression itself. The regression happened years before the tiled renderer was set default.

They should either be fixed and ported from the deprecated forward renderer, or re-implemented.

sRGB lightmaps

It's just a way to store color differently, basically shifting the color values in the storage. There would be no more precision (this is still using 8-bit color channels), but precision would be more evenly distributed among low and high lights.

The q3map2 map compiler already supports this and is ready. The Dæmon engine is not ready yet. I have some work-in-progress branch somewhere but it has bugs (for example UI is affected while it should not). Since this is still using 8-bit color channel, sRGB lightmaps are compatible with any 8-bit image format.

A game like Xonotic (q3map2 map compiler, DarkPlaces engine) already supports sRGB lightmaps so we can use Xonotic maps to test engine implementations.

HDR lightmaps

It's basically about storing lightmaps in formats allowing more precision (for example 16-bit color channels).

The engine has some remaining code from this feature but it is unused so it may be broken. The q3map2 map compiler doesn't have the feature yet. Two q3map2 implementations exists in forks, one from the old wolfmap/daemonmap (the very early one), one from an OpenJK fork. The difference should only be that they output different image formats. Merging those forks is on hold since years because NetRadiant/NetRadiant-custom fork situation is already exhausting all the time available to deal with merging forks.

HDR lightmaps may be useful if we implement adaptative lighting.

Dithering

This would reduce color banding at the cost of some GLSL computation. I have some local work-in-progress branch on my end but there result isn't very convincing to motivate me to finish it. It's better to invest time in implementing sRGB lightmaps in support, the return on investment would be way higher.

Adaptative lighting

This would overbright outdoor if you're indoor and underlight indoor if you're outdoor, with your virtual eye adjusting your ability to see in your current environment. HDR lightmaps may prevent lightmap color banding if implemented.

Sun lighting

ioquake3 has it:

Precomputed light directional data in BSP

To avoid restoring light direction from grid light (which isn't perfect), we would have to make the q3map2 map compiler stores this data in the BSP file. Doing so would break BSP format compatibility. We would need the engine to support more than one BSP format if we want to do that or we would lose compatibility with all legacy maps (this is not wanted).

Legacy vertex lighting

This technique is very bad and no implemented in Dæmon engine (actually r_vertexLingthing 1 enables grid Lighting for the whole world instead, which is far better).

The reason why we may want to implement legacy vertex lighting is that it may be needed to render properly maps that intentionally did not compute lightmap on some surfaces to save lightmap file size.

@VReaperV
Copy link
Contributor

VReaperV commented Nov 1, 2024

Precomputed light directional data in BSP
To avoid restoring light direction from grid light (which isn't perfect), we would have to make the q3map2 map compiler stores this data in the BSP file. Doing so would break BSP format compatibility. We would need the engine to support more than one BSP format if we want to do that or we would lose compatibility with all legacy maps (this is not wanted).

Am I correct in understanding that this is what deluxe maps already are?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants