Hello!
I user vertex arrays in my program, and I wanted to user vbo, but the speed is down by 500%. I posted the code in the gamedev.net, and nobody knows (yet) where is the error? I really appriciate if you could help me
Code:
The code render a terrain divided into (128x128) pieces (size:32x32).
The codetry to use 1 big buffer for all verteces (vertexBuffer). The code display the result with unexceptable speed.
private static void initArrayBuffers(){
vertexIndexCount = (2*(SpellinaWorldStatics.SEGMENTSIZE+1)-1)*SpellinaWorldStatics.SEGMENTSIZE + 1;
vertexCount = (SpellinaWorldStatics.SEGMENTSIZE+1) * (SpellinaWorldStatics.SEGMENTSIZE+1);
vertexIndexBuffer = setupIntBuffer(ByteBuffer.allocateDirect( vertexIndexCount * BufferUtils.SIZEOF_INT ));
colorCoordinateBuffer = setupByteBuffer(ByteBuffer.allocateDirect( 4 * vertexCount ));
textureCoordinateBuffer = setupFloatBuffer(ByteBuffer.allocateDirect( 2 * vertexCount * BufferUtils.SIZEOF_FLOAT ));
bumpTextureCoordinateBuffer = setupFloatBuffer(ByteBuffer.allocateDirect( 2 * vertexCount * BufferUtils.SIZEOF_FLOAT ));
}
private static void fillCoordinateBuffers(){
colorCoordinateBuffer.clear();
textureCoordinateBuffer.clear();
bumpTextureCoordinateBuffer.clear();
for (int i = 0; i <= SpellinaWorldStatics.SEGMENTSIZE; ++i ) {
for (int j = 0; j <= SpellinaWorldStatics.SEGMENTSIZE; ++j) {
colorCoordinateBuffer.put( (byte)0 );
colorCoordinateBuffer.put( (byte)0 );
colorCoordinateBuffer.put( (byte)0 );
textureCoordinateBuffer.put( 1.0f * j / SpellinaWorldStatics.SEGMENTSIZE );
textureCoordinateBuffer.put( 1-1.0f * i / SpellinaWorldStatics.SEGMENTSIZE );
bumpTextureCoordinateBuffer.put( 1.0f * j / SpellinaWorldStatics.SEGMENTSIZE );
bumpTextureCoordinateBuffer.put( 1.0f * i / SpellinaWorldStatics.SEGMENTSIZE );
}
}
}
private static void fillIndexBuffers(){
vertexIndexBuffer.clear();
for (int i = 0; i+1 <= SpellinaWorldStatics.SEGMENTSIZE; ++i ) {
if( (i % 2) == 0){
for (int j = 0; j <= SpellinaWorldStatics.SEGMENTSIZE; ++j) {
vertexIndexBuffer.put( getElement(i,j) );
vertexIndexBuffer.put( getElement(i+1,j) );
}
}
else{
for (int j = SpellinaWorldStatics.SEGMENTSIZE; j >= 0; --j) {
if( j != SpellinaWorldStatics.SEGMENTSIZE){
vertexIndexBuffer.put( getElement(i,j) );
}
if( j != 0 || i+1 == SpellinaWorldStatics.SEGMENTSIZE ){
vertexIndexBuffer.put( getElement(i+1,j) );
}
}
}
}
}
private static void initVBONames(){
gl.glGenBuffersARB( 4, names );
gl.glBindBufferARB( GL.GL_ELEMENT_ARRAY_BUFFER_ARB, names[0] );
gl.glBufferDataARB( GL.GL_ELEMENT_ARRAY_BUFFER_ARB, vertexIndexCount * BufferUtils.SIZEOF_FLOAT, vertexIndexBuffer, GL.GL_STATIC_DRAW_ARB );
gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, names[1] );
gl.glBufferDataARB( GL.GL_ARRAY_BUFFER_ARB, 4 * vertexCount, colorCoordinateBuffer, GL.GL_STATIC_DRAW_ARB );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0);
gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, names[2] );
gl.glBufferDataARB( GL.GL_ARRAY_BUFFER_ARB, 2 * vertexCount * BufferUtils.SIZEOF_FLOAT, textureCoordinateBuffer, GL.GL_STATIC_DRAW_ARB );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0);
gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, names[3] );
gl.glBufferDataARB( GL.GL_ARRAY_BUFFER_ARB, 2 * vertexCount * BufferUtils.SIZEOF_FLOAT, bumpTextureCoordinateBuffer, GL.GL_STATIC_DRAW_ARB );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0);
}
// init method
public static void initEngine(GL gl, GLU glu){
initArrayBuffers();
fillCoordinateBuffers();
fillIndexBuffers();
initVBONames();
}
private static IntBuffer setupIntBuffer(ByteBuffer buf) {
buf.order(ByteOrder.nativeOrder());
return buf.asIntBuffer();
}
private static FloatBuffer setupFloatBuffer(ByteBuffer buf) {
buf.order(ByteOrder.nativeOrder());
return buf.asFloatBuffer();
}
private static ByteBuffer setupByteBuffer(ByteBuffer buf) {
buf.order(ByteOrder.nativeOrder());
return buf;
}
// allocating memory for the buffers
private static void initArrays(){
vertexBuffer[actualTerrain] = setupFloatBuffer(ByteBuffer.allocateDirect( stepLimits[ actualTerrain ] * stepLimits[ actualTerrain ] * 3 * vertexCount * BufferUtils.SIZEOF_FLOAT ));
colorBuffer[actualTerrain] = setupByteBuffer(ByteBuffer.allocateDirect( stepLimits[ actualTerrain ] * stepLimits[ actualTerrain ] * SpellinaWorldStatics.WATERTEXTUREINDEX * 4 * vertexCount ));
vertexOffsets[actualTerrain] = new int[ stepLimits[ actualTerrain ] ][ stepLimits[actualTerrain] ];
colorOffsets[actualTerrain] = new int[ stepLimits[actualTerrain] ][ stepLimits[actualTerrain] ][ SpellinaWorldStatics.WATERTEXTUREINDEX ];
}
// fill the buffers up
private static void fillVertexArrays(){
int shiftXIndex = 0, shiftZIndex = 0; int vertexIndex = 0, colorIndex = 0;
for(int k=0; k<stepLimits[actualTerrain]; ++k)
for(int l=0; l<stepLimits[actualTerrain]; ++l){
shiftXIndex = k * SpellinaWorldStatics.SEGMENTSIZE;
shiftZIndex = l * SpellinaWorldStatics.SEGMENTSIZE;
vertexOffsets[actualTerrain][k][l] = vertexIndex;
for(int m = 0; m<SpellinaWorldStatics.WATERTEXTUREINDEX; ++m){
colorOffsets[actualTerrain][k][l][m] = colorIndex;
}
for (int i = 0; i <= SpellinaWorldStatics.SEGMENTSIZE; ++i ) {
for (int j = 0; j <= SpellinaWorldStatics.SEGMENTSIZE; ++j) {
vertexBuffer[actualTerrain].put( vertexIndex++, (shiftXIndex + i)*2 - steps[actualTerrain] );
vertexBuffer[actualTerrain].put( vertexIndex++, SpellinaTerrainStatics.getAltitude( actualTerrain, shiftXIndex + i, shiftZIndex + j )*1.0f );
vertexBuffer[actualTerrain].put( vertexIndex++, (shiftZIndex + j)*2 - steps[actualTerrain] );
for(int m = 0; m<SpellinaWorldStatics.WATERTEXTUREINDEX; ++m){
colorBuffer[actualTerrain].put( colorIndex++, (byte)255 );
}
for(int m = 0; m<SpellinaWorldStatics.WATERTEXTUREINDEX; ++m){
colorBuffer[actualTerrain].put( colorIndex++, (byte)255 );
}
for(int m = 0; m<SpellinaWorldStatics.WATERTEXTUREINDEX; ++m){
colorBuffer[actualTerrain].put( colorIndex++, (byte)255 );
}
for(int m = 0; m<SpellinaWorldStatics.WATERTEXTUREINDEX; ++m){
colorBuffer[actualTerrain].put( colorIndex++, (byte)(alphas[actualTerrain][shiftXIndex+i][shiftZIndex+j][m]+128) );
}
}
}
}
}
// creating the names of terrain pices
private static void createVBONames(){
int[] temp = CreationFactory.createInt1DArray( 1 );
gl.glGenBuffersARB( 1, temp );
gl.glBindBufferARB( GL.GL_ELEMENT_ARRAY_BUFFER_ARB, vertexNames[actualTerrain] = temp[0] );
gl.glBufferDataARB( GL.GL_ELEMENT_ARRAY_BUFFER_ARB, stepLimits[ actualTerrain ] * stepLimits[ actualTerrain ] * 3 * vertexCount * BufferUtils.SIZEOF_FLOAT, vertexBuffer[actualTerrain], GL.GL_STATIC_DRAW_ARB );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0);
temp = CreationFactory.createInt1DArray( 1 );
gl.glGenBuffersARB( 1, temp );
gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, colorNames[actualTerrain] = temp[0] );
gl.glBufferDataARB( GL.GL_ARRAY_BUFFER_ARB, stepLimits[ actualTerrain ] * stepLimits[ actualTerrain ] * SpellinaWorldStatics.WATERTEXTUREINDEX * 4 * vertexCount, colorBuffer[actualTerrain], GL.GL_STATIC_DRAW_ARB );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0);
}
// render method
public static void renderVBOTerrain(){
gl.glEnableClientState( GL.GL_VERTEX_ARRAY );
gl.glEnableClientState( GL.GL_COLOR_ARRAY );
gl.glEnableClientState( GL.GL_TEXTURE_COORD_ARRAY );
for(int k=0; k< stepLimits[actualTerrain]; ++k){
for(int l=0; l< stepLimits[actualTerrain]; ++l){
gl.glDisable( GL.GL_TEXTURE_2D );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, names[1] );
gl.glColorPointer( 3, GL.GL_UNSIGNED_BYTE, 0, BufferUtils.bufferOffset( 0 ) );
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, vertexNames[actualTerrain] );
gl.glVertexPointer( 3, GL.GL_FLOAT, 0, BufferUtils.bufferOffset( vertexOffsets[actualTerrain][k][l] * BufferUtils.SIZEOF_FLOAT ) );
gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, names[0] );
gl.glDrawElements( GL.GL_TRIANGLE_STRIP, vertexIndexCount, GL.GL_UNSIGNED_INT, BufferUtils.bufferOffset( 0 ) );
}
}
gl.glDisableClientState( GL.GL_VERTEX_ARRAY );
gl.glDisableClientState( GL.GL_COLOR_ARRAY );
gl.glDisableClientState( GL.GL_TEXTURE_COORD_ARRAY );
}
}