BennyQBD / 3DEngineCpp

It's like the 3D Game Engine, except in C++
Apache License 2.0
297 stars 82 forks source link

Deferred Rendering #23

Open zeyorama opened 10 years ago

zeyorama commented 10 years ago

The current forward rendering technique is easy to learn and good to understand, but a deferred render pipeline would improve performance immense. I'm working currently on a deferred renderer, but I got some troubles. Benny, will you implement a deferred renderer sometimes?

BennyQBD commented 10 years ago

I've said this a few time in various messages and comments, but it's nice that someone's finally asked this in a common, public location for everyone to see:

Yes, I absolutely am going to implement deferred rendering as soon as it will give a significant benefit relative to the tradeoffs.

Something a lot of people miss is that deferred rendering is not a magic bullet: It makes several rendering effects like anti-aliasing, transparency, multiple materials, etc. significantly more difficult to achieve. Furthermore, the performance benefits aren't as great as a lot of people are convinced they are. It's true that a well optimized deferred renderer will out-perform a well optimized forward renderer in most scenarios. What they don't mention is that in many scenes, the performance gain doesn't get really significant (By "really significant," I mean the types of gains that deferred rendering is often hyped to have) until you have more than about 20-30 lights on screen at once (That last part is important: We're not talking about 20-30 lights in the entire scene, just 20-30 lights that are visible at one time).

The truth is, in a lot of scenes, you just don't need more than 20-30 lights visible at the same time. So although implementing a deferred renderer will almost always provide some benefit to performance, you need a pretty extreme scene before you can justify all the tradeoffs and complexities it introduces. This is especially true in my case, as I'm trying to make a tutorial series on this stuff. I don't think a lot of people would appreciate it if I tried teaching them how transparency works by creating an insanely complex transparency system with a deferred renderer, when I could instead show them how to create a relatively simple transparency system in a forward renderer.

If you're worried about performance, there's several things we can do to speed things up before having to make difficult tradeoffs like forward vs. deferred rendering. For instance, right now the engine does hidden surface removal with just z buffering and back-face culling. Although that works, it scales horribly and quickly breaks down on complex scenes. Adding more efficient culling strategies like frustum and occlusion culling can get the engine's performance to scale relative to screen resolution rather than scene complexity. At this stage in the engine's development, I personally think that being able to render arbitrarily complex scenes would be a much more valuable optimization than being able to have more lights. (In truth, it doesn't quite work out to being able to actually render arbitrarily complex scenes, but I'll talk about that in the tutorial. It still gets reasonably close, and certainly close enough for a lot of purposes.)

citruslee commented 9 years ago

While I agree, that deferred multisampling antialias is neraly impossible with builtin multisample anttialias techniques (dunno for opengl but directx has) but you can use AA techniques like nvidia's FXAA or SMAA potentially...fxaa is quite easy to implement, hence nvidia handed out the full source. About transparency, yes it is also a concern, I made transparency with a render queue which is not so optimal, hence it works on just 180 degrees correctly, after that it is a bit tricky. But still you have things that order independent transparency which unfortunately is not so trivial to implement, but definitively works. Also it's possible that uou won't need a full fledged deferred lighting stuff l, maybe you can get well enough with forward+ rendering. I didn't tried it yet, since I went full deferred in my 64k demo engine, so I'd love to see that implemented by you. For the end, I'd like to mention one more "tradeoff" with deferred shading and thatt'll be the memory consumptions. Since you need multiple render targets, for a basic deferred you need albedo, depth and normal buffers, each RGBA 16bit dept. That alone is quite a memory hog, but imagine doing BRDF physically based rendering where you need roughness values, specular, emissive and other targets. So while deferred rendering is BLAZING fast, it uses way too much resource, which you need to pack together by encoding in colors which is quite tedious work.

citruslee commented 9 years ago

Just a random thought, you could theoretically use deferred rendering for faking ambient occlusions with negative light. But ambient occlusion is somewhat natural with MRT deferred shading :)