Jump to content
  • Advertisement
Sign in to follow this  
adt7

Deferred Shading - Handling Reflections

This topic is 3160 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

What is the best way to handle reflections in a deferred rendering pipeline? Currently I'm doing something along the lines of the following:
Each frame:-
   Fill G-Buffer with regular objects
   Light GBuffer (including shadow maps, SSAO)
   Forward render objects that require reflection/refraction data
   Forward render alpha blended objects
   Post-process scene

Once a second:-
   Fill 1/2 size GBuffer with reflection data for main water plane
   Light reflection GBuffer (max. 1 directional, 4 largest effect point/spot lights only)
   Store result for use in all frames before next update
Currently this is fine for my main water plane, but what about if I want to add a lake at a higher level than this? Or a mirror? Adding yet another reflection buffer (or more than 1) is adding even more memory/fillrate/bandwidth overhead, even at 1/2 size and it's seems like it's going to get out of hand. I know I can "cull" them based on visiblity, but I'm thinking worst case scenario of say, 3 reflective objects in a scene at once. Perhaps a system with a 1/2 size buffer for the largest object (most likely main water if in view) and two 1/3 or 1/4 sized buffers for the smaller ones? Surely there is a better way of handling this? Reducing the reflection buffers to 1/3 or 1/4 size potentially works, but too be honest I might as well not bother with reflections if I'm going to have them look that pixelated. Does anyone else have any experiences they could share? Much as I love deferred shading for it's elegancy, it's bloody annoying in other ways, issues like this make me want to scrap it in favour of forward rendering. In case it's relavent, I'm using DirectX 9 currently, but could be persuaded to move up to 10 if there is a big enough reason, although I'd really rather not. Plus, this is more of an API agnostic question, as I'm looking for an idea of the best way to implement this, as apposed to code.

Share this post


Link to post
Share on other sites
Advertisement
Deferred renderers are considered as very bad renderer in case of reflection rendering.

Maybe using 1/nth of buffer size when you're getting more distant (for closest use 1/2 or full size.
Although there might be also another solution (with help of hybrid rendering and mixing reflection layers while performing deferred shading (but hell that might need lots of fillrate)).

I'm just thinking of a way how this could be solved very quickly and I think I'm on a good way nowadays ... maybe in next weeks I'm about to release some demo. Reflection will also be correct (and also physically accurate? ... or at least close to be physically accurate), of course with all light/shadow effects.

Share this post


Link to post
Share on other sites
Planar reflections: render the view like you'd do for the main screen. Using a downscaled resolution is reasonable, I usually use 2x2 or 3x3 smaller views and apply a vertical blur on them to emulate the rough water appearance. At the main screen then render the water plane forward - it shouldn't really matter how you do it because there's no lighting involved anyways.

CubeMap reflections: render only the reflectional part of the lighting equation after everything else, and use additive alphablending to apply it. To my knowledge, the fragment colour in that case is basically "diffuse * light + reflection_term", so you can render reflective objects in the standard deferred way and then add the reflective part afterwards in a forward fashion.

Share this post


Link to post
Share on other sites
So multiple "reflection buffers" is the only real way to do it?

Guess I need to add them as a more dynamic thing within my renderer to allow them to be "culled" when not required.

Share this post


Link to post
Share on other sites
Well... not sure what you mean by "multiple reflection buffers". If you have multiple reflection planes, then of course you have to have a reflection buffer for each. Or you apply tricks like choosing only the most prominent reflection plane and use that for all planes. It will look wrong, but you'd surprised how many games still use that approach.

If you're going for the multiple reflection planes approach (which I find naturally, at least from the engine architecture POV), I suggest applying all possible culling options you can think of. In my experience, rendering a reflection plane takes a lot of CPU power for all the additional draw calls - you need to cut corners wherever possible. Cull the whole reflection rendering pass if the reflection plane is outside the frustum. Cull all objects beyond the reflection plane. Try to narrow the reflection frustum to the borders of the reflecting mesh. This is particularily effective if you have locally limited reflection planes like a lake surface, for example. If it covers only the right half of the screen, you can cull the left half of the scene when rendering the reflection.

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!