Question about display lists/general rendering

Started by
3 comments, last by nife87 16 years, 2 months ago
Hello, Perhaps someone can finally set me straight on this issue once and for all. :) I have a B-Spline surface drawing to the screen (it has 50 u-segments and 50 v-segments for a triangle count of 2500 * 2 = 5000). I am using QT for this current test application. In my paintGL() function, I make a call to the surface rendering function, and whenever I rotate the camera with a mouse drag, I call updateGL (which calls paintGL). This, in turn, means I am able to rotate the scene very fast and it will call paintGL, and in turn the surface render function, many times per second. There is no slowdown when I do this (in my surface render function, apart from specifying previously calculated colors/normals, I simply use GL_TRIANGLE_STRIP and go through a 2D array of mesh values also previously calculated). Now, in another function, I have need to draw this surface into the back buffer (with gradient shading) and perform a special operation on it. This special operation involves setting up a specific camera angle and using glReadPixels to determine the RGB value at a specific window value. However, I need to repeat this about 300 times for 300 different variables. Each surface rendering, I need to change the camera angle ONLY (I set up a viewing angle with gluPerspective and gluLookAt, then call the surface render function which draws a bazillion triangles). This operation takes upwards of 4 to 5 seconds, and ultimately I'd actually like to be able to increase the number of variables higher than 300. Obviously, it is drawing the 5000 triangles 300 times that is slowing me down, when I really only need to draw it once and just look at it from 300 different angles. At first, I had thought I could only draw the surface the first pass, then just change the camera angle 300 times to get my data. However, this somewhat obviously doesn't work because the scene must be redrawn with a new camera angle to fill the color buffers that I read when calling glReadPixels(..., GL_RGB, ...). Is display lists what I'm looking at here? Is this going to create the speed increase I am looking for? I would rather not spend the time re-researching the syntax for display lists if it is not going to help me out. To recap: I have a scene with 5000 triangles, and I need to draw this into the back buffer with a special coloring (the user will never see this) and look at it from 300+ different camera angles to get some important information. I only want to spend the time drawing the surface once, since it is a waste of my time if I am only ever changing the camera angle each time. Thanks to anyone who read this wall of text and who can help me. If I am unclear in my description, please ask for clarification and I will provide it!
Advertisement
Sounded like you make lots of calls to glReadPixels and you use GL_RGB.
32 bit is bitter. On Windows, GL_BGRA is prefered over GL_RGBA.
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);
It's dangerous to guess at where your bottleneck is without actually experimenting with the app, but here are a few ideas you could try.

Assuming that it is the drawing operation which is causing the slow down, there are a few things you could try. When you say "go through a 2D array", are you using immediate mode (glBegin/glEnd) or client vertex arrays? Using vertex arrays can cut down some of your overhead by reducing the number of function calls needed to draw the mesh. Since you are drawing the same vertex data many times, storing it in a VBO may cut down on your transfer costs. Since you always have the same general mesh layout, you could also try switching to indexed primitives and storing the static index data in a VBO. That way when the positions of the vertices change, you would be able to reuse the index data. I would use VBO instead of display lists for this kind of thing.

Another thing to consider is the read pixels operation itself. At the moment you are forcing the cpu to block on the read pixels until the rendering operation is complete, then the gpu is idle until you can start another draw. If you are using immediate mode, it seems like this could be especially bad. You could try using PBO to do an asynchronous read pixels and avoid synchronizing the CPU/GPU here.
Thank you for your reply, Solias. Forgive my ignorance, but what do PBO and VBO mean? I've coded a lot of basic openGL, but I've never really used the more advanced features of the tool.

I will post some code below that illustrates my bottleneck. Maybe this will allow someone to glean more insight from it! I guarantee I'm being extremely inefficient in a wide variety of areas, so any help would be appreciated. :) (As you can see, I use glBegin/glEnd and I also use glReadBuffer, likely inappropriately.)

I call getUVProjection, with different values for "point", but the same "normal" and "surface" each time, in a loop that executes about 300 times.

// returns true if the point, projected along the normal, intersects with the surface// returns the u and v coordinates of the surface that the point hits when projected along the normalbool GLDeform::getUVProjection(double &u, double &v, const C3DPoint &point, const C3DPoint &normal, BasicSurface *surface){	GLfloat color[3];	bool result = false;	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	// Set the correct perspective.	gluPerspective(45,1,1,100); // a very very small viewing angle		glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	gluLookAt(point.x(), point.y(), point.z(), 		point.x()-(normal.x()*EPS), point.y()-(normal.y()*EPS), point.z()-(normal.z()*EPS), 		0.0, 1.0, 0.0); // look down at the surface along the normal	surface->render(true); // bottleneck here?? (draws the surface with gradient shading)	glReadBuffer(GL_BACK);	glReadPixels(width/2, height/2, 1, 1, GL_RGB, GL_FLOAT, color); // look right down the middle	if(color[2] > 0.001) {		result = true;		u = color[0];		v = color[1];	}	// Reset the coordinate system before modifying	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	// Set the correct perspective.	gluPerspective(45,(float)width/height,1,100);	glMatrixMode(GL_MODELVIEW);	return result;}




And here is (the relevant snippets from) my surface render function:



void BSurface::render(bool colorMode){		if(colorMode) { // set up colors to draw with gradient shading		glColor4f(r,g,b,alpha);		glDisable(GL_LIGHTING);		if(colorMode) { // don't mind this redundancy, I took out some other unimportant variables from this if-clause			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);			glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		}		else			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);	}	else { // draw the surface normally		GLfloat arr[4] = {r,g,b,alpha};		GLfloat allones[4] = {1,1,1,alpha};		glEnable(GL_LIGHTING);		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0f);		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, arr);		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, arr);		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, allones);		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);	}	// draw the mesh (stored in vector<vector<point> > "mesh", with matching normals in "normals", calculated earlier)	for(int u=0; u<numUSegs; u++) {		glBegin(GL_TRIANGLE_STRIP);		for(int v=0; v<=numVSegs; v++) {			if(!wireframe && !colorMode)				glNormal3f(normals[v].x(), normals[v].y(), normals[v].z());			if(colorMode)				glColor4f((double)u/numUSegs, (double)v/numVSegs, 0.5, 1);			glVertex3f(mesh[v].x(), mesh[v].y(), mesh[v].z());			if(!wireframe && !colorMode)				glNormal3f(normals[u+1][v].x(), normals[u+1][v].y(), normals[u+1][v].z());			if(colorMode)				glColor4f((double)(u+1)/numUSegs, (double)v/numVSegs, 0.5, 1);			glVertex3f(mesh[u+1][v].x(), mesh[u+1][v].y(), mesh[u+1][v].z());		}		glEnd();	}}



Quote:Original post by Infil
Thank you for your reply, Solias. Forgive my ignorance, but what do PBO and VBO mean?


Whenever somebody mentions a phrase or a word that you are unfamiliar with; use Google. (or one of the others. The point is that it will take you less than a second, while these sort of questions, which must have been answered upon hundreds of times on these boards, will take much, much longer and involve two developers instead of just you).
It is only meant as an advice :)

This topic is closed to new replies.

Advertisement