W3C home > Mailing lists > Public > public-fx@w3.org > July to September 2016

Re: [css-transforms] CSS3D breaks with opacity flattening

From: Matt Woodrow <mwoodrow@mozilla.com>
Date: Thu, 22 Sep 2016 22:50:06 +1200
To: Tien-Ren Chen <trchen@chromium.org>
Cc: "Tab Atkins Jr." <jackalmage@gmail.com>, Rik Cabanier <cabanier@gmail.com>, /#!/JoePea <trusktr@gmail.com>, Chris Harrelson <chrishtr@google.com>, Simon Fraser <simon.fraser@apple.com>, "public-fx@w3.org" <public-fx@w3.org>
Message-ID: <28cb0542-c4ce-7b48-31fb-5f92ed84e30a@mozilla.com>

On 22/09/16 7:44 PM, Tien-Ren Chen wrote:
> In Chromium's new rendering model we internally see flattening as a
> combo of two operations:
> A. Modify the accumulated matrix so that the depth of inner 3D context
> will be propagated to screen space intact.
> B. A grouping property that performs depth sorting on planes collected
> so far, and output as an atomic group (i.e. child stacking context).
> The depth component of the output will be applied using the current
> accumulated matrix.
>
> Let me try to rephrase your approach, basically you want
> transform-style:preserve-3d + opacity to perform just operation B but
> not operation A. For example:
>
> <style> div { transform-style: preserve-3d; } </style>
> <div style="perspective:1000px;">
>    <div style="transform:rotateX(-20deg);">
>      <div style="opacity:0.7; background:rgba(255,0,0,0.7);
> transform:rotateY(45deg);" >
>        <div style="background:rgba(0,255,0,0.7);
> transform:rotateY(-90deg);"></div>
>      </div>
>      <div style="background:rgba(0,0,255,0.7);
> transform:translateZ(30px);"></div>
>    </div>
> </div>
>
> Should render equivalent to:
>
> <style> div { transform-style: preserve-3d; } </style>
> <div style="perspective:1000px;">
>    <div style="transform:rotateX(-20deg);">
>      <div style="transform-style:flat; opacity: 0.7;
> transform:rotateY(45deg)matrix3d(1.4142131, 0.36397033, 0.0,
> -0.0010641774, 0.0, 1.0641773, 0.0, -0.00036396993, 0.0, 0.0, 1.0,
> 0.0, 0.0, 0.0, 0.0, 1.0);">
>        <div style="transform:perspective(1000px)rotateX(-20deg);">
>          <div class="grid" style="background:rgba(255,0,0,0.7);
> transform:rotateY(45deg);" >
>            <div class="grid" style="background:rgba(0,255,0,0.7);
> transform:rotateY(-90deg);"></div>
>          </div>
>        </div>
>      </div>
>      <div class="grid" style="background:rgba(0,0,255,0.7);
> transform:translateZ(30px);"></div>
>    </div>
> </div>
>
> Where the matrix3d(...) just undo the 2D part of the accumulated
> matrix. i.e. matrix3d(...) =
> flatten(perspective(1000px)rotateX(-20deg)rotateY(45deg))^-1
> So that preserve-3d + opacity will propagate the accumulated matrix to
> its descendants, and its descendants will perform depth sorting with
> total matrix. The result will be projected back to the plane that has
> the opacity property.

Sort of, but not quite. This method uses the depth of the plane formed 
by the element with opacity as the depth for sorting.

If you consider the case where the opacity plane is behind another piece 
of content, but the children of the opacity are 'in front', then I think 
we want to preserve that.

Here is a simple example where adding/removing the opacity changes the 
ordering, even though it doesn't really need to: 
http://output.jsbin.com/vuquguxeqi/1

Maybe a better way of describing the proposal is that you do your depth 
sorting as if the opacity didn't exist. Then, if the nodes contained 
within the opacity aren't consecutive, move them so that they are (we're 
in undefined behaviour here, as discussed earlier). Finally, do the 
rendering pass over the sorted list, but redirect drawing of planes 
contained within the opacity to a temporary surface and once you've done 
the last of them, draw it to the destination (with an identity 
transform, and the opacity).

For the cases where we don't hit the undefined behaviour bit, then this 
seems very straightforward and gives the 'best' output (in my opinion).

For reference, my example build doesn't deal with sorting as I describe 
here (yet).

> http://jsbin.com/huveseq/ (Note: written in TR spec. Only tested on
> Chrome! See attached PNG for expected rendering.) demonstrates this
> proposal. I think I've seen this approach with a certain vendor in
> some weird corner case. However IMO this definition is not very
> useful... It is hard to understand intuitively, not backward
> compatible, and doesn't solve the use case /#!/JoePea have.
>
Does it not fix the use case? I tried one of his examples and it was 
fixed. Another one didn't render at all, so clearly I still have some 
bugs to fix.

  - Matt
Received on Thursday, 22 September 2016 10:50:41 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:49:57 UTC