This is an old revision of the document!


Laboratoire 02

OpenGL – Données

Si nous essayions de réduire l’ensemble de l’API OpenGL à de grands concepts, ils seraient:

  • données
  • états
  • shaders

Shaders shader sera présenté pendant le cours.
Les états représentent un concept plus large, OpenGL étant en fait un grand automate fini avec beaucoup d'états et de possibilités de passer d'un état à un autre. Dans tous les laboratoires, certains de ces états seront utilisés pour obtenir les effets souhaités.
Les données contiennent les informations qui définissent la scène, ainsi que:

  • objets en trois dimensions
  • propriétés matérielles des objets (plastique, verre, etc.)
  • les positions, orientations et dimensions des objets dans la scène
  • toute autre information nécessaire décrivant les propriétés de l'objet ou de la scène

Par exemple, pour une scène carrée unique, nous avons les données suivantes:

  • les sommets du carré - 4 vecteurs tridimensionnels définissant la position de chaque pic dans l'espace
  • les caractéristiques des sommets
    • si la seule caractéristique d'une pointe en dehors de la position serait la couleur, nous aurions 4 autres vecteurs tridimensionnels (RVB)
  • la topologie du carré, c'est-à-dire la manière dont nous connectons ces sommets

OpenGL est une API graphique en trois dimensions, c'est-à-dire que tous les objets pouvant être définis sont liés à un système de coordonnées cartésiennes en trois dimensions. Cependant, nous pouvons utiliser l'API pour afficher des objets en deux dimensions, même s'ils sont définis par des coordonnées (x, y, z), en plaçant toutes les données dans un seul plan et en utilisant une projection appropriée.
En laboratoire, nous utiliserons la coordonnée Z = 0. Ainsi, tout point tridimensionnel deviendra P (x, y, 0).

Topologie

La primitive de base dans OpenGL est le triangle. Ainsi, comme on peut le voir dans l'image ci-dessus, dessiner un objet doit être spécifié par des triangles.

Le cube décrit ci-dessus est spécifié par la liste des 8 coordonnées de sommets et une liste de 12 triangles décrivant la manière dont les sommets spécifiés dans la liste précédente doivent être joints pour former les faces du cube. En utilisant des sommets et des index, nous pouvons décrire discrètement tout objet en trois dimensions.

Vous trouverez ci-dessous les principales primitives supportées par le standard OpenGL 3.3+.

Comme on peut le constater, il existe plusieurs méthodes permettant de spécifier la géométrie:

  • GL_LINES et GL_TRIANGLES sont les primitives les plus couramment utilisées pour définir la géométrie
  • GL_POINTS il est souvent utilisé pour créer des systèmes de particules
  • Les autres modèles ne représentent que des optimisations des 3 primitives de base, tant du point de vue de la mémoire que de la facilité à spécifier certaines topologies, mais leur utilité est souvent limitée car les objets les plus complexes ne peuvent être spécifiés qu'en utilisant de simples primitives.

Dans le cadre, vous pouvez définir le type de primitive utilisé par un objet à restituer via la fonction. Mesh::SetDrawMode(GLenum primitive)primitive peut être n'importe lequel des primitifs mentionnés dans l'image ci-dessus.

L'ordre de la spécification des sommets

Une observation importante liée à la topologie est l’ordre des sommets dans une primitive solide (pas une ligne, pas un point) avec plus de 2 sommets. Cet ordre peut être horaire ou antihoraire.

Face Culling

L'API OpenGL offre la possibilité de tester l'orientation apparente de chaque triangle à l'écran avant sa lecture et de l'ignorer en fonction du statut de suppression défini.: GL_FRONTGL_BACK. Cette fonctionnalité s'appelle Face Culling et est très important car cela réduit le coût total de traitement.

Exemple: pour un cube 3 faces au maximum peuvent être visibles à tout moment sur les 6 existantes. Dans ce cas, un maximum de 6 triangles seront traités pour être affichés à l'écran au lieu de 12.

Normalement, la sélection du visage est désactivée. Il peut être activé en utilisant la commande glEnable:

glEnable(GL_CULL_FACE);

Pour désactiver la sélection face-à-face, utilisez la commande glDisable:

glDisable(GL_CULL_FACE);

Pour spécifier l'orientation des faces à ignorer, utilisez la commande glCullFace

// GL_FRONT, GL_BACK, and GL_FRONT_AND_BACK are accepted.
// The initial value is GL_BACK.
glCullFace(GL_BACK);

Maillage

Un „maillage” est un objet en trois dimensions défini par des points et des indices. Au laboratoire, vous pouvez télécharger des maillages dans presque tous les formats possibles en classe. Mesh.

Vertex Buffer Object (VBO)

Un vertex buffer object (objet tampon de sommet) représente un conteneur dans lequel nous stockons des données liées au contenu des astuces, telles que:

  • position
  • normal
  • couleur
  • coordonnées de texture
  • etc…

Un vertex buffer object peut être créé à l'aide de la commande OpenGL glGenBuffers:

	GLuint VBO_ID;			// L'ID (nom ou référence) du tampon qui sera requis du GPU
	glGenBuffers(1, &VBO_ID);	// l'identifiant de tampon (nom) est généré

Comme vous pouvez le voir dans l'explication de l'API, la fonction glGenBuffers reçoit le nombre de tampons à générer et l'emplacement en mémoire où les références générées (ID) seront sauvegardées.
Dans l'exemple ci-dessus, un seul tampon est généré et l'ID est enregistré dans la variable VBO_ID.

Pour détruire un VBO et libérer ainsi la mémoire du GPU utiliser la commande glDeleteBuffers:

glDeleteBuffers(1, &VBO_ID);

Pour pouvoir mettre les données dans un tampon, nous devons d’abord lier ce tampon à un „target”. Pour un vertex buffer this „binding point” ça s'appelle GL_ARRAY_BUFFER et peut être spécifié par la commande glBindBuffer:

glBindBuffer(GL_ARRAY_BUFFER, VBO_ID);

À ce stade, nous pouvons télécharger des données de la mémoire du CPU au GPU à travers la commande glBufferData:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
  • La commande lit à partir de l'adresse spécifiée, dans l'exemple ci-dessus étant l'adresse du premier sommet &vertices[0], et copier dans la mémoire vidéo la taille spécifiée par le paramètre 2.
  • GL_STATIC_DRAW représente un indice pour le pilote vidéo sur l'utilisation du tampon. Ce symbole peut avoir plusieurs valeurs, mais dans le laboratoire il suffit pour la spécification présentée. Plus d'informations peuvent être trouvées sur la page de manuel de fonction glBufferData

Pour mieux comprendre l'API OpenGL, nous vous recommandons de lire la documentation fournie avec chaque commande soumise. Quand une nouvelle commande est soumise, si vous cliquez sur son nom, vous serez redirigé vers la page de manuel de cette commande.
En outre, la documentation officielle et complète de l’API OpenGL est disponible sur la page OpenGL 4 Reference Pages

Index Buffer Object (IBO)

Un index buffer object (objet tampon d’index) est un conteneur dans lequel nous stockons des sommets. Comme VBO si IBO sont des tampons, ils sont extrêmement similaires dans leur construction, leur chargement et leur suppression.

glGenBuffers(1, &IBO_ID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO_ID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), &indices[0], GL_STATIC_DRAW);

Comme avec VBO, nous créons un IBO et le lions ensuite à un point de connexion, mais cette fois, le point de connexion est GL_ELEMENT_ARRAY_BUFFER. Les données sont envoyées au tampon mappé à ce point de liaison. Dans le cas des index, tous auront la taille d'un seul entier.

Vertex Array Object (VAO)

Dans un vertex array object (objet tableau de sommets) nous pouvons stocker toutes les informations relatives à l'état de la géométrie dessinée. Nous pouvons utiliser un grand nombre de tampons pour stocker chacun des différents attributs („separate buffers”). Nous pouvons stocker plusieurs attributs (ou tous) dans un seul tampon („interleaved” buffers). Normalement, avant chaque commande de dessin, toutes les commandes “de liaison” pour les tampons ou les attributs décrivant les données à restituer doivent être spécifiées. Pour simplifier cette opération, on utilise un objet tableau de sommets prenant en compte tous ces liens.

Un objet tableau de sommets est créé à l'aide de la commande glGenVertexArrays:

unsigned int VAO;
glGenVertexArrays(1, &VAO);

Il est lié à glBindVertexArray:

glBindVertexArray(VAO);

Avant de créer les VBO et l'IBO requis pour un objet, le VAO de l'objet sera lié et il se souviendra automatiquement de tous les liens spécifiés ultérieurement.

Une fois tous les liens spécifiés, il est recommandé de commander glBindVertexArray(0) désactiver le lien avec le VAO actuel, car sinon, nous risquons que d'autres commandes OpenGL ultérieures soient liées au même VAO, ce qui facilitera grandement les erreurs dans le programme.

Avant la commande de dessin, il suffit de lier uniquement le VAO pour qu'OpenGL connaisse toutes les liaisons créées lors de la construction de l'objet.

Laborator 2

Descriere laborator

În cadrul laboratorului vom învăța să folosim VAO, VBO, IBO și astfel să generăm și încărcăm geometrie simplă.
Laboratorul pune la dispoziție structura VertexFormat ce va fi utilizată ca bază pentru a crea geometria.

struct VertexFormat
{
	// position of the vertex
	glm::vec3 position;		
 
	// vertex normal
	glm::vec3 normal;
 
	// vertex texture coordinate
	glm::uvec2 text_coord;
 
	// vertex color
	glm::vec3 color;
};

Clasa Mesh pune la dispoziție posibilitatea de a încărca geometrie simplă folosind diverse metode:

// Initializes the mesh object using a VAO GPU buffer that contains the specified number of indices
bool InitFromBuffer(unsigned int VAO, unsigned short nrIndices);
 
// Initializes the mesh object and upload data to GPU using the provided data buffers
bool InitFromData(std::vector<VertexFormat> vertices,
		std::vector<unsigned short>& indices);
 
// Initializes the mesh object and upload data to GPU using the provided data buffers
bool InitFromData(std::vector<glm::vec3>& positions,
		std::vector<glm::vec3>& normals,
		std::vector<unsigned short>& indices);

Taste de control pentru cameră

  • W, A, S, D, Q, E - deplasare față, stânga, spate, dreapta, jos, sus
  • MOUSE RIGHT + MOUSE MOVE - rotație cameră

F3 - afișează/ascunde gridul din scenă
Space - desenează primitivele doar prin puncte sau linii (wireframe) sau geometrie opacă

Cerințe laborator

Toate cerințele ce țin de încărcare de geometrie trebuie rezolvate prin intermediul funcției Laborator2::CreateMesh dar puteți folosi metodele Mesh::InitFromData() pentru a verifica validitatea geometriei.

  1. Completați geometria și topologia unui cub: vectorii de vertecși și indecși din inițializare. VertexFormat este o structură pentru vertex cu 2 parametrii (poziție, culoare).
  2. Completați funcția Laborator2::CreateMesh astfel încât să încărcați geometria pe GPU
    • creați un VAO
    • creați un VBO și adăugați date în el
    • creați un IBO și adăugați date în el
    • afișați noul obiect (RenderMesh[cube3]) astfel încât să nu se suprapună cu un alt obiect
  3. Creați o nouă formă geometrică simplă, de exemplu un tetraedru și desenați-l în scenă
  4. Atunci când se apasă tasta F2 faceți toggle între modul de culling GL_BACK și GL_FRONT
    • nu uitați să activați și să dezactivați face culling folosind glEnable() / glDisable()
  5. Creați un pătrat format din 2 triunghiuri astfel încât fiecare triunghi să fie vizibil doar dintr-o parte
    • în orice moment de timp nu trebuie să se vadă decât 1 triunghi
egc/laboratoare/fr/02.1570632146.txt.gz · Last modified: 2019/10/09 17:42 by alexandru.gradinaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0