Skip to content

[css-transforms-2] Define how exactly to apply perspective (w-parameter) #912

Open

Description

@smfr

Long discussion in https://www.w3.org/Bugs/Public/show_bug.cgi?id=15605 with some completed spec edits. It ended with the need to test UAs to see if they matched the spec'd behavior.

Activity

  1. changed the title [-]Define how exactly to apply perspective (w-parameter)[/-] [+][css-transforms-2] Define how exactly to apply perspective (w-parameter)[/+] on Jan 13, 2017
  2. fred-wang commented on Apr 10, 2020

    @fred-wang
    Contributor

    cc @emilio

    https://drafts.csswg.org/css-transforms-2/#processing-of-perspective-transformed-boxes normalizes homogeneous coordinates to (x′, y′, z′, 1) = (x/w, y/w, z/w, w/w) when w > 0.

    Why do we need a special case for w < 0? https://en.wikipedia.org/wiki/Homogeneous_coordinates says they represent exactly the same point, so not sure what is meant by "behind". Example 8 does not explain why it is "incorrect".

    For a trivial example, the image of (0, 0, 0, 1) by M and -M are respectively (tx, 0, 0, 1) and (-tx, 0, 0, -1) which are the same point in homogeneous coordinates, but the former is rendered and the latter hidden?

    Additionally, this is inconsistent with https://drafts.csswg.org/css-transforms-2/#decomposing-a-3d-matrix which starts by normalizing the transformation matrix, so M and -M are interpolated exactly the same way.

    Here is a basic example where the non-animated "Middle" text with negative w is not rendered by browsers but the animated "w < 0" text is rendered: https://people.igalia.com/fwang/negative-w.html

  3. fred-wang commented on Apr 10, 2020

    @fred-wang
    Contributor

    For a trivial example, the image of (0, 0, 0, 1) by M and -M are respectively (tx, 0, 0, 1) and (-tx, 0, 0, -1) which are the same point in homogeneous coordinates, but the former is rendered and the latter hidden?

    I forgot to say that for any nonzero λ and vector v, (λM)v = λ(Mv) represents the same point as Mv so λM actually represents the same transformation as M. This is why the decomposition algorithm starts by normalizing the matrix. With the current spec, the image (λM)(0, 0, 0, 1) is visible only if λ is positive.

  4. faceless2 commented on Jun 15, 2022

    @faceless2

    We are - perhaps unwisely - attempting to shoehorn in 3D transforms, so I have some feedback on this algorithm.

    I've put about the simplest example I can up at https://jsbin.com/voqiber/, with rubbish MathML showing the matrix expansion (sorry Fred - I can implement it, but I still can't write it) so you'll currently need Safari or Firefox to view.

    Basically:

    • I take a 100x100 rectangle and transform by perspective(100px) rotateY(45deg)
    • I multiply the matrices out so I can see exactly what matrix is being applied.
    • If I then manually multiply the bottom-right point at (100,100), I get a point with a negative Z value

    According to the spec this should be clipped, but it's not - you can see the border all the way around it. Otherwise the point is in the right place: we get the correct shape in our implementation, so I'm fairly confident we've got the maths correct. But I have to ignore the requirement to clip away the negative Z value to render this properly.

    So I'm not quite sure about that "clip points with a negative Z value " instruction in https://drafts.csswg.org/css-transforms-2/#processing-of-perspective-transformed-boxes

  5. dbaron commented on Jun 15, 2022

    @dbaron
    Member

    @faceless2 I'm not sure which text in that section you're looking at, but what it should be saying is that you clip points with a negative w value, not points with a negative z value. (Really, non-positive w value, since w=0 puts things at infinity.) Are you seeing text that mentions z rather than w?

  6. faceless2 commented on Jun 15, 2022

    @faceless2

    Turns out it's not my maths I should worry about, it's my reading. Thank you and sorry for wasting everyone's time. I'm happy to confirm the algorithm seems to work quite well...

  7. Nax commented on Mar 4, 2023

    @Nax

    I agree with @fred-wang, the behavior for w < 0 is extremely surprising and does not really achieve anything.
    It would be both simpler and more coherent to transform, perform perspective correction (divide by w, even if negative) and then clip on the resulting x, y and z.

  8. dbaron commented on Mar 4, 2023

    @dbaron
    Member

    The reason for clipping w < 0 cases is that those are points that should appear "behind" the viewer rather than "in front of" the viewer. If you have a viewer at "perspective: 1000px", I think it makes more sense for a plane at translateZ(2000px) to disappear than it does for that plane to appear as though it was at translateZ(0) but inverted (like scale(-1)).

  9. Nax commented on Mar 4, 2023

    @Nax

    That's typically done by clipping on z after perspective correction (divide by w).

    If w was negative then it will change z's sign, either putting it outside of clip space (the case where the point is "behind the viewer"), or bringing it back inside clip space (the case @fred-wang demonstrated in his example).

    With the way the spec is implemented right now, some points are not displayed while being inside clip space after perspective correction, which is very surprising.

  10. dbaron commented on Mar 5, 2023

    @dbaron
    Member

    Clipping based on what condition regarding z (after the perspective correction)?

  11. Nax commented on Mar 5, 2023

    @Nax

    If I understand how the viewport space works with respect to 3D correctly, it should reject points with negative Z, as these are the points that are "behind" the viewport. In other words, viewport Z would go from zero to infinity.

  12. dbaron commented on Mar 6, 2023

    @dbaron
    Member

    I think in CSS that would be rejecting points with positive Z -- but either way, that would be a breaking change that would break significant amounts of existing content, as currently (with no perspective at all) planes with translate3D(100px) and translate3D(-100px) are both rendered just fine -- those are really just changing z-ordering when perspective and other transforms aren't involved.

  13. tabatkins commented on Mar 6, 2023

    @tabatkins
    Member

    Right. I think that, if we'd considered the 3d model properly before throwing the spec at the web, we probably would have specified the rendering as camera-based, but we can't do that now. (And iiuc, the perspective transform isn't camera-accurate anyway, it just roughly approximates that.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions