cgmath
cgmath copied to clipboard
Support for the Vulkan coordinate system
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?
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 🤔
Do you know if DirectX and Metal have different coordinate systems as well?
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.
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?
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 😩)
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.
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.
Looks like #350 is related. There's also some confusion regarding the look_at function, i.e., #448 and #390.
[1, 0] depth is also fairly common in modern games as well.
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.
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.
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 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.
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.