Lumen GI and Reflections feedback thread

ofc. loads of triangles where you need the details. voxels to fill distant spaces cheap without the mesh compute overhead. and even less triangles for the distant shadows. hardware raytracing is just bounding box tests and triangle clusters to hit at the end. the more triangles in the cluster, the slower the ray hit test. it’s all performance. to me it makes sense.

and volumetrics cannot be represented in the raytracing scene. this is always screenspace ray marching. a static mesh can utilise distance fields. a moving assembly would require a rebuild of that distance field every frame or every couple frames to line up the geometry with the field. huge performance penalty. also… afaik… there’s no semi-opaque in distance fields. it’s binary coverage. i dunno why you’d even ask for semi translucency in this context. makes no sense to me.

Yeah, those tree proxies aren’t great for casting shadows. Still it can be fine for larger area lights or just cheap lights, given that screen traces can recover some of the contact shadow detail. It’s basically a tradeoff between having a bunch of local lights at lower quality or a few at higher with variable performance.

SDF version works as before, so you will get a low res SDF with stochastic transparency per tree.

I see, that makes sense. Given that Nanite assemblies are instanced, upon getting close to the tree, would it switch to an assembly where the individual components are the assembly BLASes, and the tree overall is its’ own TLAS? Given that you only have a handful of individual tree components, it feels like instancing could let you support a fairly complex tree in RT at a smaller memory footprint?

nanite is not meant to use raytracing, but cached vsm. if you’d have a forest with 1000 trees of 200 bones/instances moving, i’d reckon you’d have to recompute and realign 200000 bounding boxes to get correct hit results for just the instance bounding box. it’s also alot of triangles you’d have to check for a hit. doesn’t matter if it’s instanced or not. it’s a lot you ask from the rt cores.

tho… programmaticly you’d could hit a tree, go thru all instance transforms and perform the bounding box hit test with the inverse then move to the transformed subnode? i’m not an rt coder, actually. i can visualize the wiggling box tree tho. debug visuals. hmm.

what would happen tho if a bounding box branch would move outside of the tree bounding box. wouldn’t that be impossible to hit test?

I think you could do that with new RT APIs. You would need at least a 3-level BVH: one for clusters, one for assembly inner instances and one for entire trees. Still it’s unclear how practical such approach would be: RT has a sizeable per vertex memory overhead, 3 level structure requires lots of runtime BVH building and creates lots of BLAS overlaps reducing tracing performance.

3 Likes

Any way to have niagara effects actually show up in reflections? Right now, Lumen ignores them completely unless they’re opaque or masked. Niagara effects tend to use additive like this one. This is a ring mesh with emissive material with a niagara effect inside (the purple and blue/white part).

Lumen (5.6):

Screen Space Reflections (5.6) (absolutely horrendous looking):

What is that even? One is not even present and the other is some kind of visual monstrosity.

Also, if you use emissive materials on large surfaces, Lumen will have that emissive area flicker like crazy.

Do we have any solutions to this?

A material needs to render to the depth buffer to get proper screen space reflections - both Lumen screen traces or classic SSR.

Without depth, the position of the particle will usually be presumed to be the same as whatever opaque object is behind it when calculating the reflection. This is an age old limitation of screen space techniques.

A common approach would be to put in an opaque or translucent proxy that looks similar to your particle system and render that only in the raytraced scene. This way you have only one object in the raytraced scene instead of a million particles. A player probably won’t notice that the particles aren’t an exact match to their reflection if it’s done well.

Another method is to use render the particles/simulation to a render target and then display them on a mesh as a texture instead of directly rendering particles in the scene. This technique is common with fluid sims in particular, the plugin “fluid ninja live” is a good example of what I mean. But it can work for many types of particles.

Or just use dithered masked materials.

2 Likes

I’ve tried scene capture before and it cuts the framerate in half. If I have to use one for each effect, it’s unusable. Also, scene capture mess with the shadows as each camera fights for what is being displayed. And if you’re far enough, then the shadows switch to a different system and you get intense flickering. For my game, I can likely just expand Lumen’s distance or just turn Lumen off.

Regardless, even if I turn off Niagara effects, I still get this with SSR:

Again, what is this even?

And just using Lumen normally, it still suffer badly from flickering. I’ll post a clip later when I have time. But there are tons of example online. The Internet is plagued with them. And most solutions say to bump up gather quality, but that just tanks your fps.

That’s what SSR looks like. Pretty much every game to ship in the last decade on any engine that has used SSR has issues like this. It’s why mirror reflections are avoided like the plague.

For regular particle systems on non-mirror surfaces my advice would be to simply add a colored, unshadowed pointlight. The reason being is that actor lightsources have their specular highlights computed directly as part of the surface shader, they don’t need to trace rays into the scene and so they don’t have this issue.

That’s nice to give a rough approximation of reflections; but obviously, this won’t work in your case because you have a large circular effect on a mirror surface. For this specific case, since your effect is planar you can use a rect light with a source texture:

A static texture can work for rough/glossy reflections, but for mirrors you can animate it by drawing a material to a render target and using that as the source texture. Will be orders of magnitude cheaper than trying to use a scene capture.

Render target ≠ scene capture. Scene captures use render targets, yes. But you can also directly draw onto a render target from niagara without having to render a whole scene twice. It is very high performance and is how many real-time fluid dynamic simulations are achieved.

But ultimately I agree with Arkiras. Anything more than a simple reflection proxy will be overkill, even on a mirror surface, and especially if the particles are predictable in shape like yours. It will look far better than SSR and players won’t notice if the particles are not identical as long as it’s close.

You can use flip book animations, but for such a system you could probably get away with just animated UVs of the texture spinning.

But yeah, legacy SSR is often bad, don’t need to convince us. Always been that way. It was just the best option most of the time pre-raytracing.

1 Like

That would be great. I hadn’t encountered such a workflow before. I think I found a tutorial that can do it.

I’m guessing this is why I’m seeing a lot of niagara effects with a light source in the middle. Those do get reflected even in Lumen.

Back to Lumen, I’ve never been able to avoid the flickering or shimmering. I’ve seen it in EVERY game that uses Unreal with Lumen. I played Expedition 33 a while back and it was notorious for this. In the past 3 years, I’ve never been able to get Lumen to work. All I get is what I’m showing below. This is a free asset on Fab just to give a quick example.

Here’s a screenshot of what it looks like lit. You can’t see flickering in a static image, but just to give you an idea what it looks like:

And now the flickering. I’m using Lighting only view because you can see it more clearly.

Yes, the emissive material makes it worse, but don’t let that fool you. It happens everywhere in any scene. Indoors, walls, open areas, on characters, etc.

There’s gotta be a better way than this. I really hope I’m missing something. This is worse than reflections IMO because it’s everywhere. This is not acceptable output. And even top studios can’t get rid of it.

edit:

Asmongold has a 4090 so I’m using a link to one of his playthroughs. Here’s just a clip of Gustave’s hair in Expedition 33. Is that flickering from Lumen? Sure looks like it. This happens throughout the game. Not just on hair. It’s everywhere. Such a great game, but the rendering quality is dog crap. It wouldn’t surprise me this is why they added so many floating particles everywhere to make it seem like the flickering is expected.

I recently played Silent Hill f, and it had very little (but not zero) issues at max settings. I think most people see the limitations of the tech as worthwhile for high performance real time GI. It solves far more visual artifacts than it creates IMO.

People quickly forget how bad things could look with real time lighting, and even baked lighting in certain conditions. Yeah it was temporally stable, but it could easily be far uglier. A good example was widespread lack of specular occlusion, and extreme lack of depth in shadowed areas compensated with SSAO.

A lot of these Lumen flaws can be mitigated with cvars. Epic is trying to get it to 60 fps on console without too much fuss, but if you want to spec for a 4090 you can get a much cleaner image if you’re willing to tinker.

Increasing various probe resolution and temporal accumulation buffers are potentially big wins for more stability, but lots of hardware can’t handle the VRAM load.

I’ve looked into rendering niagara into a render target. There doesn’t seem a way to do accumulation operations like doing additive color on all the particles that end up in the same pixel. And I’m only allowing a particle to affect one pixel at a time to start. Well, unless I iterate over every particle for every pixel. And I couldn’t find any atomic support in the custom hlsl node in niagara. So that’s out.

You can at least get the last written particles to show up (as overwrites). And it’s at least a start. But the point is there doesn’t seem to be anything straightforward.

The flickering is a deal breaker though. It’s really really bad. And when even a 4090 can’t deal with it by large studios, well…

I’ve done some testing on Niagara and Proxy rasterized plane projection of the effect with and without screen traces in Lumen. The proxy took some doing. I’ve only been able to find SetRenderTargetValue node for Nigara scratch pads. Not sure what one would do to render sprites into a render target. Maybe export the data to blueprint and render it there?

Anyhow, what I have is one pixel per sprite. And I actually did a + sign, so wrote the adjacent pixels as well. It looks great with screen traces and updates in real time. Unfortunately, there’s no way to hide it from the main pass with screen traces. Without screen traces, you can do it, but it’s really blocky. I’m guessing it uses Distance Field Meshes. It also updates VERY slowly (because of Lumen, not the proxy. The proxy still updates in real time). So there’s no actual combination that’s what I would call acceptable, but I think there are at least some options if you have less reflective surfaces that blur the reflections.

There were some surprising results. None of them really good, but a few surprises along the way.

Lumen is always on for these tests.

First up is just trying to get a Niagara effect to reflect on a surface. The settings listed are in the sprite material (opaque, two sided, masked, etc.)

Niagara sprites:

Material Setting With Screen Traces w/o Screen Traces
Opaque Yes No
Masked Yes No
Translucent No No
Additive No No

Conclusion here is that Lumen without screen traces doesn’t work at all with niagara. With screen traces, it looks really good for the settings that do work. But it only works on masked materials. So it comes out a bit blocky. But it does work. This is about as good as it’s going to get unfortunately. Here’s a screenshot of a reflected niagara effect using masked material sprites (supposed to use Additive, but that doesn’t do reflections). The reflection actually looks better than the main pass. LOL

Next is the use of a proxy surface mentioned above. I was able to get this to render to a flat plane in real time. It is very pixelated even at 512x512. I placed a plane over where the original niagara effect should go. The goal is to not render the proxy in the main pass, but only for indirect lighting. To do this, we make Visible = false, Affect Dynamic Indirect Shadow = true and Affect Indirect Lighting While Hidden = true. I’ve tried TONS of other settings, but none of them worked properly. I did try RayTracingQualitySwitchReplace node in the proxy material, but it didn’t do anything that the previous settings couldn’t do.

So in the following tests, Nigara is not used at all. Only the proxy and only in the relfections. It is not drawn in the main pass at all (even though Render in Main Pass = true).

Proxy Reflections (invisible in main pass):

Material Setting With Screen Traces w/o Screen Traces
Opaque Two Sided No One Side
Opaque One Sided No One Side
Masked Two Sided No One Side
Masked One Sided No One Side
Translucent Two Sided No No
Translucent One Sided No No
Additive Two Sided No No
Additive One Sided No No

This technique doesn’t work at all with screen traces. And it only works on one side with Lumen (w/o screen traces). So you could duplicate the proxy and flip it around I suppose.

The two big problems here are that it’s VERY blocky and updates every 2-3 seconds. It is not real time like the screen traced Niagara reflections.

Here’s a screenshot of what that looks like. Note the idea is that the proxy does the reflection and when you turn on Niagara (which has no reflections) will handle the main pass. It looks ok in this screenshot, but in reality, the blockiness and choppiness of it loses its appeal when you see it live. If it looked like this but didn’t look so choppy, it might actually be worth it. I can’t stress how disconcerting it is when you see it live.

Finally, we turn on the proxy in the main pass. Sometimes overlapping the proxy with the niagara effect can be a promising alternative. We still leave Niagara effect turned off for this test, but the proxy should now be visible in both the main pass and in the reflection. In production, the proxy and Niagara effect are both visible in the main pass, but the proxy handles the reflection.

Proxy visible in main pass:

Material Setting With Screen Traces w/o Screen Traces
Opaque Two Sided Both One Side reflection, but both sides main pass.
Opaque One Sided One Side One Side
Masked Two Sided Both One Side reflection, but both sides main pass.
Masked One Sided One Side One Side
Translucent Two Sided No No
Translucent One Sided No No
Additive Two Sided No No
Additive One Sided No No

We can conclude that Lumen doesn’t work at all with translucency and additive materials for reflections.

This last test did reveal an oddity with masked materials with pure Lumen (no screen traces). It respects the Two Sided flag in the material for the main pass, but not for the reflection. It is rather odd seeing both sides drawn correctly in the main pass, but only one side of the gate has a reflection.

I’ve already shown non screen traces screenshot. So here’s the screen trace of the proxy.

The strange thing here is that the reflection takes on a much bluer tint in the reflection when screen traces are used compared to no screen traces.

In conclusion, Lumen reflections are in quite the abysmal state unless you’re fine using masked materials and even then…

I’d give Lumen reflections an F- at the moment. And that’s being generous. IMO, they’re even worse than SSR. At least SSR draws something. Lumen draws NOTHING.

The two best options are these:

  1. With screen traces, you have no choice but to make the proxy visible in the main pass, so a proxy with less lit pixels to hide it within the niagara effect might be possible. And it has the bonus that the reflection is still visible when the main asset is off screen with Lumen directly as blocky as that is.
  2. Without screen traces, you can turn off the main pass of the proxy, but the reflection is VERY blocky and choppy (it does not update in real time. It updates every 2-3s).

And that’s fairly disappointing to say the least.

Conclusion: Lumen reflections… worse than SSR. Unless you hide everything that’s not strictly opaque. :frowning:

Rather than having a proxy that doesn’t render in the main pass but only in RT (which does have limitations as you noticed) it is also possible to just have the proxy faked reflection entirely in a material. Take a look at the material node “Virtual Plane Coordinates” for one example solution. It will create a UV system that you can position manually, allowing you to superimpose a sprite onto any surface which that shader is applied. By applying this to the ground (such as with a decal) you can effectively apply a reflection billboard. The decal can sample the normals of the underlying material to perturb the UVs of the virtual plane or a any number of shader trickery to make the reflection convincing.

Since it’s fake, it’s not without limitations and flaws… but virtual planes are one of my favorite material hacks.

1 Like

I looked at the node you mentioned. I was able to figure out how it works after playing around with it for a while. I think you may have just saved reflections in my project… at least in a few specific cases. I’m not sure most people would even know how to begin to use this though.

Here’s Lumen on, screen traces on. So reflections of the opaque materials still work for off screen stuff, just a little blocky. Niagara on. And using VirtualPlaneCoordinates on the material on the reflective surface using a texture sample of my proxy texture that is generated in real time. Clipping it was not obvious since the world coordinates are for the original extents, not the reflected one. And yes, a decal would likely be better but for testing, this is fine. Anyhow, this is animated and updates in real time and look really good compared to everything else I’ve tried.

The irony is that the proxy now looks better than the opaque reflection.

Not sure you can use this everywhere. This is a proxy of a niagara effect that is then reprojected onto another surface in that material. It’s a LOT of work. And clipping is a real issue. Nonetheless, a VERY useful tool to have. Thanks for the suggestion!

One thing I did notice too is that the reflection does bounce off the original mesh for added reflections on the ring gate itself.

1 Like

You can get it to behave pretty much exactly like SSR by changing the screen tracing source to antialiased scene color with translucency.

Lumen

SSR

1 Like

I couldn’t get this to work.

I’m getting a strange aliased white line artifact with Lumen reflections on highly reflective planar edges where they meet walls. If I turn off Lumen Reflection Screen Traces it goes away. This behavior doesn’t happen in editor, only in PIE and builds. Anyone else experienced this or have any tips? I’m using 5.5.4.

Here’s what it looks like in PIE…

…and in the viewport…

@Krzysztof.N Have project moved from 5.6 to 5.7, at first thought had something changed on my side, but later decided to check much older version, convert to the 5.7.. And things are quite dark in 5.7. Local Fog seems unlit in 5.7..

The same lighting set up in two clean projects. 5.6 > 5.7 , it seems atmosphere is not affecting GI in 5.7..