Guide to Game Development/Rendering and Game Engines/OpenGL/Drawing geometry
Drawing Geometry without color
[edit | edit source]This is how you pass the vertex data for triangles to OpenGL.
The data is specified in an array, where every three vertices represents a new triangle. In this format the data needs to be specified in the order that they will be connected.
#include <gl\glew.h>
#include <MyGLWindow.h>
void MyGLWindow::initializeGL(){
GLfloat verts[] =
{
//1st Triangle
+0.0f, +1.0f, +0.0f, //Vertex 1
-1.0f, -1.0f, -0.5f, //Vertex 2
+1.0f, -1.0f, +0.5f, //Vertex 3
//2nd Triangle
+0.0f, -1.0f, +0.0f, //Vertex 1
-1.0f, +1.0f, -0.5f, //Vertex 2
+1.0f, +1.0f, +0.5f, //Vertex 3
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID); //Generate an identifier for the buffer ID
glBindBuffer(GL_ARRAY_BUFFER, myBufferID); //Bind it to the array buffer binding point
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); //Send the size of the data and the data to the buffer assigned to the array buffer binding point.
//Describing the data
glEnableVertexAttribArray(0); //The first attribute to send to openGL (later redirected through a vertex shader)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); //There are 3 floats per vertex...
}
void MyGLWindow::paintGL(){
glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
glDrawArrays(GL_TRIANGLES, 0, 6); //Connect the 6 vertices into triangles (triangle=3, 6/3 = 2 triangles)
}
This code could easily be altered to just pass 2D data only, to do this you'll need to change two things:
- The array should only say the X and Y coordinate.
- glVertexAttribPointer parameter 2 will need to be changed from 3 to 2.
Optimised Drawing of Geometry
[edit | edit source]This new version of the program passes the ids of the positions of the vertices to say how the triangles should be connected. For basic triangles that aren't connected, this is less efficient than before, how for most shapes, triangles will share vertices, this will mean that you won't need to specify 3 pieces of data (XYZ, more if color and light normals are added), you only pass an extra short for the index of the vertex. This saves on RAM as less data is needed, and for animated geometry, it will mean that less duplicate data will need to be sent to OpenGL and beyond.
#include <gl\glew.h>
#include <MyGLWindow.h>
void MyGLWindow::initializeGL(){
GLfloat verts[] =
{
//1st Triangle
+0.0f, +1.0f, +0.0f, //Vertex 1
-1.0f, -1.0f, -0.5f, //Vertex 2
+1.0f, -1.0f, +0.5f, //Vertex 3
//2nd Triangle
+0.0f, -1.0f, +0.0f, //Vertex 1
-1.0f, +1.0f, -0.5f, //Vertex 2
+1.0f, +1.0f, +0.5f, //Vertex 3
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID); //Num buffers, BufferID
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
//Assigning the positions of the vertices into 2 triangle (triangle 1= {0,1,2}, triangle 2={3,4,5})
GLushort indices[] = {0,1,2, 3,4,5};
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID); //Generate an identifier for the index buffer ID
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); //Link the index buffer to the element array buffer binding point
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //Send the size of the data and the data to the index buffer, linked to the element array buffer binding point.
//Describing the data
glEnableVertexAttribArray(0); //The first attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); A vertex consists of 3 floats
}
void MyGLWindow::paintGL(){
glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0); //Notice this is different from above
}
Drawing Geometry with color (keeping optimisations from before)
[edit | edit source]Note: The color won't work until you set up the fragment shader. However, to setup the fragment shader you need to send the color data from the vertex shader.
#include <gl\glew.h>
#include <MyGLWindow.h>
void MyGLWindow::initializeGL(){
GLfloat verts[] =
{
//One colourful triangle being drawn
+0.0f, +1.0f, +0.0f, //Vertex 1
+1.0f, +0.0f, +0.0f, //Vertex 1's Color (Red)
-1.0f, -1.0f, -0.5f, //Vertex 2
+0.0f, +1.0f, +0.0f, //Vertex 2's Color (Green)
+1.0f, -1.0f, +0.5f, //Vertex 3
+0.0f, +0.0f, +1.0f, //Vertex 3's Color (Blue)
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID); //Num buffers, BufferID
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
GLushort indices[] = {0,1,2};
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//Describing the data
glEnableVertexAttribArray(0); //The first attribute (Vertex data)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) *6,0); //There are 6 floats worth of data from the start of one list of vertices and the next set of vertices
glEnableVertexAttribArray(1); //The second attribute (Color data)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) *6, (char*)(sizeof(float)*3)); //There are 6 floats worth of data from the start of one list of vertices and the next set of vertices. The first piece of data starts after 3 floats.
}
void MyGLWindow::paintGL(){
glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
}