[Bug 23014] New: Backface-visibility cannot be tested by only looking at m33

https://www.w3.org/Bugs/Public/show_bug.cgi?id=23014

            Bug ID: 23014
           Summary: Backface-visibility cannot be tested by only looking
                    at m33
    Classification: Unclassified
           Product: CSS
           Version: unspecified
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Transforms
          Assignee: smfr@me.com
          Reporter: shawnsingh@chromium.org
        QA Contact: public-css-bugzilla@w3.org
                CC: ayg@aryeh.name, cmarrin@apple.com, dino@apple.com,
                    dschulze@adobe.com, eoconnor@apple.com, smfr@me.com

Created attachment 1386
  --> https://www.w3.org/Bugs/Public/attachment.cgi?id=1386&action=edit
Example of a transform that needs to account for perspective for correct
backface-visibility.

According to the current spec, backface-visibility must be checked by testing
whether the m33 element of the matrix is positive or negative. But the problem
is that this only works without a perspective component.

Actually, it seems like this is already acknowledged since the spec says
"before accounting for perspective". However, backface-visibility will often
need to be tested on matrices that have perspective in them:
  - by definition of the "accumulated 3d transformation matrix" the perspective
will be included in that matrix
  - a user may use the matrix3d() transform function in their CSS to specify
arbitrary perspective on an element, even if it is not in a 3d rendering
context.

I attached an example page with a layer rotated just more than 90 degrees.  In
this configuration, the layer's backface would be visible if there is an
orthographic projection.  Under perspective projection, if set up correctly,
the layer's front side is actually visible.

The accumulated 3d transformation matrix of that example is:

[ +1.0574 +0.0000 +2.4037 +88.5277
  +1.2310 +1.0000 +0.4341 +53.7981
  -0.4924 +0.0000 -0.1736 +98.4808
  +0.0025 +0.0000 +0.0009 +0.5076 ]

The m33 element is negative, but because of perspective, we should interpret
that the front side of the layer is facing the camera.

Instead of checking m33, there are at least two ways to correctly implement
backface visibility:

(1) Inspect vertices of the element being drawn for clockwise /
counter-clockwise, similar to how game engines often perform backface culling

(2) Rigorously apply the transform the z normal, and check the transformed
normal is still facing the camera (i.e. it's z value is positive or negative). 
However, we cannot just apply the transform to the z normal by doing a basic
matrix*vector operation --> that is why checking m33 only is not correct. 
Instead, mathematically if we want to transform a surface normal, we must do
inverseTranspose(matrix) * normalVector.

Knowing that the normalVector is (0, 0, 1, 0), we don't have to compute a heavy
full inverse, and the implementation can remain mostly lightweight.  You can
see chrome's implementation here:
 
https://code.google.com/p/chromium/codesearch#chromium/src/ui/gfx/transform.cc&q=gfx::Transform::IsBackFaceVisible&sq=package:chromium&type=cs&l=219

I have not tested how the attached example works in IE.  Firefox, Safari, and
Chrome seem to get backface visibility correct on the attached example page --
which implies that no browser is checking for (m33 < 0) anyway.

So, would it work just to change the spec to be mathematically correct and to
reflect what browsers already implement?

-- 
You are receiving this mail because:
You are the QA Contact for the bug.

Received on Monday, 19 August 2013 22:00:56 UTC