glenableclientstate is depreciated
glBindAttribLocation(programHandle, 0, "VertexPosition");
// Bind index 1 to the shader input variable "VertexColor"
glBindAttribLocation(programHandle, 1, "VertexColor");
GLuint vboHandles[2];
glGenBuffers(2, vboHandles);
GLuint positionBufferHandle = vboHandles[0];
GLuint colorBufferHandle = vboHandles[1];
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
-0.8f, -0.8f, 0.0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f };
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData,
GL_STATIC_DRAW);
// Populate the color buffer
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData,
GL_STATIC_DRAW);
glGenVertexArrays( 1, &vaoHandle );
glBindVertexArray(vaoHandle);
glEnableVertexAttribArray(0); // Vertex position
glEnableVertexAttribArray(1); // Vertex color
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0,
(GLubyte *)NULL );
// Map index 1 to the color buffer
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0,
(GLubyte *)NULL );
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
// First, we create an empty buffer of the size we need by passing
// a NULL pointer for the data values
glBufferData( GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
NULL, GL_STATIC_DRAW );//GL_STREAM_DRAW,GL_DYNAMIC_DRAW
// Next, we load the real data in parts. We need to specify the
// correct byte offset for placing the color data after the point
// data in the buffer. Conveniently, the byte offset we need is
// the same as the size (in bytes) of the points array, which is
// returned from "sizeof(points)".
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(points), points );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader24.glsl", "fshader24.glsl" );
glUseProgram( program );
// Initialize the vertex position attribute from the vertex shader
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );
// Likewise, initialize the vertex color attribute. Once again, we
// need to specify the starting offset (in bytes) for the color
// data. Just like loading the array, we use "sizeof(points)"
// to determine the correct value.
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(points)) );
In this example, we used two buffers (one for color and one for position). Instead, we
could have used just a single buffer and combined all of the data. The data for multiple
attributes can be interleaved within an array, such that all of the data for a given vertex is
grouped together within the buffer. Doing so just requires careful use of the arguments to
glVertexAttribPointer (particularly the fifth argument: the stride). Take a look at the
OpenGL documentation for full details (http://www.opengl.org/sdk/docs/man4/).
The decision about when to use interleaved arrays, and when to use separate arrays, is highly
dependent on the situation. Interleaved arrays may bring better results due to the fact that
data is accessed together and resides closer in memory (so-called locality of reference),
resulting in better caching performance.
layout (location = 1) in vec3 VertexColor;