bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
34.31k stars 3.35k forks source link

Support perspective projections with shear #12488

Open viridia opened 4 months ago

viridia commented 4 months ago

What problem does this solve or what need does it fill?

The ability to create a camera with a sheared projection matrix is important for a number of use cases:

What solution would you like?

The setViewOffset() API in three.js is fairly simple. It accepts six parameters:

All this does is adjust the perspective projection, and the corresponding view frustum, to render a rectangular subregion of the normal frustum. This is not the same as a clip rect, the subregion is "spread" over the entire viewport rect.

While it's possible that this feature already exists, I could not find it. I would expect that if it did exist, it would be a property of either Camera, Camera3DBundle, or ProjectionMatrix, but I could find nothing in those types relevant to this.

What alternative(s) have you considered?

I can't think of a workaround for this, other than rendering to a very large render target and then cutting out a small piece of it, which would destroy performance.

viridia commented 4 months ago

My motivation for wanting this, BTW, is that I am currently working on portals. Here's a screenshot showing my work in progress:

portal-quad

The red rectangle gizmo shows the bounding box of the portal quad, which is the green gizmo. I already have in place code to render a secondary camera to an offscreen buffer; however, that secondary camera is rendering the entire screen, when ideally it should only render a tiny section of the screen. This will require modifying both the perspective transform and the frustum of the secondary camera.

For portals, specifically, there's an additional requirement that I didn't mention, which is that the near plane of the frustum needs to be adjusted to align with the portal aperture, so that objects that are in front of the portal (that is, between the secondary camera and the target viewpoint) do not get included in the view. In my old three.js code, I used a auxiliary clipping plane for this, but Bevy doesn't have that feature.

inodentry commented 3 months ago

I would like to add another use case that could benefit from this: screen shake in 3D.

If you want to shake the camera in 2D, you can just translate the camera along x/y, it's simple.

But in 3D, there are many different ways to accomplish screen shake, which look different, and it can be an artistic choice which way to implement the effect: