Drawing an off-center object with Matrix.CreateLookAt with Pi / 4 without the skewed appearance

Started by
12 comments, last by L. Spiro 5 years, 10 months ago

To explain the title, consider these two captures. The first one is a sphere that is centered at (0, 0, 0) which is the target of the Matrix.CreateLookAt with target being (0, 0, 0). In the second, the same sphere was moved to the side (Vector3.Right * some factor). The sphere is now somewhat skewed and oval-looking. This is due to the properties of perspective field of view.

I wish to render the sphere to the side as in the second capture, but with the same perspective as in first. One thing I tried is to change the field of view to a smaller, near orthographic, value. This solves the problem but creates other problems, where other objects are now subject to what is effectively a near-orthographic view. Another option is to capture the sphere into a render target and draw it separately. The problem with this is that the sphere will no longer be in 3D space. Furthermore, unnecessary GPU resources will be committed just for this, impacting performance.

Any other ideas on how I can achieve this?

1.PNG

2.PNG

Advertisement

It isn't really possible, mathematically, to have both the properties of perspective you want (things farther away are smaller) without the properties of perspective you don't (objects close to the focal point and off to the side are noticeably distorted). At least not when you've got actual 3D space involved.

You could:

  1. Render each object individually with the camera looking directly at it and composite these elements into a flat, orthographic scene, and hack the size change due to distance by scaling each relative to its 'distance' from the camera. Kind of like billboards. You can still use the GPU to depth sort them, but you'd be manipulating the depth manually.
  2. Skew the perspective matrix such that the screenspace (x,y) of the focal point is always aligned to the screenspace (x,y) position of the sphere. You will have to manually manipulate the matrices, and they have to be homogenous. It will also cause disorienting shifts in objects behind and in front of the sphere as the sphere moves.

I'm curious, why do you want to do this? I think your eye does the same thing to some extent so it's actually less realistic.

On 6/5/2018 at 9:50 AM, Gnollrunner said:

I'm curious, why do you want to do this? I think your eye does the same thing to some extent so it's actually less realistic.

Your eyes do not distort images that are off-to-the-side this way.  This happens because the spherical space around your head and in your field of view in real life is being projected onto a flat plane in the renderer.  This adds distortion that was not previously present, very obviously (since it is literally distorting a spheroid space into a flat pyramid).

In reality, if the sphere had moved to the side, it would only seem as if it had changed distances from you (it moved farther away by moving to one side) and retain its spherical shape.  You can verify this by simply turning in place to look at the new sphere.  Nothing about the sphere will change from your perspective except that it moves to the center of your vision.
In non-ray-traced computer graphics (and in most ray-traced scenes), the sphere, as projected for rendering, will retain its distance from you as it moves left and right.  Note that in the physical world of the game (inside the CPU simulation), a vector from the moved sphere to your head will match reality (it will give you a larger distance as the sphere moves to the side, exactly matching reality)—this issue is related to the projection.

Because of the projection, the sphere will cover the exact same range of depth values as it moves across the screen (check the depth buffer).  That means the near and far points of the circle have the same range of Z values as it moves left and right.  This is not consistent with reality and causes the stretching you see.

 

 

In reality, you see the world this way:
shutterstock_192524684.jpg

You just don’t notice because your field of view is limited to such a small range that you don’t notice that straight lines curve away from you, but whether you notice it or not it is physically and mathematically impossible for this not to be the case, no matter how small your field is.

But as mentioned, this is not an issue.  There is nothing here to be fixed.  This is completely expected behavior for games, which do not gather photons from a perfectly simulated game world.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

26 minutes ago, L. Spiro said:

Your eyes do not distort images that are off-to-the-side this way.

Now that I think about it more, I think you are right because the receptors on the back of your eye are roughly on the inside of a sphere. However I would think there should be some way to compensate for it by mapping pixels in the same way.

Ray tracers can handle it correctly if each ray is cast spherically out from an eye (or any infinitely small point), modeling reality (except of course that photons go into the eye, not out of it (well, some do, but they do not aide in your vision)).  These are usually reserved just for movies, since ray tracing is slow in the first place, but extra slow the more accurately you model reality.

Pyramid projections are the standard because they are fast, and they will not be going away from real-time media any time soon.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Be interesting to try it though. Maybe you could simply map the (x,y) coordinates of the pixels. by their angle from the center line in the X and Y directions.  I'm not sure you need ray-tracing for this. I may try when I get some extra time since I'm working on DirectX shaders at the moment.

gpu intensive but... increase distance param in engine somehow so you're looking at objects from further away and then only show the mid 80% of screen but w/zoom to take up your whole screen. the off-angle distortion would be  greatly reduced and perhaps feel more organic? 
Lol... i work w/2d stuff primarily so tend to have a lot of cpu cycles to spare.... probably not the case in your game.

I think  maybe you can just take x/z and y/z, round them to the appropriate level, and then plug those into an arctan table.

Thanks for the replies. @L. Spiro, to address your point of "...this is not an issue.  There is nothing here to be fixed."... correct, there's nothing wrong here. I just need a specific object to be render in this manner due to the nature of the game I am working.

With that said, I think the only two solutions that I can consider is point 1. that @Zorinthrox suggested, or to capture it into a render target.

This topic is closed to new replies.

Advertisement