xray-16
xray-16 copied to clipboard
Support for linear space rendering in R4 renderer
The game is rendered in gamma space, which is not correct - the lighting is affected by non-linear mapping. So I added optional linear space rendering. To achieve this:
- albedo (and maybe some other) textures ar now loaded as *_SRGB format. Technical textures (such as bump, masks, etc) are still loaded as is.
- main color related back buffers and render targets were also made _SRGB.
Images For comparison:
Original gamma space rendering:
New linear space rendering:
Forgot that videos in UI also require proper loading as _SRGB.
Forgot that videos in UI also require proper loading as _SRGB.
Fixed this. This required modifying yuv2rgb.ps
shader, because texture is loaded as yuv and only converted back to RGB in this shader. The solution is not the most performant, but simple.
Thank you for rising this. The fix addresses an important issue, however I don't think it will be enough to solve it. Assuming that the textures are indeed in non-linear space (are they?), it would be nice to clarify:
- Original shaders have traces of
USE_GAMMA_22
which also affects material lookup. My assumption, that the material LUT was tweaked for non-linear art pipeline and seems need to be changed for linear rendering - The same for lights colors
- The same for layered materials: there is at least one used for terrain chunks. The layers are blended as weighted sum so outcome will produce different look for landscape in cases of linear and gamma-corrected inputs
- The same for post process effects (
CPostProcessColor
andCEffectorPP
for reference) - Haven't check it myself, but the game has
CGammaControl
which affects dxgi gamma ramp. Does it interfere with implicit gamma correction for srgb back buffer?
Personally, I believe that over almost 20 years players got used to the vanilla game appearance, and it is questionable what benefits the fix can give them. Can be good for some realistic graphic mods though.
Assuming that the textures are indeed in non-linear space (are they?)
Well, diffuse textures are non-linear, because they are displayed uncorrected on sRGB display in the original version. And that is pretty much expected.
- Original shaders have traces of
USE_GAMMA_22
which also affects material lookup. My assumption, that the material LUT was tweaked for non-linear art pipeline and seems need to be changed for linear rendering
I tried enabling USE_GAMMA_22 some time ago. As I remember, it was not behaving as I expected, but I don't remember details.
- The same for lights colors
I didn't apply correction to light colors, to retain closer to original look. Converting light color to linear space would make lighting brighter in general. The light falloff appears brighter, though, I didn't adjust curves.
- The same for layered materials: there is at least one used for terrain chunks. The layers are blended as weighted sum so outcome will produce different look for landscape in cases of linear and gamma-corrected inputs
Blending in linear space should make result little brighter than in gamma space, that's expected. Must be careful to not correct weights though.
- The same for post process effects (
CPostProcessColor
andCEffectorPP
for reference)
Not familiar with them, but some change in appearance is expected.
- Haven't check it myself, but the game has
CGammaControl
which affects dxgi gamma ramp. Does it interfere with implicit gamma correction for srgb back buffer?
I tried it, and it seems works correctly. Adds additional correction.
Personally, I believe that over almost 20 years players got used to the vanilla game appearance, and it is questionable what benefits the fix can give them. Can be good for some realistic graphic mods though.
I wouldn't call this PR a fix, but a new feature. Yes, it's intended for mods, because it will require some additional artistic tweaking. That's why I made it disabled by default. It can be enabled manually from console.
Why did you used _SRGB format for rt_Generic* rendertargets? You (should) do shading in linear space, so what's the point of storing post-combine1 image in SRGB buffer?
Why did you used _SRGB format for rt_Generic* rendertargets? You (should) do shading in linear space, so what's the point of storing post-combine1 image in SRGB buffer?
Making this buffer _SRGB doesn't affect linearity of reads/writes to it through shaders. Because both such reads/writes include mapping srgb->linear and back linear->srgb. What it affects is quantization errors. Without making it _SRGB, I see color banding especially in dark areas.
Couple of examples (with non-vanilla shaders) below. Look closely at dark areas. It's usually more noticeable when you move.
-
no-srgb rt_Generic*:
-
srgb rt_Generic*: