Using VBO to draw the cube by loading wavefront object - c++

I am required to Using VBO to draw the cube by loading wavefront object.
by drawing the triangles.
here is the object:
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
f 2//1 3//1 1//1
f 4//2 7//2 3//2
f 8//3 5//3 7//3
f 6//4 1//4 5//4
f 7//5 1//5 3//5
f 4//6 6//6 8//6
f 2//1 4//1 3//1
f 4//2 8//2 7//2
f 8//3 6//3 5//3
f 6//4 2//4 1//4
f 7//5 5//5 1//5
f 4//6 2//6 6//6
I also have a cooler array filled by myself which equals to 3 times number of face which is 36 indices
float colours[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
}
I store my vertices,normals,colours information into a array which is binding to VBO buffer:
float* vbo = new float[78]
which is in the order of vertices|normals|colours which is 24indices|18indices|36indices, I have been test it works very well
I use another array to store the vertices indices information which is 36indices ,for example: f 2//1 3//1 1//1 I store as 2/3/1 in my array
int *element = new int[36];
I have been test it works well ,I initial my vbo as follow:
static void init(void){
.......
Gluint vbo_id,index_id;
glGenBuffers(1,&vbo_id);
glGenBuffers(1,&index_id);
glBindBuffer(GL_ARRAY_BUFFER,vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);
glBufferData(GL_ARRAY_BUFFER,sizeof(vbo),vbo,GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(element),element,GL_STATIC_DRAW); }
and my drawing is here
static void display(void){
.......
glBindBuffer(GL_ARRAY_BUFFER,vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3,GL_FLOAT,0,0);
glNormalPointer(GL_FLOAT,0,(void*)(24*sizeof(float)));//binding
glColorPointer(3,GL_FLOAT,0,(void*)(42*sizeof(float)));
for(int i=0;i<12;i++){
glBegin(GL_TRIANGLES);
glArrayElement(element[i]);
glArrayElement(element[i+1]);
glArrayElement(element[i+2]);
glEnd();
}
/* have try this one too:
glDrawElements(GL_TRIANGLES,3,GL_INT,0) */
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
}
however there's nothing show on the screen. is my binding method correct, my instructor tells me when I draw with the indices , if I binding vertices and normals ,and colors correct , It will automatically matching by drawing with indices of vertices.

The type of vbo is float*, so sizeof(vbo) is not the size of the array, where vbo points to, but it's the size of the pointer. See sizeof. Note, the 3rd parameter of glBufferData has to be the size of the buffer in bytes.
The size of float* vbo = new float[78] is 78 * sizeof(float) or 78 * sizeof(*vbo)
and the size of int *element = new int[36] is 36 * sizeof(int) or 36 * sizeof(*element)
But sizeof(vbo) is the size of the pointer to the array or the same as sizeof(float*).
This means you have to change the code like this:
glBufferData(GL_ARRAY_BUFFER, 78*sizeof(float), vbo, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36*sizeof(int), element, GL_STATIC_DRAW);
The 2nd paramter of glDrawElements has to be the number of indices and the 3rd paramter has to be GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT, dependent on the data type of the indices:
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);
Note, you should prefer to use unsigned int * instead of int* for the data type of the index array (element).
Your assumption is wrong. You can't mix 24 vertex coordinates, 18 normal vectors and 36 colors, with differnt arrays of indices, directly in one Vertex Array Object.
The vertex attributes for each vertex position form a set of data. This means you have to create tuples of vertex coordinate, normal vector and color.
See further Rendering meshes with multiple indices
I recommend to use std::vector and to do it somehow like this:
#include <vector>
// 8 vertex coordiantes: 8 * 3 float
std::vector<float> v{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f };
// 6 normal vectors: 6 * 3 float
std::vector<float> nv{
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f };
// 12 colors coordiantes: 12 * 3 float
std::vector<float> c{
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f };
// 12 faces 3*2 indices/face: 12 * 3 * 2 unsigned int
std::vector<unsigned int> indices{
2, 1, 3, 1, 1, 1,
4, 2, 7, 2, 3, 2,
8, 3, 5, 3, 7, 3,
6, 4, 1, 4, 5, 4,
7, 5, 1, 5, 3, 5,
4, 6, 6, 6, 8, 6,
2, 1, 4, 1, 3, 1,
4, 2, 8, 2, 7, 2,
8, 3, 6, 3, 5, 3,
6, 4, 2, 4, 1, 4,
7, 5, 5, 5, 1, 5,
4, 6, 2, 6, 6, 6 };
Create the vertex array data
// final vertex attributes 12 * 3 *(3 + 3 + 3) floats
// x0 y0 z0 nvx0 nvy0 nvz0 cr0 cg0 cb0
// x1 y1 z1 nvx1 nvy1 nvz1 cr1 cg1 cb1
std::vector<float> va;
const unsigned int no_of_faces = 12;
for (unsigned int f=0; f<no_of_faces; ++f )
{
for (unsigned int t=0; t<3; ++t )
{
unsigned int vi = indices[(f*3+t)*2]-1; // vertex index
unsigned int ni = indices[(f*3+t)*2+1]-1; // normal vector index
unsigned int ci = f; // color index
va.insert(va.end(), v.begin() + vi*3, v.begin() + vi*3+3); // insert vertex coordinate
va.insert(va.end(), nv.begin() + ni*3, nv.begin() + ni*3+3); // insert normal vector
va.insert(va.end(), c.begin() + ci*3, c.begin() + ci*3+3); // insert color
}
}
Create the Vertex Buffer Object:
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, va.size()*sizeof(*va.data()), va.data(), GL_STATIC_DRAW );
Define the an arrays of generic vertex attribute data:
glVertexPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glNormalPointer( GL_FLOAT, 9*sizeof(*va.data()), (void*)(3*sizeof(*va.data())) );
glEnableClientState( GL_NORMAL_ARRAY );
glColorPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), (void*)(6*sizeof(*va.data())) );
glEnableClientState( GL_COLOR_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
Draw the array:
glDrawArrays( GL_TRIANGLES, 0, 36 );
Preview:

Related

How to change buffers for glDrawElements

I am drawing to rectangle using glDrawElements.
glBindVertexArray(m_VAO);
glDrawElements(GL_TRIANGLES, 6 , GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
I want to draw two different geometry one facing the camera and one on the backside.
This is the data for drawing.
verticesRect = {
// Positions // Normal Coords // Texture Coords
(width / 2.0f) + taper, height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
(-width / 2.0f) - taper, height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
std::vector<float> verticesRectBack = {
// Positions // Normal Coords // Texture Coords
(width / 2.0f) + taper, height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 1.0f, 0.0f, // Top Right
width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 1.0f, 1.0f, // Bottom Right
-width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 0.0f, 1.0f, // Bottom Left
(-width / 2.0f) - taper, height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 0.0f, 0.0f // Top Left
};
verticesRect.insert(verticesRect.end(), verticesRectBack.begin(), verticesRectBack.end()); // Combining both the data sets.
This is the VAO , VBO configuration of data.
glGenVertexArrays(1, &m_VAO);
glGenBuffers(1, &m_VBO);
glGenBuffers(1 , &m_EBO);
glBindVertexArray(m_VAO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER,verticesRect.size() * sizeof(float), &verticesRect[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicesTaperRectangle), indicesTaperRectangle, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
This is the data for indices.
GLuint indicesTaperRectangle[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
Currently i am only able to draw the first rectangle how can i draw the second rectangle.
This has nothing to do with buffers. What you're experiencing is back face culling and you can go by with just a single draw call if you disable it using glDisable(GL_CULL_FACE).
Another option is to make your geometry two rectangles, and flip its winding. For that you can reuse the vertex positions and just duplicate and flip the indices:
GLuint indicesTaperRectangle_FrontAndBack[] = {
0, 1, 3,
1, 2, 3,
3, 2, 1,
3, 1, 0
};

How to add vec2 for UV for texture mapping when using indices

I am trying to apply texture mapping to my cubes but are unsure on how to proceed. Current I am using indices to avoid having to repeat vec3s to make a cube and a vertex array of the points and their normals like so:
// Cube data as our basic building block
unsigned int indices[] = {
10, 8, 0, 2, 10, 0, 12, 10, 2, 4, 12, 2,
14, 12, 4, 6, 14, 4, 8, 14, 6, 0, 8, 6,
12, 14, 8, 10, 12, 8, 2, 0, 6, 4, 2, 6
};
vec3 vertexArray[] = {
vec3(-0.5f, -0.5f, -0.5f), vec3(-0.408248, -0.816497, -0.408248),
vec3(0.5f, -0.5f, -0.5f), vec3(0.666667, -0.333333, -0.666667),
vec3(0.5f, 0.5f, -0.5f), vec3(0.408248, 0.816497, -0.408248),
vec3(-0.5f, 0.5f, -0.5f), vec3(-0.666667, 0.333333, -0.666667),
vec3(-0.5f, -0.5f, 0.5f), vec3(-0.666667, -0.333333, 0.666667),
vec3(0.5f, -0.5f, 0.5f), vec3(0.666667, -0.666667, 0.333333),
vec3(0.5f, 0.5f, 0.5f), vec3(0.408248, 0.408248, 0.816497),
vec3(-0.5f, 0.5f, 0.5f), vec3(-0.408248, 0.816497, 0.408248),
};
// convert arrays to vectors
std::vector<vec3> vertexArrayVector;
vertexArrayVector.insert(vertexArrayVector.begin(), std::begin(vertexArray), std::end(vertexArray));
std::vector<unsigned int> indicesVector;
indicesVector.insert(indicesVector.begin(), std::begin(indices), std::end(indices));
I want to now apply textures to the cube but I am not sure how to add the use of a vec2 for UV when using indices. My creating of VBOs and VAOs like this if it helps:
GLuint vertexBufferObject;
GLuint indexBufferObject;
GLuint vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
glGenBuffers(1, &indexBufferObject);
glGenBuffers(1, &vertexBufferObject);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndicesArray[0]) * vertexIndicesArray.size(), &vertexIndicesArray[0], GL_STATIC_DRAW);
// Upload Vertex Buffer to the GPU, keep a reference to it (vertexBufferObject)
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPointsArray[0]) * vertexPointsArray.size(), &vertexPointsArray[0], GL_STATIC_DRAW);
// Teach GPU how to read position data from vertexBufferObject
glVertexAttribPointer(0, // attribute 0 matches aPos in Vertex Shader
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // 0 stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(0);
// Teach GPU how to read normals data from vertexBufferObject
glVertexAttribPointer(1, // attribute 1 matches normals in Vertex Shader
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)sizeof(glm::vec3) // normal is offseted a vec3 (comes after position)
);
glEnableVertexAttribArray(1);
The vertex coordinate an the texture coordinates for a tuple with 5 components (x, y, z, u, v). If you have a vertex coordinate that is shared by the face but is associated to different texture coordinates, you need to duplicate a vertex coordinate. You must specify 1 attribute tuple for each vertex coordinate and texture coordinate combination required in your mesh.
It is not possible to specify different indices for the vertex coordinates and texture coordinates. See Rendering meshes with multiple indices and Why does OpenGL not support multiple index buffering?.

Having issues drawing 3D cube's edges with OpenGL 3

I'm trying to draw 3D cube's vertices (edges only) using OpenGL (4.3 core profile), I know the glPolygonMode function but I'd like not to draw the intermediate diagonal lines. I declare my vertices and my indices like so :
struct Vertex {
glm::vec3 pos;
glm::vec3 color;
glm::vec3 normal;
glm::vec2 uv;
};
Vertex vertices[8];
// Front vertices
vertices[0].pos = glm::vec3(-0.5f, -0.5f, +0.5f);
vertices[1].pos = glm::vec3(+0.5f, -0.5f, +0.5f);
vertices[2].pos = glm::vec3(+0.5f, +0.5f, +0.5f);
vertices[3].pos = glm::vec3(-0.5f, +0.5f, +0.5f);
// Back vertices
vertices[4].pos = glm::vec3(-0.5f, -0.5f, -0.5f);
vertices[5].pos = glm::vec3(+0.5f, -0.5f, -0.5f);
vertices[6].pos = glm::vec3(+0.5f, +0.5f, -0.5f);
vertices[7].pos = glm::vec3(-0.5f, +0.5f, -0.5f);
GLuint indices[36] = {
0, 1, 2, 2, 3, 0, // Front
1, 5, 6, 6, 2, 1, // Right
7, 6, 5, 5, 4, 7, // Back
4, 0, 3, 3, 7, 4, // Left
4, 5, 1, 1, 0, 4, // Bottom
3, 2, 6, 6, 7, 3 // Top
};
My buffer is updated accordingly :
// Bind Vertex Array
glBindVertexArray(_VAO);
// Bind VBO to GL_ARRAY_BUFFER type so that all calls to GL_ARRAY_BUFFER use VBO
glBindBuffer(GL_ARRAY_BUFFER, _VBO);
// Upload vertices to VBO
glBufferData(GL_ARRAY_BUFFER, verticesNb * sizeof(Vertex), vertices, GL_STATIC_DRAW);
// Bind EBO to GL_ARRAY_BUFFER type so that all calls to GL_ARRAY_BUFFER use EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _EBO);
// Updload indices to EBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesNb * sizeof(GLuint), indices, GL_STATIC_DRAW);
I'm using glDrawElements(GL_LINES, 36, GL_UNSIGNED_INT, 0); to draw my cube's edges, but for some reason it doesn't draw some edges and I don't understand why.
If I use GL_TRIANGLES, it works pretty well though when I want to render my 3D cube in fill-mode. Does anyone know what I'm missing here ? Is it an issue with the indices ?
(The "cube" below has a custom size of (1.0f, 2.0f, 3.0f))
Your indices form GL_TRIANGLES primitives rather than GL_LINES primitives. See GL_LINES:
Vertices 0 and 1 are considered a line. Vertices 2 and 3 are considered a line. And so on.
The indices form the primitives. Change the indices:
GLuint indices[] = {
0, 1, 1, 2, 2, 3, 3, 0, // Front
4, 5, 5, 6, 6, 7, 7, 4, // Back
0, 4, 1, 5, 2, 6, 3, 7
};
glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0);

OpenGL. Cannot draw multiple shapes. New init clears previously drawn shape

I'm trying to draw some squares within squares. I have two functions, initRedSquare() and initBlueSquare(). They have different buffers and seperate vao's which I just added before posting the question here.
Individually bothe get drawn. But I want the blue to show up over the red. When the blue square is made it removes the red square completely.
And I have to draw many more shapes after these two also.
Code :
void initRedSquare( GLfloat val )
{
GLfloat vertices[] =
{
+0.0f, +0.0f,
+1.0f, +0.0f, +0.0f,
(+0.8f - val), (+0.8f - val),
+1.0f, +0.0f, +0.0f,
(-0.8f + val), (+0.8f - val),
+1.0f, +0.0f, +0.0f,
(-0.8f + val), (-0.8f + val),
+1.0f, +0.0f, +0.0f,
(+0.8f - val), (-0.8f + val),
+1.0f, +0.0f, +0.0f,
};
// // Specifiy the vertices for a triangle
// vec2 vertices[3] = {
// vec2( -1, 0 ), vec2( -0.8, 1 ), vec2( -0.6, 0 )
// };
// Create a vertex array object
GLuint vao[1];
glGenVertexArrays( 1, vao );
glBindVertexArray( vao[0] );
// Create and initialize a buffer object
GLuint vertexbuffer;
glGenBuffers( 1, &vertexbuffer );
glBindBuffer( GL_ARRAY_BUFFER, vertexbuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader21.glsl", "fshader21.glsl" );
glUseProgram( program );
// Initialize the vertex position attribute from the vertex shader
GLuint vPosition_location = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition_location );
glVertexAttribPointer( vPosition_location, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5,
BUFFER_OFFSET(0) );
GLuint vColor_location = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor_location );
glVertexAttribPointer( vColor_location, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5,
BUFFER_OFFSET(sizeof(float) * 2) );
GLushort indices[] =
{
0, 1, 2,
0, 3, 4,
0, 2, 3,
0, 4, 1
};
GLuint indexBuffer;
glGenBuffers( 1, &indexBuffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW );
//glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background
}
void initBlueSquare( GLfloat val )
{
GLfloat vertices[] =
{
+0.0f, +0.0f,
+0.0f, +0.0f, +1.0f,
(+0.8f - val), (+0.8f - val),
+0.0f, +0.0f, +1.0f,
(-0.8f + val), (+0.8f - val),
+0.0f, +0.0f, +1.0f,
(-0.8f + val), (-0.8f + val),
+0.0f, +0.0f, +1.0f,
(+0.8f - val), (-0.8f + val),
+0.0f, +0.0f, +1.0f,
};
// // Specifiy the vertices for a triangle
// vec2 vertices[3] = {
// vec2( -1, 0 ), vec2( -0.8, 1 ), vec2( -0.6, 0 )
// };
// Create a vertex array object
GLuint vao[2];
glGenVertexArrays( 1, vao );
glBindVertexArray( vao[1] );
// Create and initialize a buffer object
GLuint vertexbuffer2;
glGenBuffers( 1, &vertexbuffer2 );
glBindBuffer( GL_ARRAY_BUFFER, vertexbuffer2 );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader21.glsl", "fshader21.glsl" );
glUseProgram( program );
// Initialize the vertex position attribute from the vertex shader
GLuint vPosition_location = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition_location );
glVertexAttribPointer( vPosition_location, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5,
BUFFER_OFFSET(0) );
GLuint vColor_location = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor_location );
glVertexAttribPointer( vColor_location, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5,
BUFFER_OFFSET(sizeof(float) * 2) );
GLushort indices[] =
{
0, 1, 2,
0, 3, 4,
0, 2, 3,
0, 4, 1
};
GLuint indexBuffer2;
glGenBuffers( 1, &indexBuffer2 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer2 );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW );
//glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background
}
void
display( void )
{
//glClear( GL_COLOR_BUFFER_BIT ); // clear the window
//glDrawArrays( GL_TRIANGLES, 0, 6 ); // draw the points
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, 0);
glFlush();
}
void
keyboard( unsigned char key, int x, int y )
{
switch ( key ) {
case 033:
exit( EXIT_SUCCESS );
break;
}
}
int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA );
glutInitWindowSize( 500, 500 );
glutCreateWindow( "Assignment 2" );
glewExperimental=GL_TRUE;
glewInit();
initRedSquare(0.2f);
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
initBlueSquare(0.3f);
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMainLoop();
return 0;
}
Vertex Shader :
attribute vec4 vPosition;
attribute vec3 vColor;
varying vec3 finalColor;
void
main()
{
gl_Position = vPosition;
finalColor = vColor;
}
Fragment Shader :
varying vec3 finalColor;
void
main()
{
gl_FragColor = vec4( finalColor, 1.0 );
}
The way you're program is structured will not work out.
First, and most important, glutDisplayFunc( display ); does not call the draw function directly, it just tells glut which function should be called whenever something should be drawn. So this function has to be able to draw ALL the content at once, in your case it will require two draw-calls with the correct state set.
To do this you'll have to store the buffers/vaos that are generated in your init functions somewhere outside of these functions and draw both objects:
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glBindVertexArray(red_vao);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(blue_vao);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, 0);
glFlush();
}
, where red_vao and blue_vao are the vao handles generated in the corresponding init function.

opengl es nacl probleme

I have an opengl es 2 code working outside of NaCl but returns this error in Chrome:
[.PPAPIContext]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 3
There is my code :
static float theta = 0.0;
glClearColor(0.5, 0.5, 0.5, 1);
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
g_matrices.PushMatrix();
g_matrices.Rotatef( theta, 0.0f, 0.0f, 1.0f );
EnableGUIShader(SM_DEFAULT);
GLfloat col[4] = {1.0f, 0.33f, 0.0f, 0.11f};
GLfloat ver[3][3];
ver[0][0] = 0.0f;
ver[0][1] = 1.0f;
ver[0][2] = 0.0f;
ver[1][0] = 0.87f;
ver[1][1] = -0.5f;
ver[1][2] = 0.0f;
ver[2][0] = -0.87f;
ver[2][1] = -0.5f;
ver[2][2] = 0.0f;
GLint posLoc = GUIShaderGetPos();
GLint colLoc = GUIShaderGetCol();
glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(ver), ver);
glVertexAttribPointer(1, 4, GL_FLOAT, 0, sizeof(col), col);
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(posLoc);
glDisableVertexAttribArray(1);
DisableGUIShader();
g_matrices.PopMatrix();
theta += 1.0f;
In the calls to glVertexAttribPointer() and glEnableVertexAttribArray() for the color, you ned to use colLoc for the first argument instead of 1:
GLint posLoc = GUIShaderGetPos();
GLint colLoc = GUIShaderGetCol();
glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(ver), ver);
glVertexAttribPointer(colLoc, 4, GL_FLOAT, 0, sizeof(col), col);
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(colLoc);
Also, if you want to pass in the colors as an array, you need a color per vertex. So for your 3 vertices, the color array would have to be col[3][4]. If you want to use the same color for all vertices, replace the glVertexAttribPointer(colLoc, ...) call with:
glVertexAttrib4f(colLoc, col[0], col[1], col[2], col[3]);