La matrice de projection décrit la correspondance entre les points 3D d'une scène et les points 2D de la fenêtre. Il se transforme de l'espace des yeux en espace de clip, et les coordonnées dans l'espace du clip sont transformées en coordonnées de périphérique normalisées (NDC) en divisant par le composant w
des coordonnées du clip. Les NDC sont compris entre (-1, -1, -1) et (1,1,1).
Lors de la projection en perspective, la matrice de projection décrit le mappage de points 3D dans le monde tels qu'ils sont vus depuis une caméra sténopé, vers des points 2D de la fenêtre.
Les coordonnées de l'espace des yeux dans le tronc de la caméra (une pyramide tronquée) sont mappées sur un cube (les coordonnées normalisées de l'appareil).
Perspective Projection Matrix:
r = right, l = left, b = bottom, t = top, n = near, f = far
2*n/(r-l) 0 0 0
0 2*n/(t-b) 0 0
(r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
0 0 -2*f*n/(f-n) 0
où:
aspect = w/h
tanFov = tan(fov_y * 0.5);
prjMat[0][0] = 2*n/(r-l) = 1.0/(tanFov * aspect)
prjMat[1][1] = 2*n/(t-b) = 1.0/tanFov
Je suppose que la matrice de vue est la matrice d'identité, et donc les coordonnées de l'espace d'affichage sont égales aux coordonnées du monde.
Si vous voulez dessiner un polygone, où les coordonnées du vertex sont traduites 1: 1 en pixels, vous devez dessiner le polygone dans le plan parallèle à la fenêtre. Cela signifie que tous les points doivent être dessinés avec la même profondeur.
La profondeur doit choisir de cette façon, que la transformation d'un point en coordonnées normalisées de l'appareil, par la matrice de projection inverse donne les coordonnées du vertex en pixel. Notez, les coordonnées homogènes données par la transformation avec la matrice de projection inverse, doivent être divisées par la composante w
des coordonnées homogènes, pour obtenir des coordonnées cartésiennes.
Cela signifie que la profondeur du plan dépend du champ de l'angle de vue de la projection:
En supposant que vous configurez une projection comme en perspective ceci:
float vp_w = .... // width of the viewport in pixel
float vp_h = .... // height of the viewport in pixel
float fov_y = ..... // field of view angle (y axis) of the view port in degrees < 180°
gluPerspective(fov_y, vp_w/vp_h, 1.0, vp_h*2.0f);
Puis le depthZ
du plan avec une relation 1: 1 de coordonnées des sommets et des pixels, est calculé comme suit:
float angRad = fov_y * PI/180.0;
float depthZ = -vp_h/(2.0 * tan(angRad/2.0));
note, le point central de la saillie de l'orifice de vue est (0,0), de sorte que le point d'angle inférieur gauche de l'avion est (-vp_w/2
, -vp_h/2
, depthZ
) et le point d'angle supérieur droit est (vp_w/2
, vp_h/2
, depthZ
). Assurez-vous que le plan proche de la perspective perspective est inférieur à -depthZ
et que le plan lointain est supérieur à -depthZ
.
Voir plus:
Les deux exigences sont par nature impossible à réaliser les deux en même temps, parce que la perspective de transformer implique une étape de division qui peut entraîner non -les coordonnées de l'intégrateur. Le mieux que vous pouvez espérer est d'avoir un "plan z" où les coordonnées du vertex traduisent 1: 1 en pixels, mais devant ou derrière ce plan, vous aurez toujours des non-entiers. – Thomas
Quel serait le meilleur moyen d'atteindre ce "z-plane"? Je pense que c'est exactement ce que je veux. – Met
La valeur 'z' pour ce" plan de pixels "dépendra du champ de vision de votre projection. Il est facile à trouver avec une géométrie de triangle simple. – derhass