Jump to content
  • Advertisement
Sign in to follow this  
SeraphLance

Deferred Shading on Complex Scenes?

This topic is 2130 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I'm trying to implement deferred shading.  I understand this is a little advanced for this subforum, but it's  more of an architectural question than anything else.

 

As I understand it, deferred shading is basically something like:

Define buffers (position, normal, diffuse, etc.)
...
Render scene into buffers

load buffers as textures
render fullscreen quad with lighting computations.

There's a number of complexities this glosses over that I'm uncertain of.  Namely, in a forward render, multiple draws frequently correspond to multiple objects.

 

Does a more descriptive pseudo-code look something like this?:

Define buffers (position, normal, diffuse, etc.)
...
for each object in scene:
    render object(aka:
        if pixel in front of existing depth value:
            blit(???) buffers with pixel information)
load buffers as textures
render fullscreen quad with lighting computations

...or am I over-complicating things?

 

I don't have any significantly solid code yet because I'm still trying to grok some stuff, but this has left me sort of stumped.

Share this post


Link to post
Share on other sites
Advertisement

No, that's not over complicating things. If anything you've underestimated what needs to be done.

 

One of the main differences between forward and deferred rendering is that forward rendering typically requires a pass per light and you accumulate the results into a buffer (which you then present or post-process, etc.). In deferred you render all the objects once, to your g-buffer and then do another pass with all the lighting objects. It is important to note that lighting objects can be geometry, which is a lot easier to conceptualize and apply (imo) with deferred rendering. It also makes doing a lot of other things, like shadow maps and volumetric lights fairly easy as well (shadow maps are almost implicitly supported by deferred rendering).

Share this post


Link to post
Share on other sites


if pixel in front of existing depth value:
blit(???) buffers with pixel information
Isn't that just psuedo-code for enabling depth-testing, which should be on in forward rendering too?

Share this post


Link to post
Share on other sites

Lighting as geometry is interesting.  I'd only just recently read about that somewhere.

 

 


if pixel in front of existing depth value:
blit(???) buffers with pixel information
Isn't that just psuedo-code for enabling depth-testing, which should be on in forward rendering too?

 

 

Essentially.  I was meaning to draw focus to the blitting part.  I guess, now that you bring that up, "blitting" is just the analogue of writing to the backbuffer in a traditional forwarding setup.  I hadn't thought of that -- for some reason I was thinking there had to be some hand-rolled way of updating the G-Buffer when it's already done.

Share this post


Link to post
Share on other sites

The difference in the blitting part is that in forward rendering, each pixel writes out a float4 and a depth value, whereas in deferred each pixels writes out N x float4's and a depth value by using MRT -- instead of writing to a single render-target/back-buffer, you bind usually ~3/4 render-targets at the same time.

Share this post


Link to post
Share on other sites

Is it really common for people to handle just one light per pass when forward rendering? I've never done it that way, but I keep hearing about it.

Share this post


Link to post
Share on other sites

It was very common on older hardware. Up through DX9 hardware you had limited instruction counts for shaders, and those shaders weren't very flexible in terms of branching or executing dynamic loops. In fact Unreal Engine 3 was originally designed with multipass forward rendering, although I don't know if they changed that later on in the console lifecycle.

On DX10+ hardware it's a different story, and it wouldn't make any sense to do multipass lighting. In those cases the major difference from deferred is granularity of lighting: with forward lighting you typically must select your lights per draw call, while with deferred you can do it per-pixel.

Share this post


Link to post
Share on other sites

Another reason to limit yourself to 1 light per pass is if you want to avoid the combinatorial "explosion" of shaders, and can't either precompile an excessive amount of shader variations or compile them during runtime as needed (eg. Windows Store apps forbid the latter.)

Share this post


Link to post
Share on other sites

Another reason to limit yourself to 1 light per pass is if you want to avoid the combinatorial "explosion" of shaders, and can't either precompile an excessive amount of shader variations or compile them during runtime as needed (eg. Windows Store apps forbid the latter.)

If you're passing in the lights as a set of arrays to your shader, simply setting those lights who are not going to be applied to 0 (assuming accumulation) will cause those lights to be ignored. There's very little shader explosion in this case.

 

It was very common on older hardware. Up through DX9 hardware you had limited instruction counts for shaders, and those shaders weren't very flexible in terms of branching or executing dynamic loops. In fact Unreal Engine 3 was originally designed with multipass forward rendering, although I don't know if they changed that later on in the console lifecycle.

On DX10+ hardware it's a different story, and it wouldn't make any sense to do multipass lighting. In those cases the major difference from deferred is granularity of lighting: with forward lighting you typically must select your lights per draw call, while with deferred you can do it per-pixel.

Thanks for the correction, I've only dealt with forward rendering in DX pre 10. After 9 I've only dealt with deferred and similar forms of rendering. Mostly on the hobby sense, since the only thing I currently use DX for professionally is DirectCompute. Mind you, even in D3D9 you could still do about 4 lights per shader, depending on the complexity of the shader.

Edited by Washu

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!