Deferred Rendering (light + parallax + shadows + ssao + fog + bloom + fxaa)

Here be what I have been playing around with over the holidays (when I can).

Deferred lighting is fairly straight forward, however does everything in 2 steps… one time through the geometries… a single shader for applying all lighting. Standard parallax can be enabled here. (Transparent-type buckets are rendered separately and handled differently)

SSAO is a new simple filter with very nice results.

The shadow renderers are a single filter (and only filter), which renders all shadows for lights with casting enabled. The filter then puts together the single image output in one pass. Blending is completely post process, which allows for using a very simple 4 slot poisson disk for initial edge dithering and then blending (all shadows as one image) can be more complex… (The vid is minus final shadow blending)

Since shadows are computed before lights, lights actually effect the final shadow output (which you can see in the vid).

Fog is added at the final composite and effects everything through the chain (minus post filters added after the deferred process)

The bloom and fxaa are standard JME filters added to the end of the deferred chain.

Here is a vid of the progress thus far:

[video]http://youtu.be/j-aQhKPEUMY[/video]

19 Likes

Oh, cool :slight_smile: Make a demo with 1k lights love those :wink:

1 Like

Wow that’s really nice!!!
Well done!
I specially like how shadows fade with lights.

Tell me more about this shadow filter, you still have a geometry pass from the light point of view right?

1 Like

Coool, looks really good.

1 Like
@nehon said: Tell me more about this shadow filter, you still have a geometry pass from the light point of view right?

Yeah, it has too for sure. The idea was to try and simplify what is required during that pass (still 6 for point lights as well) to allow for multiple shadow casters at a much lower cost and then put the heavy load on a single blending shader after all shadow depth maps are drawn and compiled into a single image. It still needs quite a bit of work to find the correct balance between the two. But! The basic idea works well enough to proceed at least.

So… each pseudo light contains a frame buffer and depth texture (if casting is enabled). During the postQueue, it cycles through the lights… updates the single shadow camera according to the light, shadow map size, etc and then renders the casters of the scene from that light’s perspective.

The filter’s material is handed all the compiled info (light projection matrices, depth maps, shadow intensities, etc), a depth map of the receivers from the view cams perspective and compiles the shadow output. At this point the SSAO filter had already run and the unblended output was handed into this shader to be mixed into the final output.

This output is handed to the lighting pass and the sum of the diffuse light is blended into the shadow map.

After this, there will be a blending shadoer which is where I’m hoping all the magic will happen to make up for anything lacking in the shadow map thus far.

Right now, using 1024x1024 maps (directional lights) the output is pretty acceptable with no blending pass… mostly due to the touch of realism the lighting being blended back in the shadow maps brings. I have high hopes for the next step.

Actually… that reminds me. I had a question about how the shadow renderers currently work. Does the renderer not flush the shadow queue to allow for chaining different renderers? This is something I am having to do (or thinking I need to do) currently and I’m not sure if it’s a bad idea… and if it is ok to do during the frames process, Are the queues flushed prior to the next frame automatically at some point? Or do I need to call something to do this?

On a final note, transparencies are starting to really work out. The major issue I’m hitting right now is alpha additive blending over shadows. It’s there… however alpha additive over daaaaaark = blech and can almost come across like the depth testing was backwards =(

1 Like

Yes, really cool! Finally we will have a new efficient solution for massive lightning and shadowing…can’t wait to play with it :).
Great job…as usual ;).

1 Like

Hey wow, that looks really nice, great work =)

Not sure if it answers your question, but while working on shadow integrated lighting, I ran into a similar issue, which I worked around like this :

[java]
private void addShadowRenderer(AbstractShadowRenderer shadowRenderer) {
if (!shadowRenderers.isEmpty()) {
shadowRenderers.get(shadowRenderers.size()-1).setFlushQueues(false); // make sure only the last added shadow renderer flushes the render queues
}
shadowRenderers.add(shadowRenderer);
if (isInitialized()) {
shadowRenderer.initialize(renderManager, viewPort);
}
}
[/java]

hopefully that is helpful =)

1 Like
@thetoucher said: Hey wow, that looks really nice, great work =)

Not sure if it answers your question, but while working on shadow integrated lighting, I ran into a similar issue, which I worked around like this :

[java]
private void addShadowRenderer(AbstractShadowRenderer shadowRenderer) {
if (!shadowRenderers.isEmpty()) {
shadowRenderers.get(shadowRenderers.size()-1).setFlushQueues(false); // make sure only the last added shadow renderer flushes the render queues
}
shadowRenderers.add(shadowRenderer);
if (isInitialized()) {
shadowRenderer.initialize(renderManager, viewPort);
}
}
[/java]

hopefully that is helpful =)

Still trying to figure out if this is necessary in my case. The JavaDocs for Filter seem to elude to the queues being flushed prior to postFrame and when I render the queues, I’m current just setting flush to false. Though, the JavaDocs might be written with the default rendering process in mind… which flushes them after rendering the queue. /shrug.

Do you know if the is a way of just flushing a queue without calling any render method?

That’s nice.

1 Like
@t0neg0d said: Do you know if the is a way of just flushing a queue without calling any render method?
GeometryList.clear()
1 Like

Hey! This is actually turning out quite nice! Here is a screen cap of the final shadow image after blendedededing: (The new SSAO needs a little bit of tightening up IMO)

And here it is mixed back into the scene:

2 Likes

@t0neg0d Is this already in core? How can I use this and reproduce what you did in the video? Cheers

@hudy said: @t0neg0d Is this already in core? How can I use this and reproduce what you did in the video? Cheers

It is not… this was just a personal project for fun. I’m sure @nehon will eventually provide a deferred rendering system for JME once things are a bit more stable. I know that there has been quite a bit of talk (and some effort) towards this already. However, the system that I put together requires use of a very specific method of rendering Geometries which would only play nice with JME if it were to use the shader nodes system.

I’ll donate what I have done towards this effort, whenever it gets underway.

4 Likes
@t0neg0d said: Hey! This is actually turning out quite nice! Here is a screen cap of the final shadow image after blendedededing: (The new SSAO needs a little bit of tightening up IMO)

That’s really nice. It’s a real shame there is the need to render from the POV of each light to get the shadows as that must be the main bottleneck on adding huge numbers of lights now.

@zarch said: That's _really_ nice. It's a real shame there is the need to render from the POV of each light to get the shadows as that must be the main bottleneck on adding huge numbers of lights now.

This is only the case is shadows are enabled for the light in question. You can have 600+ light and only 4 casting shadows at any given time and you’ll get stellar framerates.

Actually, it’s also worth mentioning, that shadow dithering is probably the most expensive part of the process. This method allows you to minimize that for each independent light casting shadows and then use a “community” blending process on the collective output.

Yeah, in fact you could possible look at the brightness and proximity of the lights and pick the most significant ones to generate shadows for although avoiding popping style effects with that would need some work.

@zarch said: Yeah, in fact you could possible look at the brightness and proximity of the lights and pick the most significant ones to generate shadows for although avoiding popping style effects with that would need some work.

Another way to speed up the process is to dynamically change the shadow map size using some form of prioritized importance.

This could be as simple as camera.getDirection().dot(light.getDirection()), then sort and resize (-1 being the highest priority–i.e. the shadows are facing towards you), 1 being the lowest priority) for directional.

Points based on camera.getLocation().distance(light.getLocation()) + thecamera.getPosition().dot(light.getPosition())

And spots could be prioritized using a combination of the above.

Directional would likely receive highest priority due to the nature of directional lighting, However, the prioritizing would be fairly simple and and minimize the fps damage for anything that was off in the distance or facing away from you, leaving detailed shadows for the most noticeable.

Hi,

Any updates @t0neg0d ? I’m really interested in this. Can you explain how you set up your system please…i plan to work on shadows in my game and i will make my own shadow filter so i want to know if you always use it or if you have done some things internally and that’s a waste of time to do it now ^^.

Thanks.