Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL Game Template found in xcode 4.2 (What is going on in this code?!!)

Hello I have tried understanding what is going on in this part of the code as much as I could but I haven't had any luck.

glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

glBindVertexArrayOES(0);

This belongs to the template for creating OpenGL games on the xcode 4.2. However I am totally confused and I would love if someone could explain it to me.

First how can I generate and bind the _vertexArray without adding anything to it?

Second, IF gCubeVertexData is an array of 216 with the following:

GLfloat gCubeVertexData[216] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,

I would suppose that im handling this array for the following command where i enable the GLK attributes and that's what Im using the pointers for (still using the prev bound one). But if im not mistaken the syntaxis is, (attribute to set, size of vertex, type, false, size of structure (which i think is not 24), and offset from the data (where does that 12 comes from?!))

and last question, why am i now binding 0 to the vertex array?

EDIT: To be Honest I DID try researching about opengl in various sites but I could only come across the theory not the practice. That is why I was asking this question.

like image 678
Pochi Avatar asked Nov 30 '22 15:11

Pochi


1 Answers

Ok, step by step:

glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);

This binds and generates a vertex array object (VAO). Now a VAO doesn't contain any data. It just contains all state related to vertex arrays/attributes, like the enabled attributes or the settings made with glVertexAttribPointer.

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

This now creates and binds a vertex buffer object (VBO), which is essentially jsut a plain data buffer managed by OpenGL, and copies the vertex data into it.

Let's look at this data:

GLfloat gCubeVertexData[216] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,

Your data is laid out as a bunch of floats (32-bit/4-byte each), with every six values representing a vertex, which in turn consists of a position (3 floats) and a normal (3 floats).

glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));

This specifies the first attribute (position) to contain 3 float values per vertex, with a stride of 24 bytes between each vertex. Meaning it's 24 bytes from the start of the attribute values (position in this case) of one vertex to the start of the attribute data of the next vertex. And indeed 24 bytes is the size of 6 floats and therefore of the data of a single vertex in our vertex data, so this fits exactly. The last parameter says that the position data starts at the start of the currently bound VBO (which contains our vertex data), as it's the first attribute in our vertex data.

glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

This specifies the second attribute (normal) to contain 3 float values per vertex, again with a stride of 24 bytes, as were sourcing it from the same data. So from one normal to the next it's also 24 bytes (6 floats). Now the last parameter says that the normal data starts 12 bytes (3 floats) after the start of the currently bound VBO (which contains our vertex data). This is neccessary because the normal is the second attribute in our vertex data, so we need to "jump over" the first three values (which are the position) to get to the normal data. If we had again used 0, we would take the same data as for the positions.

glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribNormal);

These finally enable the attributes for rendering.

glBindVertexArrayOES(0);

So this now binds the default (no) VAO, as we're finished with specifying it. I guess this whole code snippet is part of some initialization routine. So now whenever we later want to render our vertex data, maybe using glDrawArrays, we only need to bind the VAO using glBindVertexArray before calling the draw method and every vertex array state made by glEnableVertexAttribArray or glVertexAttribPointer get's the values set when the VAO was bound last, like in our initialization routine. If you would not use a VAO, you would have to call glBindBuffer and the two glEnableVetrexAttribArray and glVertexAttribPointer calls each time you want to draw this vertex data.

But all these explanations assume that you are more or less acquainted with these concepts. If all those words don't tell you anything, you should start with learning from some real learning resource before trying to decipher other people's code.

like image 116
Christian Rau Avatar answered Dec 14 '22 23:12

Christian Rau