VBO to VAO

Indeed parts in the API, and the model, are overloaded from historical meanings - often in attempts to not increase the number of identifiers or perceived complexity even further.

You have the effects right, but your reason for them is wrong.

VBOs are a perfect example. The ARB wanted transitioning to VBOs to be easy. Thus they implemented it in a way that required as few changes to existing code as possible. VAO are done similarly.

The problem is the ARB’s continued insistence on this kind of backwards compatibility. Of reusing old APIs regardless of how convoluted the semantics get.

Thank you Xmas, you post helped me greatly to get VAO’s set-up… and the VAO-less iOS 3.2 path was really simple to get once the app was configured to use VAO’s (moved to an interleaved vertex format too) :)!

VAO, VBO, and IBO set-up:

	//PRAGMA MARK: VAO and VBO creation and set-up...
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	{
		if(iOS4Path) {
			glBindVertexArrayOES(0);
			glGenVertexArraysOES(1, &pageTrianglesFrontVAO);
			glBindVertexArrayOES(pageTrianglesFrontVAO);
		}
		glGenBuffers(1, &pageTrianglesVBO);
		glBindBuffer(GL_ARRAY_BUFFER, pageTrianglesVBO);
		glBufferData(GL_ARRAY_BUFFER, numVertices_ * sizeof(VertexBufferElement2D), inputMesh_, GL_STATIC_DRAW);
		glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(VertexBufferElement2D), (void*)offsetof(VertexBufferElement2D, position));
		glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(VertexBufferElement2D), (void*)offsetof(VertexBufferElement2D, texcoord));
		
		glGenBuffers(1, &pageTrianglesFrontIBO);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pageTrianglesFrontIBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, stripLength_*sizeof(GLushort), frontStrip_, GL_STATIC_DRAW);
		
		// At this point the VAO is set up with two vertex attributes
		// referencing the same buffer object, and another buffer object
		// as source for index data. We can now unbind the VAO, go do
		// something else, and bind it again later when we want to render
		// with it.
		
		if(iOS4Path) {
			glGenVertexArraysOES(1, &pageTrianglesBackVAO);
			glBindVertexArrayOES(pageTrianglesBackVAO);
		}
		glBindBuffer(GL_ARRAY_BUFFER, pageTrianglesVBO);
		glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(VertexBufferElement2D), (void*)offsetof(VertexBufferElement2D, position));
		glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(VertexBufferElement2D), (void*)offsetof(VertexBufferElement2D, texcoord));
		
		glGenBuffers(1, &pageTrianglesBackIBO);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pageTrianglesBackIBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, stripLength_*sizeof(GLushort), backStrip_, GL_STATIC_DRAW);
		
		if(iOS4Path) glBindVertexArrayOES(0);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

that code, coming after the mesh was created, deals with a co-planar mesh (used to render a page with two sides).

Rendering objects:

	glUniform1i(u_frontSideLoc, YES);
	[objDataGL validateProgramDebug]; //only used in Debug mode
	{
		if (iOS4Path) {
			CMLog(@"iOS 4.2 path...");
			glBindVertexArrayOES(0);
			glBindVertexArrayOES([obj pageTrianglesFrontVAO]);
			GL_ENABLE_VERTEX_ATTRIBUTES();
			glBindTexture(GL_TEXTURE_2D, objDataGL.textureId[0]);
			glDrawElements(GL_TRIANGLE_STRIP, stripLength, GL_UNSIGNED_SHORT, (void*)0);
			GL_DISABLE_VERTEX_ATTRIBUTES();
			
			glBindVertexArrayOES([obj pageTrianglesBackVAO]);
			GL_ENABLE_VERTEX_ATTRIBUTES();
			glBindTexture(GL_TEXTURE_2D, objDataGL.textureId[1]);
			glUniform1i(u_frontSideLoc, NO);
			glDrawElements(GL_TRIANGLE_STRIP, stripLength, GL_UNSIGNED_SHORT, (void*)0);
			GL_DISABLE_VERTEX_ATTRIBUTES();
			glBindVertexArrayOES(0);
		}
		else {
			CMLog(@"iOS 3.2 path...");
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
			
			glBindBuffer(GL_ARRAY_BUFFER, [obj pageTrianglesVBO]);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, [obj pageTrianglesFrontIBO]);
			GL_ENABLE_VERTEX_ATTRIBUTES();
			glBindTexture(GL_TEXTURE_2D, objDataGL.textureId[0]);
			glDrawElements(GL_TRIANGLE_STRIP, stripLength, GL_UNSIGNED_SHORT, (void*)0);
			GL_DISABLE_VERTEX_ATTRIBUTES();
			
			glBindBuffer(GL_ARRAY_BUFFER, [obj pageTrianglesVBO]);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, [obj pageTrianglesBackIBO]);
			GL_ENABLE_VERTEX_ATTRIBUTES();
			glUniform1i(u_frontSideLoc, NO);
			glBindTexture(GL_TEXTURE_2D, objDataGL.textureId[1]);
			glDrawElements(GL_TRIANGLE_STRIP, stripLength, GL_UNSIGNED_SHORT, (void*)0);
			GL_DISABLE_VERTEX_ATTRIBUTES();
			
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		}
	}