JOGL Rendering many objects with VBO and Display Lists

Started by
15 comments, last by V-man 15 years, 10 months ago
Don't use doubles, they aren't native on most consumer GPUs, just use floats.
Advertisement
I only get a marginal increase with floats.
Ok, I've looked at it, and you've made a small mistake [smile]

You just need one display list for the ball model, not one for every ball object.
What you should do is create the display list in the PongDisplay class.
Then you can pass the display list as a parameter to Ball::Draw.

//// Ball::Draw//	public void draw(GL gl, unsigned int ball_dlist) { //draw ball		if (isWhirling) {			gl.glColor3f(0.0f, 1.0f, 0.0f);		} else {			gl.glColor3f(red, green, blue);		}		gl.glPushMatrix();		gl.glTranslated(xn, yn, 0);		gl.glCallList(ball_dlist);		gl.glPopMatrix();	}


//// This function is now located at// PongDisplay::generateDisplayList//	public void generateDisplayList(GL gl) { //generate display list		display_list = gl.glGenLists(1);		gl.glNewList(display_list, GL.GL_COMPILE);		gl.glBegin(GL.GL_POLYGON);		for (int a = 0; a < RESOLUTION; a++) 		{			gl.glVertex2d(POINTS_X[a], POINTS_Y[a]);		}			gl.glEnd();		gl.glEndList();	}



//// PongDisplay::init//	public void init(GLAutoDrawable gld) {		gl = gld.getGL();		GLU glu = new GLU();		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);		gl.glPointSize(5.0f);		gl.glViewport(0, 0, 600, 600);		gl.glMatrixMode(GL.GL_PROJECTION);		gl.glLoadIdentity();		glu.gluOrtho2D(0, 600, 0, 600);		generateDisplayList(gl);	}


//// inside PongDisplay::display//ball.draw(gl, display_list); //draw ball


I'm not sure if this is going to fix the speed issue, but this is how you should use the display list.
If this doesn't solve it, try removing glPushMatrix() and glPopMatrix() from Ball::Draw and see if that does anything.
while (tired) DrinkCoffee();
It doesn't change the speed. Romoving the push and pop messes up the drawing and doesn't change speed either. There has to be a way to get millions of ball i would think. I have a Geforce 8600.

Would VBOs really give me the kinda speed I need?
I believe a display list is marginally faster than a VBO. A VBO shouldn't outperform a display list enough to make a difference anyway. What's good about VBOs is that they provide you with a much greater degree of control over the actual vertex attributes. But AFAIK, they're not faster than display lists, just a lot more flexible.

When I think about it, the slowdown is probably caused by the large amount of matrix multiplications caused by using glTranslate for every ball. Perhaps using glBegin() and glEnd() is the optimal solution for rendering a really big amount of very simple meshes.


I guess another option is using a Vertex Array.
You'll have to create some form of shared vertex list. Every time you render a ball, the ball add its 12 vertices to this shared list. When all the balls which should be rendered have added its vertices to the list, you simply render 12 and 12 vertices at a time with GL_POLYGON. Then you clear the list and repeat the same process for the next frame.

Here's a small example which renders a quad:

float vert[12] = {-1, -1, -5, 1, -1, -5, 1, 1, -5, -1, 1, -5};float color[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_COLOR_ARRAY);glVertexPointer(3, GL_FLOAT, 0, vert); //3 floats per vertexglColorPointer(3, GL_FLOAT, 0, color); // 3 floats per colorglDrawArrays(GL_QUADS, 0, 4); // Render one quad with the data specified with glVertexPointer and glColorPointer


Vertex Array tutorial




EDIT: The code below won't work, I didn't think that through properly at all.
Obviously you can't render multiple polygons with one glBegin(GL_POLYGON), because a polygon is defined as everything between a glBegin() and glEnd(). My bad. [smile]
-----------------------------------------------------

You could revert back to your original glBegin() and glEnd() method, but you should make as few glBegin() and glEnd() calls as possible. So, you should put those calls outside Ball::Draw.

Something like this:

//// PongDisplay::display//public void display(GLAutoDrawable gld) {    // ...    gl.glBegin(GL.GL_POLYGONS);                for (int i = 0; i < NUM_BALLS; i++) {        // ...				ball.draw(gl); //draw ball    }    gl.glEnd();}


//// Ball::draw//public void draw(GL gl) {    if (isWhirling) {	gl.glColor3f(0.0f, 1.0f, 0.0f);    } else {	gl.glColor3f(red, green, blue);    }    for (int a = 0; a < RESOLUTION; a++) {	gl.glVertex2f(xn+POINTS_X[a], yn+POINTS_Y[a]);    }}


[Edited by - polymorphed on May 30, 2008 7:06:36 PM]
while (tired) DrinkCoffee();
Any idea as to why I can render so few of them? I would assume the current generation of video cards would do much better.
I always recommending interleaving and using supported formats

struct MyVertex{   float x, y, z;   uint color;   float garbage[4];   //For padding, to make structure multiple of 32 byte};MyVertex myvertex[4];glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_COLOR_ARRAY);glVertexPointer(3, GL_FLOAT, sizeof(MyVertex), &myvertex[0].x);glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MyVertex), &myvertex[0].color);glDrawArrays(GL_QUADS, 0, 4); // Render one quad with the data specified with glVertexPointer and glColorPointer


You can even convert to GL_TRIANGLES since GL_QUADS aren't directly supported.

Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

This topic is closed to new replies.

Advertisement