This is an old revision of the document!
Si nous essayions de réduire l’ensemble de l’API OpenGL à de grands concepts, ils seraient:
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:
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:
primitive
peut être n'importe lequel des primitifs mentionnés dans l'image ci-dessus.
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.
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_FRONT oú GL_BACK. Cette fonctionnalité s'appelle Face Culling et est très important car cela réduit le coût total de traitement.
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);
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.
Un vertex buffer object reprezintă un container în care stocăm date ce țin de conținutul vârfurilor precum:
Un vertex buffer object se poate crea prin comanda OpenGL glGenBuffers:
GLuint VBO_ID; // ID-ul (nume sau referinta) buffer-ului ce va fi cerut de la GPU glGenBuffers(1, &VBO_ID); // se genereaza ID-ul (numele) bufferului
VBO_ID
.
Pentru a distruge un VBO și astfel să eliberăm memoria de pe GPU se folosește comanda glDeleteBuffers:
glDeleteBuffers(1, &VBO_ID);
Pentru a putea pune date într-un buffer trebuie întâi să legăm acest buffer la un „target”. Pentru un vertex buffer acest „binding point” se numește GL_ARRAY_BUFFER și se poate specifica prin comanda glBindBuffer:
glBindBuffer(GL_ARRAY_BUFFER, VBO_ID);
În acest moment putem să facem upload de date din memoria CPU către GPU prin intermediul comenzii glBufferData:
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
&vertices[0]
, și copiază în memoria video dimensiunea specificată prin parametrul al 2-lea.
Un index buffer object (numit și element buffer object) reprezintă un container în care stocăm indicii vertecșilor. Cum VBO si IBO sunt buffere, ele sunt extrem de similare în construcție, încărcare de date și ștergere.
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);
La fel ca la VBO, creăm un IBO și apoi îl legăm la un punct de legatură, doar că de data aceasta punctul de legatură este GL_ELEMENT_ARRAY_BUFFER. Datele sunt trimise către bufferul mapat la acest punct de legatură. În cazul indicilor toți vor fi de dimensiunea unui singur întreg.
Într-un vertex array object putem stoca toată informația legată de starea geometriei desenate. Putem folosi un număr mare de buffere pentru a stoca fiecare din diferitele atribute („separate buffers”). Putem stoca mai multe (sau toate) atribute într-un singur buffer („interleaved” buffers). În mod normal înainte de fiecare comandă de desenare trebuie specificate toate comenzile de „binding” pentru buffere sau atribute ce descriu datele ce doresc a fi randate. Pentru a simplifica această operație se folosește un vertex array object care ține minte toate aceste legături.
Un vertex array object este creat folosind comanda glGenVertexArrays:
unsigned int VAO; glGenVertexArrays(1, &VAO);
Este legat cu glBindVertexArray:
glBindVertexArray(VAO);
După ce toate legăturile au fost specificate este recomandat să se dea comanda glBindVertexArray(0)
pentru a dezactiva legătura către VAO-ul curent, deoarece altfel riscăm ca alte comenzi OpenGL ulterioare să fie legate la același VAO și astfel să introducem foarte ușor erori în program.
Înainte de comanda de desenare este suficient să legăm doar VAO-ul ca OpenGL să știe toate legatările create la construcția obiectului.
Î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);
F3 - afișează/ascunde gridul din scenă
Space - desenează primitivele doar prin puncte sau linii (wireframe) sau geometrie opacă
Laborator2::CreateMesh
dar puteți folosi metodele Mesh::InitFromData()
pentru a verifica validitatea geometriei.
VertexFormat
este o structură pentru vertex cu 2 parametrii (poziție, culoare).Laborator2::CreateMesh
astfel încât să încărcați geometria pe GPUglEnable()
/ glDisable()