backface-visibility not rendered as expected, front-face becomes hidden
Reported by
trusktr@gmail.com,
Apr 22 2017
|
||||||||||
Issue descriptionUserAgent: Mozilla/5.0 (X11; CrOS x86_64 9202.64.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.146 Safari/537.36 Example URL: https://jsfiddle.net/g0f31r36/1/ Steps to reproduce the problem: 1. Look at https://jsfiddle.net/g0f31r36/1/ The (matrix3d) on the div has rotation of approximately 89 degrees applied. 2. Look at https://jsfiddle.net/g0f31r36/2/ The (matrix3d) on the div has rotation of approximately 91 degrees applied. 3. In the second example, the div has become invisible despite the fact that the front-face should still be visible based on the perspective of the #container. 4. Try toggling the backface-visibility from hidden to visible on both examples. What is the expected behavior? Both example should look almost exactly the same, except for a small amount of rotation. What went wrong? You notice that the second example's div disappears when it should not. The front-face should become invisible at the angle when the div's plane is parallel with our line of site based on the perspective, not before. If there were no perspective (f.e. "orthographic" or "isomorphic"), then we *would* in fact see the div disappear at an angle of 90, and reappear when it rotates past 270. So it seems as if the div is being made invisible based on the wrong perspective value. Does it occur on multiple sites: N/A Is it a problem with a plugin? No Did this work before? N/A Does this work in other browsers? N/A Chrome version: 57.0.2987.146 Channel: n/a OS Version: 9202.64.0 Flash Version: Shockwave Flash 25.0 r0 Here's another example, using custom elements; it rotates the <motor-node> element slowly, and you can see that it becomes invisible at the wrong time: https://jsfiddle.net/trusktr/ymonmo70/30/ The JS API is just setting CSS transform:matrix3d on the motor-node element, and I made the first two fiddles based on this example (I just copied all the inline styles, once for 89 degrees, and once for 91 degrees).
,
May 18 2017
I believe this is the same issue I’ve encountered. Here is an example: https://codepen.io/keithjgrant/pen/zwmvJP It seems an element with backface visibility is hidden any time it is rotated between 90 and 270 degrees. But, depending on the perspective, this doesn't necessarily mean the backface of the element is facing the viewer.
,
May 23 2017
,
May 23 2017
,
May 24 2017
Blink>Paint for further triage
,
May 25 2017
Absolutely right that the perspective changes the viewer direction w.r.t. the normal of the rotating plane. We appear to have an error in computing that. I think it's in the compositor, so I'll change the component. Feel free to send it back if this is indeed code in Blink.
,
May 26 2017
danakj@ Can you please assign to the correct owner for this? Thanks!
,
May 26 2017
flackr, something you can look at?
,
May 26 2017
FWIW this is probably something in the property tree math, I would guess?
,
Jun 9 2017
The problem seems to be when we set use_local_transform_for_backface_visibility in property_tree_builder.cc SetBackfaceVisibilityTransform https://cs.chromium.org/chromium/src/cc/trees/property_tree_builder.cc?type=cs&q=use_local_transform_for_backface_visibility&l=1100 This thinks that the layer is at the boundary of a 3d rendering context, but afaict it should be in the same rendering context as its parent given the preserve-3d. Then in draw_property_utils.cc IsLayerBackfaceVisible we only look at the local transform given that property, otherwise we'd use the screen space transform as is expected here. I'm now looking into why we have different rendering contexts.
,
Jun 9 2017
I spent a good amount of time researching the transform spec. It is due to we followed (flawed, IMO) transform spec in verbatim. <div id="container"> has overflow:hidden, which forces the used value of transform-style to be flat. Because of that, the stacking context created by <div id="container"> sort its child stacking contexts by z-index order instead of depth sorting. i.e. the composited result of the child stacking context is not participating any 3D context. In the case that the parent stacking context being flat but also has a perspective, the perspective will still be inherited by its children. However, the spec also says for element not in 3D context, face orientation is determined by local matrix: "For an element in a 3D rendering context, compute its accumulated 3D transformation matrix. For an element not in a 3D rendering context, compute its transformation matrix." ---- Below is my personal opinion about the spec: 1. The spec is ill-defined almost entirely. Even the very definition of 3D context is incomplete, and implementation is inconsistent across 4 major engines (Blink, WebKit, Gecko, and Edge). 2. Even the algorithm to determine the screen matrix of an element is broken, due to an issue known as "containing block penetration". Fortunately the "screen projection" (flattened screen matrix, discarding the 3rd col/row that's only meaningful for depth sorting and face orientation) implementation is quite consistent across vendors. That implies most of the time elements will have the same drawing position, but drawing order and face orientation are often inconsistent. 3. backface-visibility is even worse ill-defined. In the spec language it is supposed to be like visibility, which is applied per-element. All implementation treat it as some grouping property, the expand its scope to some stacking context subtree. Again, in very inconsistent ways. Basically the spec is crap. We'd better off just do whatever make sense to us, as long as we don't introduce diffs in screen projection matrix. ¯\_(ツ)_/¯ For this particular issue, I think we should delete code about use_local_transform and only use screen matrices for face orientation instead. i.e. ignore the stupid clause I quoted above. It may introduce some bug in the process, because sometimes we forget to set flatten bits on the transform nodes and rely on render surfaces to implicitly correct it. Those "implicit flatten" can cause screen matrices to be incorrect. Nevertheless I think it's better to clean the mess early than later.
,
Jun 9 2017
Coincidentally chrishtr@ is working on this exact issue. Reassigning.
,
Jun 16 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/daececa45559179618055e7244d5208e2264cdb8 commit daececa45559179618055e7244d5208e2264cdb8 Author: Chris Harrelson <chrishtr@chromium.org> Date: Fri Jun 16 22:09:52 2017 Always use transform to render target for checking backface visiblity. Previously the local transform would sometimes be used if the layer was "at the border of a 3D rendering context". This is unnecessary complexity, and leads to the linked bug. Bug: 714369 Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel Change-Id: I5507d88f0c35bb2dba7e0be99fcd6cdc8fe6f66d Reviewed-on: https://chromium-review.googlesource.com/531646 Reviewed-by: Tien-Ren Chen <trchen@chromium.org> Commit-Queue: Chris harrelson <chrishtr@chromium.org> Cr-Commit-Position: refs/heads/master@{#480192} [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/layers/layer.cc [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/layers/layer.h [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/layers/layer_impl.cc [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/layers/layer_impl.h [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/trees/draw_property_utils.cc [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/trees/layer_tree_host_common_unittest.cc [modify] https://crrev.com/daececa45559179618055e7244d5208e2264cdb8/cc/trees/property_tree_builder.cc
,
Jun 16 2017
,
Jun 16 2017
> I spent a good amount of time researching the transform spec. It is due to we followed (flawed, IMO) transform spec in verbatim. > Basically the spec is crap. We'd better off just do whatever make sense to us, as long as we don't introduce diffs in screen projection matrix. ¯\_(ツ)_/¯ Thank you so much for putting the spec on fire. THANK YOU THANK YOU THANK YOU!!! --- 3D is the future. Other things are leaving CSS 3D in the dust (PBR, VR, AR, etc). I have too much frustration towards CSS 3D. I just deleted like 10 paragraphs while writing this. At this point I am leaving CSS 3D behind, and just learning WebGL. It will be a while before I am back to making user interfaces, but when I'm back it will be with a WebGL implementation that works (for example transparent scene graph objects won't flatten things into paper like CSS 3D does). |
||||||||||
►
Sign in to add a comment |
||||||||||
Comment 1 by trusktr@gmail.com
, Apr 22 2017