Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
smfr opened this issue Jan 13, 2017 · 12 comments
Open

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

smfr opened this issue Jan 13, 2017 · 12 comments

Comments

@smfr
Copy link
Contributor

smfr commented Jan 13, 2017

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.

@smfr smfr changed the title Define how exactly to apply perspective (w-parameter) [css-transforms-2] Define how exactly to apply perspective (w-parameter) Jan 13, 2017
@fred-wang
Copy link

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

@fred-wang
Copy link

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.

@faceless2
Copy link

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

@dbaron
Copy link
Member

dbaron commented Jun 15, 2022

@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?

@faceless2
Copy link

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...

@Nax
Copy link

Nax commented Mar 4, 2023

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.

@dbaron
Copy link
Member

dbaron commented Mar 4, 2023

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

@Nax
Copy link

Nax commented Mar 4, 2023

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.

@dbaron
Copy link
Member

dbaron commented Mar 5, 2023

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

@Nax
Copy link

Nax commented Mar 5, 2023

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.

@dbaron
Copy link
Member

dbaron commented Mar 6, 2023

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.

@tabatkins
Copy link
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
Projects
None yet
Development

No branches or pull requests

6 participants