New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 714369 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Jun 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Compat



Sign in to add a comment

backface-visibility not rendered as expected, front-face becomes hidden

Reported by trusktr@gmail.com, Apr 22 2017

Issue description

UserAgent: 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).
 

Comment 1 by trusktr@gmail.com, Apr 22 2017

Here's another example, it doesn't look right because the items disappear all of a sudden: 

https://jsfiddle.net/trusktr/ymonmo70/31/
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.
Components: Blink
Labels: -OS-Chrome OS-All

Comment 5 by rtoy@chromium.org, May 24 2017

Components: -Blink Blink>Paint
Status: Untriaged (was: Unconfirmed)
Blink>Paint for further triage
Components: -Blink>Paint Internals>Compositing
Summary: backface-visibility not rendered as expected, front-face becomes hidden (was: [bug] backface-visibility not rendered as expected, front-face becomes hidden)
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.
Owner: danakj@chromium.org
Status: Assigned (was: Untriaged)
danakj@ Can you please assign to the correct owner for this? Thanks!

Comment 8 by danakj@chromium.org, May 26 2017

Cc: danakj@chromium.org
Owner: flackr@chromium.org
flackr, something you can look at?

Comment 9 by danakj@chromium.org, May 26 2017

FWIW this is probably something in the property tree math, I would guess?
Cc: jaydasika@chromium.org petermayo@chromium.org trchen@chromium.org
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.
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.
Cc: flackr@chromium.org
Owner: chrishtr@chromium.org
Coincidentally chrishtr@ is working on this exact issue. Reassigning.
Project Member

Comment 13 by bugdroid1@chromium.org, 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

Status: Fixed (was: Assigned)

Comment 15 by trusktr@gmail.com, 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