2009-10-28 4 views
16

J'ai un peu d'expérience en écriture d'applications OpenGL 2 et je veux apprendre en utilisant OpenGL 3. Pour cela j'ai acheté le "Red-book" et le "Orange-book" Addison Wesley qui décrivent la dépréciation de la fixe fonctionnalité et le nouveau pipeline programmable (shaders). Mais ce que je n'arrive pas à comprendre, c'est comment construire une scène avec plusieurs objets sans utiliser les fonctions déconseillées translate *, rotate * et scale *. Ce que j'avais l'habitude de faire dans OGL2 était de "se déplacer" dans l'espace 3D en utilisant les fonctions de translation et de rotation, et de créer les objets dans les coordonnées locales où je les voulais en utilisant glBegin ... glEnd. En OGL3, ces fonctions sont toutes obsolètes et, si j'ai bien compris, remplacées par des shaders. Mais je ne peux pas appeler un programme de shader pour chaque objet que je fais, n'est-ce pas? Cela n'affecterait-il pas tous les autres objets? Je ne suis pas sûr si j'ai expliqué mon problème satisfaisant, mais le noyau de celui-ci est comment programmer une scène avec plusieurs objets définis dans les coordonnées locales dans OpenGL 3.1. Tous les tutoriels pour débutants que j'ai trouvés n'utilisent qu'un seul objet et n'ont pas/ne résolvent pas ce problème.Comment traduire des objets uniques dans OpenGL 3.x?

Éditer: Imaginez que vous voulez deux cubes en rotation. Ce serait une douleur de modifier manuellement chaque coordonnée vertex, et vous ne pouvez pas simplement modifier la matrice modelview, car cela tournerait plutôt la caméra autour de deux cubes statiques ...

Répondre

20

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

+1

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

+0

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

1

Ces fonctions sont apparemment déconseillées, mais techniquement encore parfaitement fonctionnel et en effet compilera. Vous pouvez donc toujours utiliser les fonctions translate3f (...) etc. Cependant, this tutorial a une bonne explication de la façon dont les nouveaux shaders et ainsi de suite, et pour plusieurs objets dans l'espace.

Vous pouvez créer x tableaux de vertex, et les lier dans des objets x VAO, et vous rendre la scène à partir de là avec des shaders etc ... eh, c'est plus facile pour vous de simplement le lire - c'est vraiment une bonne lecture saisir les nouveaux concepts.

En outre, le livre rouge OpenGL comme il est appelé a une nouvelle version - The Official Guide to Learning OpenGL, Versions 3.0 and 3.1. Il inclut «Discussion sur le mécanisme de dépréciation d'OpenGL et comment vérifier vos programmes pour les futures versions d'OpenGL».

J'espère que ça aide!

+0

Encore une fois merci pour la réponse rapide. J'ai lu le tutoriel que vous mentionnez, mais bien qu'il crée deux triangles, il les crée en coordonnées globales - pas locales comme je le veux. Le problème est lorsque vous avez un modèle plus compliqué, il peut être fastidieux d'utiliser des coordonnées globales, surtout si le modèle se déplace. En outre, je veux charger un objet premade à partir d'un fichier .obj et le placer quelque part dans l'espace 3D. – Wonko

+8

@Mark Le premier lien est cassé. – Jeff

Questions connexes