Guide to Game Development/Rendering and Game Engines/OpenGL/Drawing geometry

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Drawing Geometry without color[edit]

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]

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]

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);
}

References[edit]