🔒 Locked
Minimizing Perspective Distortion
Advertisement
Original Post
Hi, For a project I'm working on, I've been trying to hammer out a good way to get 3D models to draw on a 2D backdrop. The natural choice would be to use an orthogonal projection, since I'm using it to do the backdrop anyway, but the models definitely don't look as nice as when I use a perspective projection. The problem I've been having with the perspective projection is that the models become distorted at the screen edges; by that I mean they stretch out vertically near the top of the screen and rotate slightly to the left or right near the sides of the screen. This is due to the projection's effect. Here is some example code I am using to draw at a certain screen x,y: float fScale = 0.19f; glScalef (fScale, fScale, fScale); GLint viewport[4]; GLdouble modelview[16]; GLdouble projection[16]; GLdouble dPosX, dPosY, dPosZ; glGetDoublev(GL_MODELVIEW_MATRIX, modelview); glGetDoublev(GL_PROJECTION_MATRIX, projection); glGetIntegerv(GL_VIEWPORT, viewport); // get the world coordinates of a point on the screen near the far clip plane gluUnProject(fScreenX, fScreenY, 0.99f, modelview, projection, viewport, &dPosX, &dPosY, &dPosZ); glTranslatef ((float)dPosX, (float)dPosY, (float)dPosZ); glRotatef(g_fRotationX, 1.0, 0, 0); glRotatef(g_fRotationY, 0, 1.0, 0); Render3DModel(); Ideally I'd like to have the model always appear as it does at the center of the screen, without any distortion as it moves to the edges. I could do this using orthogonal view and baking some perspective into the model itself, but I would really like to be able to have the flexibility of doing it on the fly if this is possible... I tried messing with the near and far planes and the view angle (which right now is 45 degrees) but nothing I've tried seems to really keep the distortion down. I would greatly appreciate any tips!
Not sure if this will help you, but you might try looking for information on perspective correction.
Maybe this works: Position your object in the center of the camera view ray (your perspective projection). This would result in the model to be drawn in the center of the screen. Now to move this object you would have to move the vertices that result after projection. This should be doable by simply applying a translation AFTER the perspective transformation.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(...)
gluPerspective(...);
You should know that after the projection matrix has been applied the vertices are in NDC or clip space, so the on screen range is from -1 <= x, y, z, <= 1. A translate in x by 0.5 would thus move the object by half of the screen.
Im not 100% sure if that works but it seems plausible.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(...)
gluPerspective(...);
You should know that after the projection matrix has been applied the vertices are in NDC or clip space, so the on screen range is from -1 <= x, y, z, <= 1. A translate in x by 0.5 would thus move the object by half of the screen.
Im not 100% sure if that works but it seems plausible.
Maybe this is gonna work - try it - render separately model and scene into textures, then combine it. Model's texture needs to have alpha channel 1 where model, and zero anywhere else - this is method similar to masking final screen.
Anyway second solution - you could try combining few textures to have not so much perspective disortion, while you have far clipping plane in very high distance.
Anyway second solution - you could try combining few textures to have not so much perspective disortion, while you have far clipping plane in very high distance.
Thanks for the replies.
I'm aware that there will always be distortion, which I want of course, but I guess I should say I want to minimize inconsistent distortion across the screen. At the margins, maybe 10% into the screen, the model becomes warped. At the top this is a vertical expansion, at the bottom a compaction (which doesn't really affect the appearance and is actually kind of nice) and at the sides a rotation.
Like I said in my original post I tried messing with the angle some, but changing the FOV for some reason doesn't seem to make a difference. I tried all the way down to 4 degrees.
Rendering to a texture is an option, I was hoping for an easier way however. I'll be sure to look into your idea Trenki.
At worst case I thought about just adding a vertical scale factor near the top and rotating the models some at the sides of the screen to do a manual correction, but this is definitely a huge hack...
Quote:
Original post by zedz
with perspective projection theres always gonna be perspective distortion (hence the name)
to minimze it u can decrease the FOV eg 10 degrees
I'm aware that there will always be distortion, which I want of course, but I guess I should say I want to minimize inconsistent distortion across the screen. At the margins, maybe 10% into the screen, the model becomes warped. At the top this is a vertical expansion, at the bottom a compaction (which doesn't really affect the appearance and is actually kind of nice) and at the sides a rotation.
Like I said in my original post I tried messing with the angle some, but changing the FOV for some reason doesn't seem to make a difference. I tried all the way down to 4 degrees.
Rendering to a texture is an option, I was hoping for an easier way however. I'll be sure to look into your idea Trenki.
At worst case I thought about just adding a vertical scale factor near the top and rotating the models some at the sides of the screen to do a manual correction, but this is definitely a huge hack...
Just choose the correct FOV: 2*atan((height/2) / eye-to-screen-distance). (Height for FOV in Y direction, width for FOV in X.)
If you aren't actually interested in correcting persepective distortion, but rather in correcting perspective mismatch with a backdrop, you'll probably be happiest with a parallel projection that isn't an orthogonal projection. Or did you think that perspective and orthogonal were your only choices?
If you aren't actually interested in correcting persepective distortion, but rather in correcting perspective mismatch with a backdrop, you'll probably be happiest with a parallel projection that isn't an orthogonal projection. Or did you think that perspective and orthogonal were your only choices?
Quote:
Original post by Sneftel
Or did you think that perspective and orthogonal were your only choices?
That would be correct ;) Google tells me that it is basically ortho mode with the projection occurring at an angle to the view plane, correct?
This doesn't seem to be a very popular mode judging by the amount of useful info I turned up on it. I have no idea how I would set up the projection matrix to do this.
Wikipedia provides a fairly good taxonomy. You'll likely be interested in a Cavalier perspective. As for setting up the projection matrix, you'll have to do it by hand; there's some stuff about it on the wiki page, but the easiest thing would probably just be to start with the equation for an orthogonal projection and modify it. You're basically just adding a little Z into the X and Y axes.
There is a stock GL function (maybe GLu?) that allows you to pan and zoom around the viewport, this should do what you want but I can't think of the name.
It just dawned on me what that "mysterious" function was... glFrustum. Hiding in plain sight.
So for example, glFrustum(-2,0,-1,1,1,100) will pan 1 (half) a screen to the left. This leaves the center of perspective half a screen to the right.
glFrustum(left, right, bottom, top, Znear, Zfar)So for example, glFrustum(-2,0,-1,1,1,100) will pan 1 (half) a screen to the left. This leaves the center of perspective half a screen to the right.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement