Rough Lumen reflections cheat sheet

I wanted to make a place where I could write a few of the tips and tricks I came across for getting glossy/rough lumen reflections to ‘work’. The lumen developers are absolute masters of their craft, but the lumen documentation doesn’t necessarily include all of the necessary tricks/cheats/CVars needed to get lumen to work its best in shipping scenarios.

Stock lumen reflections on rough surfaces are inadequate for many visual scenarios, especially at material roughness values generally well-suited to cubemaps and other old-hat reflection techniques. I’ve been trying for the past while to figure out ways of extracting better results from lumen reflections, and I’m just putting them here for now. I’ll add more posts when I have the time. While there might be some higher-level analysis occasionally thrown in here, this will be, for the most part, the kludges and values I’ve found that ‘work’ in some way. No guarantees on side effects.

2 Likes

For testing, I’ll be using Epic/Quixel’s SciFi hallway scene. In addition to being freely available for anyone to reproduce, it represents a good example of a scene that could be handled well with traditional rendering methods, such as cubemaps and Screen-Space Reflections (SSR). It contains relatively detailed materials and geometry, and most important for my purposes, a large number of materials of varying specularity.


This is the SciFi scene stock, with direct lighting, cubemaps, and SSR set to 50 (perfect specularity).

This is the lumen version, with HWRT enabled, default settings, ray lighting=surface cache, and high-quality translucent reflections enabled.


This is the material roughness buffer, with black being perfectly specular (0) and white being perfectly diffuse (lambertian, or 1.0). Lumen can handle near-perfect specular (roughness of ~.1) and rough to diffuse reflections (.4-1.0) very well, but struggles immensely with glossy reflections (~.2-.39).

While this may sound like a very small limitation, those material values are actually very common in legacy content. Since SSR (the only common dynamic reflection solution at the time) had obvious failure cases, content had to be authored with cubemaps as a fallback. And that meant making materials such that low-res, distorted, and static cubemaps would still look visually plausible. This meant glossy-to-rough surfaces that would hide these errors, the exact material lumen reflections struggle with. By struggle, I refer to extremely unstable noise that creates very distracting flickering (hard to show in stills), or alternatively, wide blurs that destroy much high-frequency detail.

Fortunately, the lumen system has ample CVars to tune art direction, pipeline, and performance to work around some of the limitations. Obviously, if there was a perfect solution to this problem, it would be stock with the engine by now. Instead, we have a series of tradeoffs we can make, choosing off between physical correctness, artistic controlability, and performance.

3 Likes

Let’s say you just want the noise to go away without having to redo your materials. An easy solution is to simply clamp your materials to a value that won’t generate glossy reflections to begin with. This will not affect direct lighting’s material response, but your reflections will definitely look different. You can use r.Lumen.Reflections.MaxRoughnessToTrace (default .4) to determine the roughest material value lumen will trace reflections for, and r.Lumen.Reflections.SmoothBias (default 0), which will nudge any reflection-receiving surfaces towards being more specular, thus potentially reducing noise.


r.Lumen.Reflections.MaxRoughnessToTrace at .4 (default)

r.Lumen.Reflections.MaxRoughnessToTrace at .3. Note the changed appearance of the floor. What isn’t visible is a new fizzle in the emissive GI on the right of the image.

r.Lumen.Reflections.SmoothBias at 0 (default).

r.Lumen.Reflections.SmoothBias at 1. Note how much shinier not only the floor is, but the adjacent walls and other surfaces.

Both of these CVars can cause visual errors, with the maxroughnesstotrace sometimes revealing lumen GI errors that the reflections hid, or the smoothbias altering the look of rough surfaces too severely. These aren’t magic bullets, but good tools in the toolbox.

It should also be said about the SciFI test scene: this is one of the worst scenes you could support under lumen. It runs the gamut of all potential roughness values, it has very shiny metallic surfaces that require very accurate reflections, and small, irregularly-shaped emissive panels that must propagate lighting. A vast number of modern game scenes, especially those with more diffuse lighting, will resolve better with lumen than this scene will.

3 Likes

There are also slightly more involved solutions, or ones with more complex/content-dependent implications. The previous two Cvars were still arguably physically correct from an energy conservation perspective (if I understand it correctly), but I think it might be good to take a moment and explain why glossy reflections are harder to solve for. If there are people here who already understand light transport pretty well, I’m doing a recap partly because it’s what I wish I had when I was getting into this.

Fundamentally, lumen is a global illumination and reflections solver based around ray-tracing. Ray-tracing means, as in the name, tracing rays of light bouncing around a scene, and using that information to compute indirect lighting from it. For surfaces that are rough,rays are sent in semi-random directions upon hitting a surface, to simulate how the surface at a microscopic level is very jagged, which creates what is often termed global illumination. Reflections refer to surfaces that are shinier at a microscopic level, and the rays tend to bounce off in an predictable manner. This is why perfectly shiny surfaces are effectively noiseless.

Because rougher surfaces send rays in random directions, they can hit parts of the scene with vastly different amounts of lighting intensity frame-to-frame. Since the same lighting position can return different values depending on what the ray hits that frame, this can result in flickering, or noise. It’s especially bad when a reflection hits a bright surface like that of a light source, which causes very unstable lighting. Lumen GI doesn’t have as much of this problem, because it uses sampling and filtering techniques that assume the lighting doesn’t change depending on which way you’re looking at it. Perfectly specular lighting is innately noiseless, and diffuse lighting can use a variety of techniques to improve its’ results, but glossy reflections can’t use either of these assumptions, which is why they generally resolve so poorly. While lumen reflections are still subject to filtering and denoising, it isn’t quite enough to get a clean resolve at the moment. So, we have hacks.

Note: I’m aware this is a pretty simplified explanation of a very complex topic (ray-tracing based light transport), please feel free to do your own research on the subject, as I could have absolutely missed something.

1 Like

After @Daniel_Wright offered some clarification on the position of rough reflections in the lumen team’s priority stack, he also provided a CVar that I believe many will find helpful:

r.Lumen.Reflections.ScreenSpaceReconstruction.TonemapStrength can eliminate most of rough lumen reflections’ noise by (as far as I understand it) essentially tonemapping the problem away. Noise reduces significantly, enough to make almost any scene acceptable from a noise perspective, but it also erases a significant amount of detail from the reflection resolve. It’s probably the best tool I’ve seen for noise managment, however.


Sci-fi hallway example at previously established settings.

Sci-fi hallway example with r.Lumen.Reflections.ScreenSpaceReconstruction.TonemapStrength set to 1. Note the much cleaner resolve on the floor and metal walls (stills can’t really do it justice). This scene essentially went from unusable with lumen to acceptable. However, almost every specular highlight has been dimmed, and bright spots in the reflection are largely absent.

This CVar is a very good tool to manage noise, but like essentially everything else on this thread, it’s a tradeoff. If you need noise-free reflections and don’t mind the loss of detail however, this is a potential solution.

2 Likes

I downloaded that scene as well and can confirm it is so much more stable and brings back a lot of texture detail. Metals still have a lot of contrast, but those emissive lights in reflections look more like paper white objects in reflections instead of light sources. I think I’ll probably use r.Lumen.Reflections.ScreenSpaceReconstruction.TonemapStrength in any scene with obvious noisy semi-gloss reflections at this point.

1 Like

I think they mention this cvars will accept fractional values in 5.4, not just enabled/disabled. So it will be more flexible too.

1 Like

Oh, I wish you directed me here!

I’ll be studying your findings.

Thank you!

1 Like