FUSEEProjectTeam / Fusee

Fusee aims at becoming a multiplatform 3D realtime engine with a strong emphasis on content transformation and manipulation. Fusee is written mainly in C# and can be programmed in C#. Fusee builds bridges to make your code run in environments that don't support C#, like Content-Creation-Software, C++, Plug-In-APIs and native HTML5/WebGL Javascript code.
https://fusee3d.org
MIT License
90 stars 36 forks source link

Transparency in complex scenes #212

Open RedImp1470 opened 4 years ago

RedImp1470 commented 4 years ago

See #257

The following refers to the Deferred Example. After I did some alteration in the lighting calculation we can render transparent textures, but....

When rendering the scene forward, we can see two kinds of issues with meshes that have a partially transparent albedo texture:

  1. Transparent parts have the color of the Clear Color

image

  1. Transparent parts are too transparent - for example we can see through the pillar in the picture below

image

When debugging the draw calls in RenderDoc, we can see that meshes like the one in picture 1 are drawn before any other meshes behind them. Debugging the example in the second picture reveals the following draw order:

  1. Ground
  2. Tendrils
  3. Pillar

Expected result, where the order of the meshes in the scene graph coincidentally matched the correct drawing order:

image

Therefore I think we should implement a way to sort transparent meshes before we render them to avoid this behavior.

With Deferred Rendering comes an additional issue where the lighting is not applied correctly for the transparent parts.

image

griestopf commented 4 years ago

... a well known issue in 3D rendering. Transparency requires some kind of sorting. There are varying levels of complexity. Simpler approaches have more cases where transparency remains incorrect. More complex approaches have less incorrect behavior, but require more calculation.

🡅 Simple

🡇 Complex

RedImp1470 commented 4 years ago

Personally I'd try a BSP solution (becaus we may be able to also implement occlusion culling with this at the same time). In any case I think this will require some conceptional work. E. g. on how to not destroy the scene graph for the user and manage/share states.

CoffeeParser commented 4 years ago

This might help. I've implemented a general purpose Renderqueue based on this approach last year.

http://realtimecollisiondetection.net/blog/?p=86

The approach is called replay queue and works very well even for complex scenes with multi Pass shading, renderlayers and post processing.

Steps:

  1. Traverse scene and collect renderable data to a flat list. Renderable data is used as input for rendercontext commands (buffer handles, shader handles, input layout handles, etc)
  2. Sort renderable data and add commands via Action (Command Pattern). Sorting can be done via one key or with multiple keys by type.
  3. Run commands in loop on rendercontext

Tips: Avoid linq or fat object allocation in tight loops because triggers GC and slows down the rendering.

Exploit cache efficiency as much as possible: https://github.com/dbartolini/data-oriented-design