Scene render order - #5708
Conversation
|
/benchmark 20 |
|
There is definitely a use to allow scenes to merge with each other, in the case where you are translating a scene in order to apply that effect to all plots within it. I think we had a robot arm example which did something like that. |
|
The scene merging thing only affects z order and not as much as I thought. Iirc, I originally had each scene complete a full render (with postprocessor), and then stacked the resulting images on top of each other. That would make z ordering per scene and could break stuff where a covering scene translates plots to be under the covered scenes content. The code I have here/locally doesn't do that. It still renders all plots together, which means OpenGL's depth testing applies and you still get ordering across scenes from that. What changes is only when the render calls are made (across scenes), which may mess with the AA of scatter, text and lines. (I.e. a scatter markers AA may blend with a scatter marker that should be on top rather than the background) WGLMakie has been rendering scenes independently already. CairoMakie is tricky again, because it entirely relies on plot sorting for z order. So it either needs grouping or we need to adjust the few cases where it causes issues (see test failures) |
|
/benchmark 20 |
|
/benchmark 20 |
Benchmark ResultsSHA: 57ac2571608f439cbb07573d8c0d947984836b96 · 20 samples Warning These results are subject to substantial noise because GitHub's CI runs on shared machines that are not ideally suited for benchmarking. |
|
/benchmark 20 |
Benchmark ResultsSHA: cc7c164f7be766aa426488e4605d19738a53753a · 20 samples Warning These results are subject to substantial noise because GitHub's CI runs on shared machines that are not ideally suited for benchmarking. |
… clear (simplify inset Axis to not need translate!)
|
I changed Axis a bit to rely on clear instead of a background poly if the backgroundcolor is opaque. This makes it unnecessary to translate inset scene but causes grid lines to disappear under transparent plots. Probably because of per-scene plot rendering |
|
Before I forget what's on my mind about this pr: First, I'm not sure about Second I'm still all over the place when it comes to plot draw/render order (and depth order). CairoMakie doesn't have depth testing, so draw order must be back to front. W/GLMakie are more nuanced. Fully opaque plots would optimally render front to back (or do front to back depth prepass). Or it might be better to group them by plot type and scene to reuse uniforms and reduce shader program switches. Transparent plots (including natively anti-aliased plots like scatter) should render later, in back to front order. Isolating scenes with respect to draw order (as I currently have) is also questionable. Only There is also the problem that draw order is currently based on model translations, which is completely wrong in 3D. A better approach would be calculating the real depth from the plots bounding box. For plots where the bounding box spans a range of depth values (i.e. 3D) the layering can still be wrong with this. So I think there should also be an overwrite, but I'm not sure how that would integrate with defaults (which have to be calculated down the line, i.e. they're not super easy to view) and backend specific ordering (e.g. how do we combine this with opaque-transparent ordering?) Third, I'm also not 100% convinced we should require child scenes to be within their parent scenes viewport. It's already mentioned in the architecture docs on master and would make some coverage analysis easier, but it's not actually required/used anywhere yet, afaik. Though the opposite is not required or used either. Enforcing it seems hard to me, since we'd have to compare parent and child viewports whenever they update if we want to be thorough. That might introduce more synchronization headaches. |
|
To track some discussions I had with Simon:
|
Description
This is a new attempt at #4150. If this gets merged it will also include changes from #4724 and changes for WGLMakie.
Fixes #5292
Related: #4904, #4650
Problems/Differences
Each backend handles scenes a little bit different. Using the example that is also added as a test (same as #4724):
Calling
display(scene)after creating all scenes and plots will cause the full scene tree to be added. This includes scenes without plots. Scenes render in a depth first order (i.e. with arender(scene); render.(scene.children)recursion). Only WGLMakie treats plots under a cleared scene as covered.The same
save(filename, scene)command is creating different image sizes for me here... Is this a bug on breaking? master? Expected?Calling
display(scene)immediately after creating the root scene, i.e. adding scenes and plots interactively causes backends to diverge more.CairoMakie behaves the same as before, as it evaluates the scene tree whenever it creates an image. There is no interactive adding of scenes here.
GLMakie and WGLMakie do not interactively add scenes. Instead they add them once a plot is added to them. This means some scenes maybe missing from the render, and some may be in the wrong order.
Emptying a scene does not (interactively) remove child scenes from the backend screen. This currently happens when scenes are GC'd, which never happens if the scene is hold on to as a variable in the global scope. The test has variables for every scene, so calling
empty!(scene)after displaying will leave behind scenes. (This again doesn't matter to CairoMakie as it reevaluates the scene tree on draw.) Emptying the first example yields:Related issues: #5292
After this pr
Early display (second example)
After empty (third)
Goals and other things to consider
Rules:
translate!(scene, ...))clear = trueerases everything that is drawn behind itWith these rules we can naturally define groups of scenes that start with a cleared scene (back) and stop just before another cleared scene would be added (front). These groups fully define what is drawn on top of the cleared scene (if not occluded by another clear). This means that we don't need plot sorting (draw order) or depth buffering (rendering) beyond these groups.
I'm still unsure if we should restrict this further and make draw order and/or depth per scene. Per scene depth would require the render pipeline to partially run per scene, which seems unnecessarily difficult to me. Per scene draw order would simplify backend code (don't need to find and manage groups) but may occasionally complicate front end code. (If a back scene draws a scatter/text/lines plot and the front scene draws something else behind that, the back scene plot would need to be moved to the front scene (or a scene in front of it) to correctly blend its AA. Currently you can translate to fix this.)
Menu
Menu is a rather complicated example since it has a dropdown scene that should draw over other scenes regardless of when it is created. Currently this sort of works via
translate!(scene, 0, 0, high_z), but that can cause z-fighting issues, e.g. #5292. With working clear (2), a scene that is added after the menu can also erase the dropdown content.To fix this we need a way to keep the menu dropdown on top. This is why I want to add a z-index to scenes. Instead of having the dropdown scene as a child of
blockscene, it would need to be a child ofblockscene.parentwith a high z-index so it remains in front of other scenes in the parent. Usually the parent is the figure, meaning that the dropdown would draw on top of all other blocks. But we could also add floating windows/subfigures in the future to which the Menu would naturally be constrained. And if we don't want this constraint (for Menu or another block) we could seek the root scene and directly add to that instead.TODO
GLMakie: re-group scenes when clear updatessimplify to not GLScene instead of scene groupstransformationin text specs to:nothing(or directly include model transformations there)Changes
Makie:
blockscene.parentBoxsceneCairoMakie:
WGLMakie:
insert_scene!toScene(parent, ....)creation in Makiedelete!for scenesGLMakie:
GLSceneas a wrapper aroundSceneand the associated renderobjectsRenderContextas a manager object for scenes and renderobjects (replacing renderlist, screens, scene2screen in Screen)GLScenes in back-to-front order for renderingcopy_to_screen(screen, framebuffer)function for easier compat with other window librariesType of change
Delete options that do not apply:
Checklist