PDA

View Full Version : Duplicate geometry appearing on incorrect VBO



mikkell404
01-17-2012, 08:12 AM
Hey folks,

I'm new to openGL and absolutely love it.


Problem:

I have multiple interleaved VBOs. The geometry itself is rendering properly. However, it appears that in some cases that the geometry from one VBO gets combined with the geometry from another VBO.


I'm rendering planets. Each planet contains 4 VBOs based on quality: low, med, high, best. These are selectively rendered based on camera distance from the planet surface.


Most planets render properly. In some situations a planet may render the geometry for itself as well as the geometry of another planet over top of itself.


Image attached.



Details:

Java / LWJGL on Win 7 x64

No shaders

Seems to be vedor specific:
Radeon HD 68xx - problem appears
GeForce 8600GT - no problem

GL_VENDOR: ATI Technologies Inc.
GL_VERSION: 4.2.11318 Compatibility Profile Context
GL_RENDERER: AMD Radeon HD 6800 Series



Does my approach below look correct?








private void prerender()
{

if ( !prerendered )
{
prerendered = true;


validateVerticies();

if ( verticies.length > 0 )
{

/*
* Setup Buffers
*/

// Generate buffer ids
buffers = BufferUtils.createIntBuffer(2);
GL15.glGenBuffers(buffers);


/*
* Setup VBO
*/

int floatCnt = verticies[0].getOutput().length;

vboBuffer = BufferUtils.createFloatBuffer(verticies.length*flo atCnt);
for ( int i=0; i<verticies.length; ++i)
vboBuffer.put( verticies[i].getOutput() );
vboBuffer.flip();


// Bind and Upload
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buffers.get(0));
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vboBuffer, GL15.GL_STATIC_DRAW);


// Pointer Data
// note: glVertexPointer should be at the end
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, offsetTexture);
GL11.glNormalPointer(GL11.GL_FLOAT, stride, offsetNormal);
GL11.glColorPointer(4, GL11.GL_FLOAT, stride, offsetColor);
GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, offsetVertex);


/*
* Setup IBO
*/

int size = verticies.length*stride;

iboBuffer = BufferUtils.createIntBuffer(size);
for ( int i=0; i<size; ++i)
iboBuffer.put(i);
iboBuffer.flip();


// Bind and Upload
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, buffers.get(1));
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, iboBuffer, GL15.GL_STATIC_DRAW);


checkError();


// Log
log("+ VBO:" + name + ", " + buffers.get(0) + ", " + buffers.get(1) );

}

}

}


/*
* Interleaved Data Format
* 3 vertex, 3 normal, 4 color, 2 texture, 4 padding
*
* Example Data (floats):
* {vX, vY, vZ, nX, nY, nZ, cX, cY, cZ, cA, tX, tY, 0f, 0f, 0f, 0f}
*
* floats are 4 bytes each
*
*/

private int floatBytes = 4;
private int stride = (3 + 3 + 4 + 2 + 4) * floatBytes; // should total 64;

private int offsetVertex = 0;
private int offsetNormal = (3) * floatBytes;
private int offsetColor = (3+3) * floatBytes;
private int offsetTexture = (3+3+4) * floatBytes;


/*
* Render VBO data
*
*/

public void render()
{

if ( verticies.length > 0 )
{

prerender();


// Bind the vertex buffer and the index buffer
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buffers.get(0));
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, buffers.get(1));


// Enable State
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARR AY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);


// Pointer Data
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, offsetTexture);
GL11.glNormalPointer(GL11.GL_FLOAT, stride, offsetNormal);
GL11.glColorPointer(4, GL11.GL_FLOAT, stride, offsetColor);
GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, offsetVertex);



/*
* Debug: Check the current binding
*/

IntBuffer response = BufferUtils.createIntBuffer(16);
GL11.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING, response);
int arrayBinding = response.get(0);

GL11.glGetInteger(GL15.GL_COLOR_ARRAY_BUFFER_BINDI NG, response);
int colorBinding = response.get(0);

GL11.glGetInteger(GL15.GL_VERTEX_ARRAY_BUFFER_BIND ING, response);
int vertexBinding = response.get(0);

if ( arrayBinding != buffers.get(0) || colorBinding != buffers.get(0) || vertexBinding != buffers.get(0) )
{
log("BINDING ERROR!");
}



// Draw
GL11.glDrawElements(type, verticies.length*stride, GL11.GL_UNSIGNED_INT, 0);

// Log
log("> VBO:" + name + ", " + buffers.get(0) + ", " + buffers.get(1) + ", verts: " + verticies.length);


// Disable State
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_AR RAY);


// Unbind
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);



}



}





Any suggestions would be appreciated.

carsten neumann
01-17-2012, 02:40 PM
int size = verticies.length*stride;


Why do you put #vertices * stride many indices in your IBO? Shouldn't it be just one index per vertex? Since the i-th index is i you could just use non-indexed drawing (glDrawArrays()) and do away with the IBO completely.

It looks like you are uploading data to the buffers each frame, that wastes performance - of course until it works correctly that is a secondary concern ;)

mikkell404
01-17-2012, 03:22 PM
I dropped the IBO and used non-indexed drawing like you suggested. This resolved the duplicate geometry issues and provided a nice increase in fps.

This is awesome. Many thanks.


One remaining question:


It looks like you are uploading data to the buffers each frame ...

My messy code might not make it clear that prerender is only called on the first render pass.

Is this what you are referring to or am I overlooking something?

carsten neumann
01-17-2012, 03:25 PM
No, I just overlooked the test at the beginning of the function, sorry about the false alarm.

mikkell404
01-17-2012, 03:51 PM
Awesome, thanks again.