Skip to main content
GameDev.net gamedev.net
🔒 Locked

Crysis using Deferred Shading ?!

Started by sepul Sep 24, 2006 at 11:38 AM 36 replies 15.1k views
Original Post
sepul
sepul
check out this screenshot : http://ve3dmedia.ign.com/ve3d/image/article/698/698899/vista-delay-impacts-crysis-release-20060328062524952.jpg notice the wierd silhouette on the edges of the chains (bottom), I think it is due to a bug in deferred shading, cuz I have encountered the exact same bug in my deferred renderer, the problem is actually with the texture reads from G-Buffer that doesn't match quite well with the screen quad and has precision problems. another thing is that the shot has no anti-aliasing, which is really easy to do on the forward renderer, unless it is some kind of deferred shading technique which is incompatible with AA. any opinions ?
nts
nts
AFAIK Crysis is still using a forward renderer, this was covered in one of the Crytek and ATi papers, can't remember which (something about enviornment, clouds, etc).

linkified image (use html < a href = '' > < / a > tags, without the spaces)

EDIT: This Paper

Quote:
CryEngine2 uses traditional rendering style

Matt Aufderheide
Matt Aufderheide
Yes i think that sillouette on the chains is some kind of reflected light, not an error.

I would suprised if any game engine ever uses deferred lighting.
Toji
Toji
S.T.A.L.K.E.R. will be using deferred lighting when it's released.... if it's released...

So yeah, it may be that none ever do use it. :)
// The user formerly known as Tojiro67445, formerly known as Toji [smile]
AndyTX
AndyTX
Quote:
Original post by Matt Aufderheide
I would suprised if any game engine ever uses deferred lighting.

In the near future I'd be surprised if any games *didn't* start to use some aspects of deferred shading to be honest - but I guess that's a discussion better left for another thread :)

However I agree that the error doesn't particularly resemble anything that I've seen in deferred shading. In particular I'm interested in why you're having any precision issues with it... there should be none; make sure that you're sampling the centers of pixels properly (this is actually a bit odd in Direct3D 9).
Matt Aufderheide
Matt Aufderheide
Nothng is horribly wrong with differed shading. I just dont think its benefits outweigh its disadvantages. It seems as though its only real benefit is allowing many lights per vertex/pixel..but in my view this is a rarely encountered event that hundreds of point lights affect one polygon...there are other easy ways to get around this.

Maybe I'm wrong, I have never implemented a differed renderer so maybe it has more uses.
sepul
sepul
Quote:
However I agree that the error doesn't particularly resemble anything that I've seen in deferred shading. In particular I'm interested in why you're having any precision issues with it... there should be none; make sure that you're sampling the centers of pixels properly (this is actually a bit odd in Direct3D 9).


I was using this quad :
			verts[0].pos = hmrVector3( -1.0f, -1.0f, 0.0f );			verts[1].pos = hmrVector3( -1.0f, 1.0f, 0.0f );			verts[2].pos = hmrVector3( 1.0f, -1.0f, 0.0f );			verts[3].pos = hmrVector3( 1.0f, 1.0f, 0.0f);						verts[0].coord = hmrVector2( 0.0f, 1.0f );			verts[1].coord = hmrVector2( 0.0f, 0.0f );			verts[2].coord = hmrVector2( 1.0f, 1.0f );			verts[3].coord = hmrVector2( 1.0f, 0.0f );


for the lighting post process, and I got a little silhouette edges around objects on some views, but when I subtracted a little epsilon value from the right and the bottom of the quad, it was fixed.
(I'm using no filtering on the g-buffer textures)
I thought it was a bit odd too, but couldn't find the source of the problem.
am I doing something wrong there ? just drawing that quad with no transformation, and fetching the data from g-buffer textures in pixel shader ...

Quote:
AFAIK Crysis is still using a forward renderer, this was covered in one of the Crytek and ATi papers

yes, my mistake, but I think they are using some kind of hybrid method (deferred) on thier environmental effects like unreal3

Quote:
I just dont think its benefits outweigh its disadvantages.

but I think it has more pros than cons, good batching, less draw calls, clean renderer, high-poly scenes with lots of dynamic lights, ...
the two main problems for me are AA and fillrate issues, which I don't have any idea which of the methods are gonna be faster in the end.
but my guess is the more you increase the objects/polys and lights in the scene, is where the deferred renderer really shines

anyway, it's all just my theory, cuz I'm still developing the renderer, I can't be sure about it unless it is done, I just hope it won't turn me down.

[Edited by - sepul on September 24, 2006 7:41:42 PM]
sepul
sepul
Quote:
According fullscreen quad UVs refer to
http://developer.nvidia.com/object/Mapping_texels_Pixels.html


oh thanks for article, I now got it solved in the right way !
Nitrogen
Nitrogen
That artifact looks more like an overactive fresnel term on a metal pixel shader...
Delphi C++ OpenGL Development: www.nitrogen.za.org
AndyTX
AndyTX
Quote:
Original post by sepul
oh thanks for article, I now got it solved in the right way !

Yep that's the weirdness of D3D pixel/texel mapping that I was mentioning. Note that there's a similar article in the D3D SDK, albeit less detailed.

Also note for interest that IIRC D3D10 will switch to the same pixel/texel scheme as OpenGL (i.e. with pixel centers at .5's) and I believe the XBox360 has state to use the alternate pixel centers if you wish (ATI's control panel also includes this setting, although that's less useful).
AndyTX
AndyTX
Quote:
Original post by Matt Aufderheide
Nothng is horribly wrong with differed shading. I just dont think its benefits outweigh its disadvantages.

There are three benefits that are huge in my books:

1) Depth (and neighborhood depth) available to fragment shader. This is true of all of the g-buffer data actually, but in particular having depth available (and writable on the first pass) makes a lot of volumetric or displacement algorithms quite simple.

2) Solves/eliminates combinatoral explosion of shaders with different lighting combinations. This is going to be a huge problem in the future since multipassing every light will simply not be an efficient option. It can be dealt with in other ways, but none are as ellegant or scale as well.

3) Computes light extents per-pixel (using arbitrary light geometry). The best you can do without something like deferred shading is per-object, and even that can be expensive.

The only disadvantages that I see:

1) Incompatible with MSAA. This might get easier in D3D10 when we have some control over the multi-sample resolve step. Even then, I'm not too interested in MSAA in the long term, although it is useful right now.

2) Incompatible with object sorting schemes (like alpha blended transparency). Again I'm not interested in alpha blended transparency in the long run (it's a hack anyways), but moreover you can always do these passes after deferred shading... so this isn't really even a problem.

Anyways I didn't mean to get back into deferred shading, but it's so good... I feel the need to spread the news ;) I have developed a forward renderer and deferred renderer from scratch that effectively use the same shader fragments and so are relatively interchangable (even at runtime). That said, the deferred renderer often offers many more possibilities for advanced algorithms and rarely (if ever) limits any.
daktaris
daktaris
Quote:
Original post by AndyTX
Quote:
Original post by Matt Aufderheide
Nothng is horribly wrong with differed shading. I just dont think its benefits outweigh its disadvantages.

There are three benefits that are huge in my books:

1) Depth (and neighborhood depth) available to fragment shader. This is true of all of the g-buffer data actually, but in particular having depth available (and writable on the first pass) makes a lot of volumetric or displacement algorithms quite simple.

2) Solves/eliminates combinatoral explosion of shaders with different lighting combinations. This is going to be a huge problem in the future since multipassing every light will simply not be an efficient option. It can be dealt with in other ways, but none are as ellegant or scale as well.

3) Computes light extents per-pixel (using arbitrary light geometry). The best you can do without something like deferred shading is per-object, and even that can be expensive.

The only disadvantages that I see:

1) Incompatible with MSAA. This might get easier in D3D10 when we have some control over the multi-sample resolve step. Even then, I'm not too interested in MSAA in the long term, although it is useful right now.

2) Incompatible with object sorting schemes (like alpha blended transparency). Again I'm not interested in alpha blended transparency in the long run (it's a hack anyways), but moreover you can always do these passes after deferred shading... so this isn't really even a problem.

Anyways I didn't mean to get back into deferred shading, but it's so good... I feel the need to spread the news ;) I have developed a forward renderer and deferred renderer from scratch that effectively use the same shader fragments and so are relatively interchangable (even at runtime). That said, the deferred renderer often offers many more possibilities for advanced algorithms and rarely (if ever) limits any.


YOU may not be interested in alpha transparency but 100% of the texture artists at my work are and probably 98.435% of the ones I've worked with in the past are as well...for the long run btw (meaning the next 3 or 4 games we ship). As far as being a "hack"...it's a damn good one and has served games well for a long time. I'll take those kind of hacks any day. Maybe our definitions of hacks are different.

per MSAA...fair enough...I can roll with that.

To further the discussion on deferred shading. Let's assume you are correct and it is the future...now what?

How do we move forward?

What are the steps we need to take as engine programmers to move forward with this without sacrificing backwards compatibility(as far back as GF3 given the numbers of those cards still around)?

Is it going to be a simple context switch at a high level to change techniques (much like moving between different shader versions) or a major engine overhaul? You mention a runtime switch in your app can you please describe at a high-level where the breakoff is? For example, am i going to have to rewrite the scene graph class?

Are light batching techniques like those found in ShaderX4 temporary solutions on the way to deferred shading or are they going to be final solutions (basically fast approximations that look "good enough")?
AndyTX
AndyTX
Quote:
Original post by daktaris
As far as being a "hack"...it's a damn good one and has served games well for a long time. I'll take those kind of hacks any day. Maybe our definitions of hacks are different.

I only mean that it's a "hack" with respect to the proper way to compute transparency in a scene. i.e. one has to sort per-object rather than per-fragment. The "right" ways to do it are either raytracing (not that far off, and handles much more complex effects like refraction as well) or A-buffers (or something similar that sorts fragments... but the hardware necessary to do that would be unreal). Transparency information will certainly continue to be encoded into the alpha channel, but the way that we compute in the scene will probably change (i.e. not sorting the render order back to front).

Quote:
Original post by daktaris
What are the steps we need to take as engine programmers to move forward with this without sacrificing backwards compatibility(as far back as GF3 given the numbers of those cards still around)?

Supporting deferred shading only really "requires" floating point render targets (and not filtering). I think probably it will be reasonable to target GF6 as the low end by the (hypothetical) time that deferred shading is common.

Quote:
Original post by daktaris
Is it going to be a simple context switch at a high level to change techniques (much like moving between different shader versions) or a major engine overhaul?

It's generally a high-level change to the rendering loop, but shader changes may be required depending on how tightly coupled they are. Using something like libsh or Cg interfaces can reduce the coupling drastically and make the changes pretty minimal. Effectively computation of the BRDF is now factored out of the surface shaders (which now simply output attributes that are input to the BRDF).

Quote:
Original post by daktaris
You mention a runtime switch in your app can you please describe at a high-level where the breakoff is? For example, am i going to have to rewrite the scene graph class?

In my case, only the renderer needed to be modified/rewritten, and that was less than 1000 lines of relatively high level code. The scene graph can remain totally untouched. As I mentioned it was a bit easier in my case since I was using Libsh (and already had light shaders disjoint from surface shaders).

Thus the forward renderer has to:

1) Sort and group lights per-object as best it can.

2) Generate permutations of shaders with different lighting combinations.

3) Match the light sets from #1 with those from #2 (or generate/cull either as necessary) and render each object.

The deferred renderer has to:

1) Do a relatively simple register-allocation like pass to encode scene BRDF inputs into the G-buffer - it then tags simple encode/decode shaders (which are often just swizzles) onto the surface and light shaders in the scene.

2) Render objects (outputs go to G-buffer).

3) Render lights (input from G-buffer, output to framebuffer).

As you can probably imagine from the above, the deferred renderer is actually significantly shorter and more straightforward.

Because of the extra memory bandwidth required, the deferred renderer takes a constant-time hit in performance, but scales *much* better with scene and lighting complexity. Indeed one doesn't need to get very complex with the scene before the deferred renderer begins to win in performance.

Quote:
Original post by daktaris
Are light batching techniques like those found in ShaderX4 temporary solutions on the way to deferred shading or are they going to be final solutions (basically fast approximations that look "good enough")?

I haven't read the actual chapter in ShaderX4, but if the techniques are at-all similar to what I've discribed above, they simply do not scale well to complex, dynamic scenes. I don't see it being worth doing these sorts of things in the long run when we can use the rasterizer to solve the problem elegantly, and at a much finer granularity (per-fragment).

In the end, deferred shading is really just a reorganization of the render loop, but one that decouples lighting and geometric complexity (into O(L) + O(G) instead of O(LG)).
griffin2000
griffin2000
They "kind of" use defferred shading... There main rendering is done traditionally but all their effects (particularly their atmoshpherics) rely on a depth texture pass that is then operated on in a "defferred shading" style.

They big disadvantage with DS in my opinion is it doesn't work well with anti-aliasing. Whenever you intelpolate values that aren't colors (e.g. normals, etc) as it they were you will get artifacts.

[Edited by - griffin2000 on September 25, 2006 4:08:40 PM]
wolf
wolf
Quote:
As you can probably imagine from the above, the deferred renderer is actually significantly shorter and more straightforward.
Unfortunately in practice deferred renderer were most of the time slower up until DX9 hardware. I would bet the amount of people who implemented a deferred renderer for a game and had to remove it afterwards because it too slow is pretty high :-) ...
If you measure with real world data, you can find out that the theory does not work out very well especially on next-gen consoles like the PS3 and XBOX 360 (the available memory bandwidth for these consoles are public knowledge).

It is expected that DX10 cards will change this, but this was also expected from DX9 cards.
One of the major disadvantages of a deferred renderer is that it is not well suited for DX8 hardware or slower hardware. In case of slow memory bandwidth is never an option ... check out a 7600 GT to see what I mean :-).

The most famous game that uses a deferred renderer currently was not released so far (Stalker) ...
MENTAL
MENTAL
Can't you just perform a manual AA pass using an edge-blending filter ?
wolf
wolf
... it will not look as good as MSAA (multisampling + AA).
multisample
multisample

Wolf is right on the money. We tried out deferred rendering for a while. Its main drawback was/is bandwidth. Lack of MSAA support (which is big to us as well) is second, and a secondary alpha pass is a distant third (not that big of a deal). The bandwidth issue with GF6 series cards is a big problem. The framebuffer bandwidth is a problem along with texture bandwidth (since G-buffers are usually large uncompressed textures).

Personally, I love the relative simplicity of deferred rendering. I can live without MSAA and do it manually to some degree if it makes life much easier. Also, to be completely fair, the material params in G-buffers still are a limiting factor for some geometry. For our characters we ended up rendering them "forward-style" do be able to do more complex materials. We could have used up another render target , but that would have been even more expensive.

Without deferred you are left doing some more light sorting. Realistically this isnt' horrible as we were already doing this sort of stuff for previous gen. The problem is the extra PS ALU required if you are doing multiple lights per-pass, since some lights may not hit all of an object. Deferred does this much better. If you don't do multiple lights per pass, you can do some other optimizations (light stencil/scissor) but you end up rendering the geometry more often, sampling its textures each time (normal mapping etc), and using framebuffer bandwidth for each pass.

That said, I am always looking at deferred as a possible option because of its high points.
AndyTX
AndyTX
Quote:
Original post by wolf
If you measure with real world data, you can find out that the theory does not work out very well especially on next-gen consoles like the PS3 and XBOX 360 (the available memory bandwidth for these consoles are public knowledge).

Deferred rendering should already work pretty well on modern hardware (at least on the PC side - and it does in my experience), but that will only get better. I'm not suggesting that everyone go out and change all of their engines now, but it would be unreasonable to use deferred shading in any new engines still being developed.

I was merely reacting to the comment then no one will ever use deferred shading... I can't comment on the timeline, but I suspect that eventually deferred shading will be the preferred method of rendering (unless something else becomes more attractive first). All of it's so-called "faults" are simply due to current hardware limitations, and are eroding quickly.

In particular, the memory bandwidth of deferred shading - while higher - is extremely coherent and predictable, and thus won't be an issue in the long term. Truely random access patterns can be an algorithmic problem, but that's not the case for streaming memory access. Current absolute bandwidth numbers are immaterial in the long run.

Quote:
Original post by wolf
One of the major disadvantages of a deferred renderer is that it is not well suited for DX8 hardware or slower hardware.

Agreed, but I don't care ;) I'm bored of DX9 hardware, let alone DX8! I'm not saying that this won't be an issue for some people, but again, I'm talking about the mid/long term.

Quote:
Original post by wolf
... it will not look as good as MSAA (multisampling + AA).

Yeah edge filtering can hide artifacts, but it isn't anti-aliasing. Super-sampling is the proper solution and will become more viable in the future. In particular, I suspect that there will be an interesting time before switching to a different method of rasterization (probably REYES or something similar) in which increasing resolution won't cost that much since otherwise you'll be wasting a whole ton of vertex transform power (due to increasingly small triangles).

In the very long term I suspect that it will be quite reasonable to randomly sample both the spatial and the temporal domains, and get some really nice anti-alising and motion blur on *everything*, not just rastization.

Anyways this is mostly speculation, but it comes down to this in my mind: deferred shading's disadvantages are simply due to current hardware - the algorithm is sound and scales very well. However forward rendering has some significant complexity cliffs as scenes become more complex and more dynamic. Efforts to manage this complexity all boil down to solving the problem that deferred shading does at a much courser granularity and in the end it will be much more efficient to simply use a bit more memory on the GPU.

If it was a question of trading off ALU vs Memory, I'd be the first to argue that using ALU is the right way to go in the long term, but it is not. It's a question of O(LG) vs. O(L)+O(G) where the second complexity has a slightly higher constant factor. i.e. as the lighting and geometric complexity increases, algorithm B will be increasingly more attractive...

That's just a performance discussion - as I mentioned, there are a lot of cool algorithms that simply cannot be implemented efficiently in a forward rendering. A paper from I3D on splatting indirect illumination comes to mind.
AndyTX
AndyTX
Quote:
Original post by multisample
Also, to be completely fair, the material params in G-buffers still are a limiting factor for some geometry. For our characters we ended up rendering them "forward-style" do be able to do more complex materials.
[clip]
... sampling its textures each time (normal mapping etc)

Let me be clear that I'm talking about "deferred lighting" here... i.e. the surface shader is still executed in the first pass and only the inputs to the light BRDF are stored. i.e. only the lighting pass is deferred.

In this case, there are relatively few BRDF params to store (16 is usually more than sufficient), and the original scene textures are no longer used after the G-buffer pass (normal mapping, displacement mapping, etc. has all been done by this point).

There are a few select cases to defer other parts of the surface shading, but they are rare and don't produce nearly the benefits that deferring the lighting does.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.