Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draw order & (order independent) transparency #702

Open
1 of 2 tasks
Wumpf opened this issue Jan 9, 2023 · 3 comments
Open
1 of 2 tasks

Draw order & (order independent) transparency #702

Wumpf opened this issue Jan 9, 2023 · 3 comments
Labels
🔺 re_renderer affects re_renderer itself user-request This is a pressing issue for one of our users

Comments

@Wumpf
Copy link
Member

Wumpf commented Jan 9, 2023

Current situation

Currently we do not support sorting within a Renderer, instead all renderer have a fixed order.
This is primarily an issue for supporting transparency as transparent objects (with (premultiplied) alpha blending) need to be at least be ordered back to front.
Note that additive blended objects are order independent but still need to be drawn after all opaque objects.

Steps needed

If (!!) we're keeping the current monolithic Render approach, we can split the way to fully supporting transparency in two steps:

  • allowing Render to be invoked several times for different "phases", a prototype is being developed on andreas/re_renderer/phases
  • Sorting within (certain) phases either by..
    • invoking every Renderer an arbitrary amount of time with relatively fine grained draw data
    • implementing an order independent transparency technique

Pro/Con of fine grained object sorting

Sorting rendering primitives by distance to camera is very common in general purpose rendering engines!
However, regardless of the other implications of an order independent transparency algorithm, not sorting within Renderer actually has both advantages and disadvantages:

Drawbacks:

  • no front-to-back order for opaque, meaning potentially lot of (discarded) overdraw
    • fragment shader with discard/depth changes may not profit from ordering
    • this is an issue if pixel shading complexity is high and can be alleviated with a depth-first pass
    • profiling is needed to determine if this actually helps, may be very scene dependent. Some of our key vertex shading is complex (points & lines), making depth-first less attractive
  • no back-to-front order for transparent, meaning rendering artifacts
    until we implement some form of order independent transparency

Advantages:

  • super simple, less data to transfer & compute (don't need to know distances)
    • allows fast path from database to gpu data, close to no data examination needed
  • faster in some cases
  • best possible batching, we invoke every Renderer only once per pass, meaning minimal stage changes without the need for any sorting

Order Independent transparency (OIT)

Employing an OIT technique is partially independent of the question of draw order: As noted above draw order has advantages even with OIT in place but is no longer required then.
Furthermore, depending on our expected scenes draw order alone will not solve alpha blending ordering issues either because our batches are not fine grained enough (i.e. a single draw has several front/back faces in line of sight) or triangles are overlapping (happens often in our case - e.g. line penetrating transparent box).

As our visualizations become more complex it seems to be unavoidable to employ at least one (maybe several for different situations or quality tiers) OIT technique. As this removes the sorting requirement, our database->renderer path could profit from being freed of the sorting limitation which is why making a directional decision here early can inform other design aspects of the renderer!

OIT techniques to evaluate

(WIP, trying to do rough families so far and do some early discarding)

  • ❓ Fragment lists
    • every pixel keeps list of fragments which is later sorted and resolved
    • probably highest quality and most expensive. Comes in many variations
    • Update: Bevy now has a simple version of this which works with a fixed number of layers (rather than linked lists, this may have pros & cons as well!)
  • Weighted, Blended Order-Independent Transparency
    • see also implementation guide
    • use additive blending with depth dependent weights, i.e. faking alpha blending
    • very cheap and surprisingly good results overall, but breaks down when weight heuristic (needs tweaking) fails. Can happens in particular when objects are only very slightly transparent for an example (probably with incorrect weights?) see [this implementation/blog by MJP](https://therealmjp.github.io/posts/weighted-blended-oit/
  • ❓ Stochastic transparency
  • ❓Wavelet/fourier based methods
    • great recent writeup on a haar-wavelet based one here https://osor.io/OIT
    • Fourier Opacity Mapping is an older one I implemented at some point (:
    • typically great memory usage and ok'ish number of draws required (varies over concrete implementations)
    • depending on basis functions typically suffers from different kind of noise/ringing/other artifacts
  • ❌ Depth Peeling
    • fixed amount of depth layers that are rendered one by one
    • rather expensive as geometry need to be rendered multiple times
@Wumpf Wumpf added the 🔺 re_renderer affects re_renderer itself label Jan 9, 2023
Wumpf added a commit that referenced this issue Feb 27, 2023
…dering

Or rather as a first and super easy step towards it. Also takes the first step towards supporting transparency, see #702
Replaces previous sorting key!

Very simple idea: Every `Renderer` is invoked with every `DrawPhase` it registered for.
`DrawPhase` have a strict order and implicitly describe the `wgpu::RenderPass` that is passed for drawing.

For now and forseeable future, these passes are managed by the ViewBuilder (unchanged!).
At some point we will probably make `DrawPhase` a more complex object, but this is not today!
Wumpf added a commit that referenced this issue Feb 27, 2023
…ring (#1419)

Or rather as a first and super easy step towards it. Also takes the first step towards supporting transparency, see #702
Replaces previous sorting key!

Very simple idea: Every `Renderer` is invoked with every `DrawPhase` it registered for.
`DrawPhase` have a strict order and implicitly describe the `wgpu::RenderPass` that is passed for drawing.

For now and forseeable future, these passes are managed by the ViewBuilder (unchanged!).
At some point we will probably make `DrawPhase` a more complex object, but this is not today!
emilk pushed a commit that referenced this issue Mar 2, 2023
…ring (#1419)

Or rather as a first and super easy step towards it. Also takes the first step towards supporting transparency, see #702
Replaces previous sorting key!

Very simple idea: Every `Renderer` is invoked with every `DrawPhase` it registered for.
`DrawPhase` have a strict order and implicitly describe the `wgpu::RenderPass` that is passed for drawing.

For now and forseeable future, these passes are managed by the ViewBuilder (unchanged!).
At some point we will probably make `DrawPhase` a more complex object, but this is not today!
@emilk
Copy link
Member

emilk commented Mar 14, 2023

We should consider doing something simple/stupid as a first step, something that is not order-independent. Just draw transparent objects last, for instance, just to get some of the transparency story done.

emilk added a commit that referenced this issue Jul 15, 2024
### What

Implement an `Ellipsoids` archetype and visualizer. This may be used to
render ellipsoids, or spheres where `Points3D` is unsuitable because the
actual boundary in space is significant. It is intended as a first step
towards completing #1361, by adding ellipsoids and by sketching out a
general mechanism for rendering procedurally-generated shapes, which
will be reusable for cylinders and anything which needs many vertices to
render.

The archetype, extensions, etc. are largely forked off of `Boxes3d`.

Unfinished parts / future work:

* Currently, the spheres are always drawn as wireframes (with an
automatically chosen mesh subdivision level). We will want to also
support solid rendering (i.e. triangles in place of lines), but many use
cases for spheres might want them to be transparent, which isn't yet
properly supported in 3D space views (#702), so I chose wireframe as the
first version.

* Currently, all of the wireframe lines are piped through the
`LineDrawableBuilder` every frame. Instead, they should be drawn as
instanced meshes; that will require implementing a new renderer that
invokes the existing line shader with the different data layout.
However, this current implementation should not be worse than if the
user were to create a similar number of lines directly.

* The sphere mesh needs a choice of subdivision level. Currently, it is
automatically derived from the size of the sphere in the scene, which
may be inappropriate depending on the scale of scene units or the
specific application. I'd like feedback on the best way to handle this.
Just add another component, perhaps kind of like the `Radius` component?

* I‘m not sure what the best way to handle the (future) errors in
generating meshes is. Should it return a `SpaceViewSystemExecutionError`
(which hides unrelated data), just draw nothing and continue (which
could lead to silent missing data), or something else?


![rerun_example_ellipsoid_batch](https://github.com/rerun-io/rerun/assets/779501/5ad90a6e-720d-44b0-883d-e3213777345e)


### Checklist
* [X] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [ ] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6853?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6853?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [X] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!
* [x] If have noted any breaking changes to the log API in
`CHANGELOG.md` and the migration guide

- [PR Build Summary](https://build.rerun.io/pr/6853)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
@Wumpf Wumpf mentioned this issue Aug 15, 2024
@Famok
Copy link

Famok commented Aug 15, 2024

@Wumpf was the opacity implemented? Because the none of the opacity sliders seem to do anything, neither does setting an alpha value in RGBA values seem to have any effect.

@Wumpf
Copy link
Member Author

Wumpf commented Aug 16, 2024

@Famok this ticket is about implementing transparency and its prerequisites in Rerun. We have some very limited support, for example the opacity slider on images which is only really used for layering images on top of each other. If there's a bug with that please do file an issue!

@gavrelina gavrelina added the user-request This is a pressing issue for one of our users label Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔺 re_renderer affects re_renderer itself user-request This is a pressing issue for one of our users
Projects
None yet
Development

No branches or pull requests

4 participants