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?