Skip to content

linear colorspace lightmap applied on non-linear sRGB colorspace diffusemap #270

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

Open
illwieckz opened this issue Jan 11, 2020 · 8 comments

Comments

@illwieckz
Copy link
Member

illwieckz commented Jan 11, 2020

This is related to #243 (sRGB lightmap).

For what I know, what we call color, diffuse, or albedo maps are in sRGB color space because all image editors work that way.

On the other hand, textures like normal maps are stored in linear space, and by default q3map2 produces linear light maps and deluxe maps too.

I really doubt that, back in the day, Quake 3 and other games from that age was converting color maps to linear space before applying light maps on them.

I highly suspect that gamma ramping done by those old games was a hack to convert the light maps to sRGB space, that was making light looking OK while the color maps were wrong but no one cared as the priority was to get light map OK.

I highly suspect that many other hacks the industry invented like the Half-Lambert lighting were basically ways to deal with missing conversion somewhere in the pipeline.

This very instructive page by Joey de Vries explains how game developers are likely to use non-physically correct linear light attenuation to workaround their non-gamma corrected games, while the physically correct quadratic attenuation gives correct results on gamma corrected games.

We can see in q3map2 that while Quake 3 used a physically correct quadratic falloff in light map computation, Wolfenstein: Ennemy Territory while using a non-correct linear one to workaround the issue we talk about. Basically, Wolf:ET required more realistic lighting than Quake 3 and a wrong linear falloff is known to produce more realistic results when a linear light map is wrongly applied on a non-linear color map.

The default q3map2 profile for Unvanquished is to not use the linear falloff. We are very lucky.

The Alpha 27 release post tells that some lighting in some maps were modified because of some gamma issue, it links an extensive article that tells more about it.

The blog post tells that the game was initially using a 1.3 gamma custom value and it was reset to 1.0 to avoid colors to look washed out, but since it would darken the maps, Unvanquished maps lighting was redone to produce something that looks good.

Well, now we know why a more-than-one gamma was used and why the colors looked bad: using a more-than-one gamma is a hack to convert light map to something approaching the sRGB space, but since the color maps were already in sRGB space, they looked like converted two times.

So, we have to expect that all of our maps have unproper lighting. Also, it may explain why our game looks so dark.

I made a very-naive implementation (not using OpenGL builtin like internal sRGB format and sRGB frame buffers) to do some tests…

This is how looks the Metro map before and after:

not srgb

srgb

This is not only more bright, this is more correct.

Station15 map:

not srgb

srgb

Test-PBR map:

not srgb

srgb

In Perseus map, we can see shadows that look physically correct, given the amount of light in that room, shadow would be wrong if they were more dark:

srgb

The major issue is that because of the various conversion, we lose precision in the process, and light maps not having already enough precision than we would like (see #239 for issue about HDR light mapping), dark blotches are worst than ever:

srgb

srgb

Also, while most of models seems to look good:

srgb

srgb

srgb

srgb

Some of them like egg, leech and barricade do not look that good. I've read at some place that some textures were reworked to look good in game, maybe those were unfortunately altered to workaround a bug while they were right:

srgb

Basically, our maps looks a bit too-bright, and a bit washed, but if they were just less bright they may look good, here is some various random examples:

srgb

srgb

srgb

srgb

srgb

srgb

srgb

srgb

@illwieckz
Copy link
Member Author

The naive trick I used would be useful on pre-OpenGL 3 hardware in any way (driver without support for sRGB framebuffer and internal image formats), if we still support them.

@illwieckz
Copy link
Member Author

Note: I've discovered that the barricade diffuse texture we use:

current barricade diffuse

Is slightly darker than the one linked in its respective forum thread:

original barricade diffuse

I was expecting the other way…

@illwieckz
Copy link
Member Author

illwieckz commented Jan 11, 2020

I attempted to do it the OpenGL way, it's far more intrusive and is more complicated to get it right as we have to make sure all images are uploaded the right way, also I'm not sure all internal formats have sRGB variants.

The main problem is that we have to make sure all the textures are correctly loaded with the right internal format, otherwise it looks like that (UI and skybox not being processed as sRGB, hence wrong) :

srgb

Otherwise it looks the same as the glsl trick, with same issues:

srgb

srgb

srgb

srgb

srgb

@illwieckz
Copy link
Member Author

illwieckz commented Jan 11, 2020

This is how looks Vega when compiled with noFast (less dark blotches because -fast has a faster falloff) and rendered with light correction. Except when there is dark blotches because of the image format not having enough precision, the “shadow darkness” is physically correct everywhere. It does not look like the shadow is painted over the light anymore, but the light being subtly attenuated:

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

vega nofast gamma corrected

For reference, this is how this map looks with q3map2 fast lighting and without gamma correction:

vega fast not gamma corrected

vega fast not gamma corrected

vega fast not gamma corrected

vega fast not gamma corrected

vega fast not gamma corrected

@illwieckz illwieckz changed the title linear colorspace lightmap applied on non-linear sRGB colors pace diffusemap linear colorspace lightmap applied on non-linear sRGB colorspace diffusemap Jan 11, 2020
@illwieckz
Copy link
Member Author

illwieckz commented Jan 11, 2020

An interesting read about why there is such ugly artifacts on dark shadows:
https://blog.demofox.org/2018/03/10/dont-convert-srgb-u8-to-linear-u8/

@ghost
Copy link

ghost commented Dec 31, 2021

Really... could you get a look at if that's still true? I'm drowned by the screenshots... you certainly love them :)

@illwieckz
Copy link
Member Author

Nothing on that topic reached master branch ever. Only proofs of concept were done.

There may even be misunderstanding from myself in the original description, but this is a counterpart of #243 and until #243 isn't fixed, this one can't be fixed because until #243 is fixed, we should assume knowledge required to fix this may not be fully acquired yet.

@illwieckz
Copy link
Member Author

I did some experiments locally, and one problem is that if it's wrong that “linear lightmaps are applied on non-linear textures”, all mappers of all legacy maps tested their map with a faulty renderer, and then all the maps are full of workarounds for the faulty renderer. It means if we fix the engine, the maps will not look the way the mapper wanted them to look like. Sometime it looks better to render properly a legacy map, but the more the mapper spent time to make his map look good on a faulty renderer, the less we can fix the renderer.

My suggestion is that we carry a metadata telling the engine the map has been thought for a correct renderer. When someone makes a new map from scratch or decide to totally redo the lighting of a map, he would set a metadata and then the engine will do a correct computation. This way the mapper would always test his map with a correct computation and then set lights in his map that are only meant to produce the expected result when rendered in a correct renderer.

This metadata would not change anything in the way lights are precomputed, it would just make sure both the mapper and the player use the same renderer profile, while the legacy renderer profile would be kept for legacy maps.

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

1 participant