Multiple buffers for a single vertex

I asked about this a while back. . . but I’m still having problems. To recap: I’m trying to make my memory usage more efficient in my terrain rendering by using only a single set of (x, y) positions, stored in a vertex array via VBO, that is used for all terrain segments. Unfortunately, what I currently have is not working properly.

Here’s the two structures I use:

struct TerrainGridVertex
{
	float coords[3];
};

struct TerrainVertex
{
	float height;
	float colour[3];
};

The first is for the reusable coordinates and the second is used for each individual terrain segment. The first has three coordinates when it really only needs two, but that’s just there for debugging purposes.

Here’s my code for filling the buffers:

aGrid = new TerrainGridVertex[nSize * nSize];
aTerrainVertices = new TerrainVertex[nSize * nSize];

for (y = 0; y < nSize; y++)
	for (UINT x = 0; x < nSize; x++)
	{
		aGrid[x + y * nSize].coords[0] = (float) x;
		aGrid[x + y * nSize].coords[1] = (float) y;
		aGrid[x + y * nSize].coords[2] = afTotal[x + y * nSize] * 0.5f;
		aTerrainVertices[x + y * nSize].height = afTotal[x + y * nSize] * 0.5f;

		float fColour;
		fColour = afTotal[x + y * nSize] / 255.0f;

		aTerrainVertices[x + y * nSize].colour[0] = fColour;
		aTerrainVertices[x + y * nSize].colour[1] = fColour;
		aTerrainVertices[x + y * nSize].colour[2] = fColour;
	}

UINT nGridSize = nSize * nSize * sizeof (TerrainGridVertex);
UINT nTerrainSize = nSize * nSize * sizeof (TerrainVertex);

glGenBuffersARB (nMeshes, &gluiVertexArray);

glGenBuffersARB (1, &gluiTerrainGrid);

glBindBufferARB (GL_ARRAY_BUFFER_ARB, gluiTerrainGrid);
glBufferDataARB (GL_ARRAY_BUFFER_ARB, nGridSize, aGrid, GL_STATIC_DRAW_ARB);

glBindBufferARB (GL_ARRAY_BUFFER_ARB, gluiVertexArray);
glBufferDataARB (GL_ARRAY_BUFFER_ARB, nTerrainSize, aTerrainVertices, GL_STATIC_DRAW_ARB);

GLenum eError = glGetError ();

switch (eError)
{
	case GL_OUT_OF_MEMORY:
		return false;

	default:
		break;
}

Again, the reusable array has 3-element coordinates for debugging purposes. In the vertex program I can simple tell it to use the third coordinate to render “normally”, without combining with another array.

Here’s my draw code:

glEnable (GL_VERTEX_PROGRAM_ARB);
glBindProgramARB (GL_VERTEX_PROGRAM_ARB, nVertexProgram);

glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glEnableClientState (GL_COLOR_ARRAY);

glBindBufferARB (GL_ARRAY_BUFFER_ARB, gluiTerrainGrid);
glVertexPointer (3, GL_FLOAT, sizeof (TerrainGridVertex), 0);

glBindBufferARB (GL_ARRAY_BUFFER_ARB, gluiVertexArray);

glTexCoordPointer (1, GL_FLOAT, sizeof (TerrainGridVertex), 0);
glColorPointer (3, GL_FLOAT, sizeof (TerrainGridVertex), BUFFER_OFFSET (sizeof (float) * 1));

glDrawElements (GL_QUADS, (nSize - 1) * (nSize - 1) * 4, GL_UNSIGNED_INT, anIndices);

glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);

glDisable (GL_VERTEX_PROGRAM_ARB);
glDisableClientState (GL_VERTEX_ARRAY);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glDisableClientState (GL_COLOR_ARRAY);

Lastly is my vertex program:

!!ARBvp1.0

PARAM	mvp[4] = {state.matrix.mvp};
PARAM	one = {1.0, 1.0, 1.0, 1.0};

TEMP	vertcoords;

MOV		result.color, vertex.color;

MOV		vertcoords.x, vertex.position.x;
MOV		vertcoords.y, vertex.position.y;
MOV		vertcoords.z, vertex.texcoord.x;
MOV		vertcoords.w, one.w;

DP4		result.position.x, mvp[0], vertcoords;
DP4		result.position.y, mvp[1], vertcoords;
DP4		result.position.z, mvp[2], vertcoords;
DP4		result.position.w, mvp[3], vertcoords;

END

Is there anything you can see wrong with what I’ve done?

Originally posted by Ostsol:

glGenBuffersARB (nMeshes, &gluiVertexArray);

I hope nMeshes==1.


glBindBufferARB (GL_ARRAY_BUFFER_ARB, gluiTerrainGrid);
glVertexPointer (3, GL_FLOAT, sizeof (TerrainGridVertex), 0);
glBindBufferARB (GL_ARRAY_BUFFER_ARB, gluiVertexArray);
glTexCoordPointer (1, GL_FLOAT, sizeof (TerrainGridVertex), 0);
glColorPointer (3, GL_FLOAT, sizeof (TerrainGridVertex), BUFFER_OFFSET (sizeof (float) * 1));

If you bind gluiVertexArray, then why sizeof(TerrainGridVertex)? Not TerrainVertex?

Also, why does “TerrainGridVertex” have 3 floats? Shouldn’t it just be 2 (the x and y)? Granted, Csiki’s point is likely the actual cause of the problem.

sighs I can’t believe I didn’t catch that. . . Copy-paste is the bane of my existance. Thanks, guys!

TerrainGridVertex has three components only temporarily. It’s like that so I could test other parts of my vertex shader without worrying about combining the vertex positions. It certainly is totally pointless overall, though, and can be taken out.

Anyways, it finaly works, so thanks, again.