cgmath icon indicating copy to clipboard operation
cgmath copied to clipboard

Support for the Vulkan coordinate system

Open dthul opened this issue 7 years ago • 14 comments

cgmath uses OpenGL's coordinate system conventions for the projection matrices. This means that the projection matrices generated by cgmath need to be modified (see: the new Vulkan coordinate system) when one wants to use them with Vulkan. glm seems to handle this issue by having different functions for left-handed and right-handed coordinate systems as well as [-1, 1] and [0, 1] depth ranges (see: glm commit aa383). Might this be a valuable addition to cgmath as well?

dthul avatar Feb 27 '18 09:02 dthul

Interesting! I'm guessing this is something Amethyst has to handle as well. Not sure how they work around different coordinate systems and column-major/vs row major options 🤔

brendanzab avatar Feb 27 '18 10:02 brendanzab

Do you know if DirectX and Metal have different coordinate systems as well?

brendanzab avatar Feb 27 '18 10:02 brendanzab

Not entirely sure how the coordinates are defined for those systems. I only saw the the Windows Matrix class for DirectX has methods to generate left as well as right handed projection matrices.

dthul avatar Feb 27 '18 12:02 dthul

I took a little while to read up on this, hopefully I got it all correct (the documentation for this stuff is scattered at best)

  • Direct3D uses a left-handed coordinate system with a depth range of [0, 1]
  • Metal uses a left-handed coordinate system with a depth range of [0, 1]
  • OpenGL uses a left-handed coordinate system with a depth range of [-1, 1], but it can be set to [0,1] with ARB_clip_control, which is core in OpenGL 4.5
  • Vulkan uses a right-handed coordinate system with a depth range of [0,1], but it can be made left-handed by using a negative viewport scale with VK_KHR_maintenance1, which is core in Vulkan 1.1

Given that both Vulkan and OpenGL have well-documented ways of working around their weird behaviors, I'd propose that cgmath should use the DirectX/Metal convention, and document that Vulkan and OpenGL users should use the appropriate APIs to make their environments more "normal". This is going to break* every existing OpenGL user once, but it's consistent long-term and it allows keeping from/into impls around Perspective and Matrix types. It also means that cgmath would be usable as-is in all the modern APIs, rather than being held back by OpenGL compatibility.

* It might actually just waste half of their depth buffer precision but otherwise appear correct?

branan avatar Apr 11 '18 02:04 branan

Sorry for the late reply. Yeah, that could be a decent approach. It would be important to get feedback on that change, and it would definitely require a minor version bump (still pre-1.0 😩)

brendanzab avatar Apr 21 '18 12:04 brendanzab

If we're going to change the API for this, I feel like cgmath should still have functions to convert to OpenGL's default coordinate space. Honestly, I'd rather scrap the from/into implementations all together in favor of explicitly named functions, as IMO implementing those traits implies that there's a single, "correct" way to do the conversion - something that isn't true here.

Osspial avatar Apr 22 '18 00:04 Osspial

I also think that the right way to go here is to add explicit functions for different coordinate systems, just like how GLM does it, e.g. perspective_fov_lh_zo, perspective_fov_rh_zo, perspective_fov_lh_no, perspective_fov_rh_no. I'm not sure why the from/into implementations exist in the first place.

If we can agree on the approach I'm sure someone could put together a PR in no time.

ghost avatar Jan 01 '19 14:01 ghost

Looks like #350 is related. There's also some confusion regarding the look_at function, i.e., #448 and #390.

ghost avatar Jan 01 '19 14:01 ghost

[1, 0] depth is also fairly common in modern games as well.

MaikKlein avatar Jan 01 '19 15:01 MaikKlein

Do these projection functions have to be separate functions? Other transformations like rotation and look_at is inside Matrix4. I think it would make sense to put them to the same place.

kocsis1david avatar Jan 13 '19 19:01 kocsis1david

This hit me recently as well, as we started using cgmath for the examples in wgpu-rs: https://github.com/gfx-rs/wgpu/pull/52 I think agree with @Osspial and @aleksijuvani about just having dedicated methods for perspective in different coordinate systems, instead of From/Into.

kvark avatar Feb 04 '19 18:02 kvark

why not just a second parameter, which specifies the convention (either a range, to cover all cases, or just a bool to switch between -1..1 and 0..1). Then in order to switch between right handed and left handed a transpose should be sufficient, I assume. But there could also be another parameter (bool or enum) to specifiy, if it's left handed or right handed.

porky11 avatar Feb 24 '19 07:02 porky11

@porky11 Second parameter would be fine by me as well.

Then in order to switch between right handed and left handed a transpose should be sufficient

I don't think transpose would do. You need to multiply a row by -1 to get from left to right.

kvark avatar Feb 25 '19 14:02 kvark

I don't think transpose would do. You need to multiply a row by -1 to get from left to right.

That's why I mentioned the alternative of using a third parameter.

porky11 avatar Feb 26 '19 11:02 porky11