Commençons par les bases.
Habituellement, vous voulez transformer vos sommets de triangle locaux à travers les étapes suivantes:
local-space coords-> world-space coords -> view-space coords -> clip-space coords
Dans GL standard, les 2 premières transformations sont faites par GL_MODELVIEW_MATRIX
, le 3 se fait par GL_PROJECTION_MATRIX
Ces transformations de vue de modèle, pour les nombreuses transformations intéressantes que nous voulons habituellement appliquer (par exemple, traduire, mettre à l'échelle et faire pivoter, par exemple), peuvent être exprimées en multiplication vecteur-matrice lorsque nous représentons homogeneous coordinates. Typiquement, le sommet V = (x, y, z)
est représenté dans ce système par (x, y, z, 1)
.
Ok. Dites que nous voulons transformer un sommet V_local en une translation, puis une rotation, puis une traduction. Chaque transformée peut être représentée comme une matrice *, appelons-les T1, R1, T2. Nous voulons appliquer la transformation à chaque sommet: V_view = V_local * T1 * R1 * T2
.La multiplication matricielle étant associative, on peut calculer une fois pour toutes M = T1 * R1 * T2
. De cette façon, il suffit de transmettre M au programme vertex et de calculer V_view = V_local * M
. À la fin, un vertex shader typique multiplie la position du vertex par une seule matrice. Tout le travail pour calculer cette matrice est comment vous déplacez votre objet de l'espace local à l'espace du clip.
Ok ... J'ai jeté un coup d'œil sur un certain nombre de détails importants. Premièrement, ce que j'ai décrit jusqu'ici ne couvre réellement que la transformation que nous voulons habituellement faire jusqu'à l'espace de la vue, pas l'espace du clip. Cependant, le matériel s'attend à ce que la position de sortie du vertex shader soit représentée dans cet espace-clip spécial. Il est difficile d'expliquer les coordonnées de l'espace-clip sans maths significatives, donc je vais le laisser de côté, mais le bit important est que la transformation qui amène les sommets à cet espace-clip peut généralement être exprimée comme le même type de multiplication matricielle. C'est ce que le vieux gluPerspective, GlFrustum et GlOrtho calculent. Deuxièmement, c'est ce que vous appliquez aux positions de vertex. Le calcul pour transformer les normales est quelque peu différent. C'est parce que vous voulez que la normale reste perpendiculaire à la surface après la transformation (à titre de référence, elle nécessite une multiplication par la transposition inverse de la vue-modèle dans le cas général, mais peut être simplifiée dans de nombreux cas)
Troisièmement, vous n'envoyez jamais de coordonnées 4-D au vertex shader. En général, vous passez les 3-D. OpenGL va transformer ces coordonnées 3D (ou 2-D, btw) en coordonnées 4-D de sorte que le vertex shader n'a pas besoin d'ajouter la coordonnée supplémentaire. il étend chaque sommet pour ajouter le 1 en tant que coordonnée w
. Donc, pour reconstituer tout ça, pour chaque objet, vous devez calculer ces M matrices magiques en fonction de toutes les transformations que vous voulez appliquer à l'objet. A l'intérieur du shader, vous devez ensuite multiplier chaque position de sommet par cette matrice et la transmettre au vertex shader. Code typique est plus ou moins (ce qui utilise ancienne nomenclature):
mat4 MVP;
gl_Position=MVP * gl_Vertex;
* les matrices réelles se trouvent sur le web, notamment sur les pages de manuel pour chacune de ces fonctions: rotate, translate, scale, perspective , ortho
Merci pour cette réponse très thorogh! Un détail que j'avais manqué était que vous pouvez changer la matrice MVP (par exemple en la déclarant uniforme) entre les appels à glDrawElements ... Étrange déplacer de khronos pour laisser la spécification de ces matrices très communes au programmeur cependant. J'espère qu'ils trouveront leur chemin dans glu ou similaire bientôt ... – Wonko
C'est ce que le middleware est pour. GL3.2 est moins expressif pour le codage rapide. Mais les versions précédentes étaient le mauvais niveau d'abstraction pour une application réelle de toute façon. Il a fallu un cadre de gestion d'état en plus de celui-ci. Aussi, disons que vous voulez garder des matrices. Cela signifie que le pilote doit conserver toutes les piles matricielles, comment les transmettre uniquement à tous les shaders qui en ont besoin (pas seulement le vertex), déterminer quelle est la saveur dont vous avez besoin - M, MV, MVP, IT (MV), IT (M). La pire partie ? l'application est la seule qui peut rendre les calculs efficaces, en exécutant de nombreuses opérations matricielles à la fois. GL ne peut pas le faire efficacement. – Bahbar