Skip to content
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

Perspective transforms for Canvas2D #5620

Open
Tracked by #5613
fserb opened this issue Jun 8, 2020 · 11 comments
Open
Tracked by #5613

Perspective transforms for Canvas2D #5620

fserb opened this issue Jun 8, 2020 · 11 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: canvas

Comments

@fserb
Copy link
Contributor

fserb commented Jun 8, 2020

Allow for perspective (non-affine) 2D transforms. Non-affine transforms are
transformations where parallel lines don't remain parallel after the transform.

Working proposal: https://github.com/fserb/canvas2D/blob/master/spec/perspective-transforms.md

(cc @whatwg/canvas )

@fserb fserb mentioned this issue Jun 8, 2020
9 tasks
@annevk annevk added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: canvas labels Jun 9, 2020
@litherum
Copy link

litherum commented Jun 9, 2020

This would be extremely difficult to implement in WebKit's architecture. Core Graphics doesn't have any facility for 3d operations. Trying to split a canvas into a Core Animation layer hierarchy would be a world of pain.

If authors want this effect, they can transform multiple canvas elements using CSS 3D transforms. Or, use WebGL.

The benefit doesn't seem worth the cost.

@kdashg
Copy link

kdashg commented Jun 9, 2020

Isn't this just a helper function for explicit setTransform?

@fserb
Copy link
Contributor Author

fserb commented Jun 16, 2020

@jdashg, not really. The proposal here would be to allow also non-affine transforms (like CSS does). Canvas2D already has rotate/scale/translate. This would add a optional 3rd dimension to some of those, to allow perspective transformations.

@kdashg
Copy link

kdashg commented Jun 16, 2020

Ah, it's pretty subtle that setTransform runs only the 2d dictionary constructor for DOMMatrix, which is otherwise 3d-capable by spec.

@fserb
Copy link
Contributor Author

fserb commented Feb 11, 2021

Exactly. The proposal here is to match the CSS capabilities inside Canvas and just support the full DOMMatrix.

@dbaron
Copy link
Member

dbaron commented Apr 22, 2021

A few comments after looking over the proposal quickly:

  • The rotate3d method proposed here (taking 3 angles) is different from the CSS rotate3d() function (which takes 3 components of a vector and a single angle). This seems like a surprising difference. It also requires specifying how the angles compound with each other when more than one of them are nonzero, and whatever rules you come up with for that might end up being surprising in some cases. Whereas your proposed rotateAxis() is equivalent to CSS's rotate3d(). I'd argue in favor of naming consistency, and I'm also concerned about the 3-angle form being confusing.

  • if you're using 4x4 matrices, something needs to specify the handling of the w in the result, as CSS Transforms does in § 4.2. Processing of Perspective-Transformed Boxes.

@mysteryDate
Copy link
Contributor

Whereas your proposed rotateAxis() is equivalent to CSS's rotate3d(). I'd argue in favor of naming consistency, and I'm also concerned about the 3-angle form being confusing.

The thinking here was that it would be more valuable to match popular and well established 3d APIs like three.js, unreal and Unity as opposed to CSS in this instance. rotateAxis is definitely more useful than the rotate3d Euler rotations, but the most requested use cases are things like card flipping and text crawls. In lieu of adding three separate rotateX, rotateY, rotateZ functions, we decided to go with just one. Euler angles always get surprising when pushed to their limits, this feels like a limitation of most 3d platforms.

@tabatkins
Copy link
Contributor

I feel pretty strongly that, even if established 3d APIs have a different 3d rotation primitive, we shouldn't use the existing CSS name for that new primitive and put the CSS function under a different name. Learnability and consistency generally leans strongly on letting the CSS function use its native name, and giving the new/better thing a different name; exceptions would only be if, say, the existing CSS functionality is just straight-up a mistake that shouldn't be repeated.

@tabatkins
Copy link
Contributor

Fwiw, then, I think you should just add the three rotateX/Y/Z functions, since they're already in CSS Transforms, and if 3d libraries usually have a 3-angle version that takes all three and composes them in a particular order, then add that additionally as rotateAngle or something.

@mysteryDate
Copy link
Contributor

Fwiw, then, I think you should just add the three rotateX/Y/Z functions, since they're already in CSS Transforms, and if 3d libraries usually have a 3-angle version that takes all three and composes them in a particular order, then add that additionally as rotateAngle or something.

This seems fair to me, if I remember correctly (big if) that was my original approach. Composing Euler angles is tricky and surprising and I'm generally for discouraging it. So, how does consensus feel about the rotation api being:

  • rotateX, rotateY, rotateZ
  • rotateAxis (supply x, y, z axis and rotation around that axis)

This lets us avoid the whole rotate3d naming thing entirely.

@jrmuizel
Copy link

FWIW, cairo (WebKitGTK) doesn't support perspective transforms either.

L1Z3 added a commit to L1Z3/Pyret-3D-Game that referenced this issue Dec 17, 2021
The code here does not and cannot work as I intended it to. I am committing it just so I can keep it in the record in case I need something from it later. 

This code takes the four points of some image, like a texture to be mapped, as well as four output points, like where a face is to be rendered, and calculates a transformation matrix that takes the input four points and maps them to the output points.

Then it implements a new Pyret image type that I thought would allow for arbitrary matrix transformations. It turns out Canvas2D currently only allows for 2D affine transformations, which means given a square input its output can be at most a parallelogram--it can not produce the distortions needed for it to render arbitrary faces in 3-space. The behavior to allow for this properly seems to be in the works, whatwg/html#5620, but for now I will need to use a hack or some entirely different method for texture mapping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: canvas
Development

No branches or pull requests

8 participants