Question

À partir de ce site: http://www.toymaker.info/Games/html /vertex_shaders.html

Nous avons l'extrait de code suivant:

// transformations provided by the app, constant Uniform data
float4x4 matWorldViewProj: WORLDVIEWPROJECTION;

// the format of our vertex data
struct VS_OUTPUT
{
  float4 Pos  : POSITION;
};

// Simple Vertex Shader - carry out transformation
VS_OUTPUT VS(float4 Pos  : POSITION)
{
  VS_OUTPUT Out = (VS_OUTPUT)0;
  Out.Pos = mul(Pos,matWorldViewProj);
  return Out;
}

Ma question est la suivante: pourquoi la structure VS_OUTPUT a-t-elle un vecteur à 4 dimensions comme position? La position n’est-elle pas juste x, y et z?

Était-ce utile?

La solution

Parce que vous avez besoin de la coordonnée w pour le calcul de la perspective. Une fois que vous avez sorti du vertex shader, DirectX effectue une division de la perspective en divisant par w.

Essentiellement, si vous avez 32768, -32768, 32768, 65536 comme position de sommet de sortie, puis après la division w, vous obtenez 0,5, -0,5, 0,5, 1. À ce stade, le w peut être ignoré car il n’est plus nécessaire. Cette information est ensuite transmise à travers la matrice de la fenêtre de visualisation qui la transforme en coordonnées 2D utilisables.

Éditer: si vous regardez comment une matrice est multipliée à l'aide de la matrice de projection, vous pouvez voir comment les valeurs sont placées aux bons endroits.

Prise de la matrice de projection spécifiée dans D3DXMatrixPerspectiveLH

2*zn/w  0       0              0
0       2*zn/h  0              0
0       0       zf/(zf-zn)     1
0       0       zn*zf/(zn-zf)  0

Et en l'appliquant à une valeur aléatoire x, y, z, 1 (la note pour une position de sommet w sera toujours 1), valeur d'entrée de sommet que vous obtenez ce qui suit

x' = ((2*zn/w) * x) + (0 * y) + (0 * z) + (0 * w)
y' = (0 * x) + ((2*zn/h) * y) + (0 * z) + (0 * w)
z' = (0 * x) + (0 * y) + ((zf/(zf-zn)) * z) + ((zn*zf/(zn-zf)) * w)
w' = (0 * x) + (0 * y) + (1 * z) + (0 * w)

Instantanément, vous pouvez voir que w et z sont différents. La coordonnée w ne contient plus que la coordonnée z transmise à la matrice de projection. z contient quelque chose de beaucoup plus compliqué.

Alors ... supposons que nous avons une position d'entrée de (2, 1, 5, 1), nous avons un zn (Z-Near) de 1 et un zf (Z-Far de 10) et aw (largeur) de 1 et ah (hauteur) de 1.

En passant ces valeurs, nous obtenons

x' = (((2 * 1)/1) * 2
y' = (((2 * 1)/1) * 1
z' = ((10/(10-1)  * 5 + ((10 * 1/(1-10)) * 1)
w' = 5

en expansion que nous obtenons alors

x' = 4
y' = 2
z' = 4.4
w' = 5

Nous effectuons ensuite une division finale de la perspective et nous obtenons

x'' = 0.8
y'' = 0.4
z'' = 0.88
w'' = 1

Et nous avons maintenant notre position de coordonnées finale. Cela suppose que x et y sont compris entre -1 et 1 et z entre 0 et 1. Comme vous pouvez le constater, le sommet est affiché à l'écran.

Comme bonus bizarre, vous pouvez voir que si | x '| ou | y '| ou | z '| est plus grand que | w '| ou z 'est inférieur à 0 que le sommet est hors écran. Cette information est utilisée pour couper le triangle à l'écran.

Quoi qu’il en soit, je pense que c’est une réponse assez complète: D

Edit2: Soyez averti que j'utilise les matrices principales ROW. Les matrices majeures des colonnes sont transposées.

Autres conseils

La rotation est spécifiée par une matrice tridimensionnelle et la traduction par un vecteur. Vous pouvez effectuer les deux transformations dans un " single " opération en les combinant dans une seule matrice 4 x 3:

rx1 rx2 rx3 tx1
ry1 ry2 ry3 ty1
rz1 rz2 rz3 tz1

Toutefois, comme ce n’est pas une case carrée, diverses opérations ne peuvent pas être effectuées (inversion pour une seule). En ajoutant une ligne supplémentaire (qui ne fait rien):

0   0   0   1

toutes ces opérations deviennent possibles (si ce n’est pas facile).

Comme l'explique Goz dans sa réponse en faisant le "& 1;" " une valeur non identitaire la matrice devient une transformation de perspective.

Le découpage est une partie importante de ce processus, car il permet de visualiser ce qu'il advient de la géométrie. La phase de découpage supprime essentiellement tout point d’une primitive située en dehors d’un cube à 2 unités centré autour de l’origine (vous devez reconstruire les primitives partiellement découpées mais cela n’a aucune importance ici).

Il serait possible de construire une matrice qui mapperait directement les coordonnées de votre espace mondial à un tel cube, mais un mouvement progressif du plan lointain au plan proche serait linéaire. C’est-à-dire qu’un mouvement d’un pied (vers le spectateur) à un mille du spectateur entraînerait une augmentation de taille identique à celle d’un mouvement d’un pied à plusieurs pieds de la caméra.

Cependant, si nous avons une autre coordonnée dans notre vecteur (w), nous pouvons diviser le vecteur par composante, et nos primitives ne présenteront pas le comportement ci-dessus, mais nous pourrons néanmoins les faire se retrouver dans la 2 -unit cube ci-dessus.

Pour plus d'explications, voir http://www.opengl.org /resources/faq/technical/depthbuffer.htm#0060 et http: // en .wikipedia.org / wiki / Transformation_matrix # Perspective_projection .

Une réponse simple serait de dire que si vous ne dites pas au pipeline ce que w est, vous ne lui avez pas donné suffisamment d’informations sur votre projection. Ceci peut être vérifié directement sans comprendre ce que le pipeline en fait ...

Comme vous le savez probablement, la matrice 4x4 peut être divisée en parties en fonction de ce que fait chaque partie. La matrice 3x3 en haut à gauche est modifiée lorsque vous effectuez des opérations de rotation ou d’échelle. La quatrième colonne est modifiée lorsque vous effectuez une traduction. Si vous inspectez une matrice de perspective, elle modifie la ligne inférieure de la matrice. Si vous examinez ensuite comment une multiplication Matrice-Vecteur est effectuée, vous constatez que la ligne du bas de la matrice affecte UNIQUEMENT le composant w résultant du vecteur. Donc, si vous ne dites pas au pipeline que w n’aura pas toutes vos informations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top