View Full Version : Pixel perfect projection matrix

Phippu

07-01-2010, 04:53 AM

Hi,

currently I have two different projection modes, orthogonal and perspectivic. The orthogonal matrix is pixel perfect, I.E if I have a Quad that has a dimension of 100x100 and it is not transformed, the rendered size of that quad will be 100x100 as well. Now I want that the perspective matrix is pixel perfect too (I need it for a 3D UI), how can I do this? Scaling seems not to be the right way :o

float ymax = _near * (float)Math.Tan(fovy * Pi180);

float ymin = -ymax;

float xmin = ymin * aspectRatio;

float xmax = ymax * aspectRatio;

Gl.Frustumf(xmin, xmax, ymin, ymax, near, far);

Gl.Orthof(Width / -2.0f, Width / 2.0f, Height / -2.0f, Height / 2.0f, near, far);

Dark Photon

07-01-2010, 06:19 AM

Now I want that the perspective matrix is pixel perfect too...

Please clarify what you mean by this.

Phippu

07-01-2010, 06:52 AM

Ok, I'll try to explain:-) Here's an image of the perspectivc projection I want:

http://www.philippewechsler.ch/Images/stuff/perspective.jpg

Now the special thing I need. Imagine the green quad has the size 100 x 100. The red quad should represent the screen and splits the projection in two parts, the near and the far part. The target is the follwing: I want to define all models in pixel dimensions. If the model is exactly in the red plane, it should be rendered 1:1 to the screen. The projection I'm looking for is nothing else than a mix between a orthogonal and a perspective matrix. Its strange to explain, to you know what I mean?

Phippu

07-01-2010, 09:24 AM

I got it;-)

near = 1;

far = 1000;

focal = 500;

float ymax = Height/2.0f * near / focal;

float ymin = -ymax;

float xmin = ymin * aspectRatio;

float xmax = ymax * aspectRatio;

Gl.Frustumf(xmin, xmax, ymin, ymax, near, far);

An here's what that matrix is doing:

its a normal perspective projection, but near,far and focal are measured in pixels. When the distance from the point to the camera is 500 (focal), then the point will be rendered 1:1 to the screen. A plane that is 100 x 100 and is 500 away from the camera, the plane will be rendered exactly 100 x 100 pixels.

Thanks for your help anyway;-)

loicm

07-01-2010, 04:57 PM

Here's the function I use to build that kind of matrix. width and height defines the 2D space available at z=0, must be the same as the size of the viewport. z_near defines the z position of the near plane, must be greater than 0. z_far defines the z position of the far plane, must be lesser than 0. z_eye defines the position of the viewer, must be greater that z_near. All the vertices placed at z=0 will now perfectly map with the pixel grid of your screen.

void MatrixPerspectivePixelPerfect(Matrix* m, float width, float height,

float z_eye, float z_near, float z_far) {

const float kdn = z_eye - z_near;

const float kdf = z_eye - z_far;

const float ksz = - (kdf + kdn) / (kdf - kdn);

const float ktz = - (2.0f * kdn * kdf) / (kdf - kdn);

VectorSet(&m->v0, (2.0f * z_eye) / width, 0.0f, 0.0f, 0.0f);

VectorSet(&m->v1, 0.0f, (2.0f * z_eye) / height, 0.0f, 0.0f);

VectorSet(&m->v2, 0.0f, 0.0f, ktz - ksz * z_eye, -1.0f);

VectorSet(&m->v3, 0.0f, 0.0f, ksz, z_eye);

}

Note that you'll need to transpose the matrix before sending it to OpenGL.

Powered by vBulletin® Version 4.2.3 Copyright © 2017 vBulletin Solutions, Inc. All rights reserved.