[Bf-committers] OpenGL optimisation

Richard Berry bf-committers@blender.org
Mon, 24 May 2004 13:56:44 +0100


>> A few choice expletives and a fresh CVS later:
>>
>> http://www.warwick.ac.uk/student/R.J.Berry/customblender.zip
>
> I gave this a try on OSX 10.3 with a file with some high poly subsurfs.
> Speed increased from 3.1 FPS (2.33) to 6.5 FPS on this version. Not
> bad! One thing I did notice though, it that all my objects that were
> 'set smooth' were not in your version, they were displayed flat shaded.
> Is this a limitation in the OpenGL display lists? Could it also be a
> factor in speeding it up?
>
> Matt

The main change that I've made to the code is to alter the displistmesh_dra=
w_solid routine from drawobject.c (apologies if this is formatted badly):

static void displistmesh_draw_solid(DispListMesh *dlm, int drawsmooth, =
float *nors) {
	/* rick: the authors really should be shot... */
	int lmode, lshademodel=3D GL_FLAT, lmat_nr=3D -1;
	int i;

#define PASSVERT(ind) {								=
	\
	if (drawsmooth && lshademodel=3D=3DGL_SMOOTH)				=
\
		glNormal3sv(dlm->mvert[(ind)].no);				=
	\
	glVertex3fv(dlm->mvert[(ind)].co);					=
	\
}

	/* rick: draw a display list if we've already got one */
	if (dlm->dispList) {
		glCallList(dlm->dispList);
		return;
	}

	/* rick: no OpenGL display list defined, so make one */
	dlm->dispList =3D glGenLists(1);
	glNewList(dlm->dispList, GL_COMPILE_AND_EXECUTE);

	glBegin(lmode=3D GL_QUADS);
	for (i=3D0; i<dlm->totface; i++) {
		MFace *mf=3D &dlm->mface[i];
	=09
		if (mf->v3) {
			int nmode=3D mf->v4?GL_QUADS:GL_TRIANGLES;
		=09
			if (nmode!=3Dlmode) {
				glEnd();
				glBegin(lmode=3D nmode);
			}
		=09
			/* rick: state changes mess performance up at the =
moment */
			/*
			if (drawsmooth) {
				int nshademodel=3D (mf->flag&ME_SMOOTH)?GL_=
SMOOTH:GL_FLAT;

				if (nshademodel!=3Dlshademodel) {
					glEnd();
					glShadeModel(lshademodel=3D =
nshademodel);
					glBegin(lmode);
				}
		=09
				if (mf->mat_nr!=3Dlmat_nr)
					set_gl_material((lmat_nr=3D =
mf->mat_nr)+1);
			}
			 */
		=09
			if (drawsmooth && lshademodel=3D=3DGL_FLAT)
				glNormal3fv(&nors[i*3]);
			=09
			PASSVERT(mf->v1);
			PASSVERT(mf->v2);
			PASSVERT(mf->v3);
			if (mf->v4)
				PASSVERT(mf->v4);
		}
	}
	glEnd();

	/* rick: done creating OpenGL display list */
	glEndList();
=09
#undef PASSVERT
}

As you can see, I've commented out the bits that deal with smooth shading =
and materials. I've done this because if there are a lot of state changes =
while compiling / drawing the display list a lot of the performance is =
lost. In the final version the materials / smooth shading should work; =
display lists allow you to do everything that you could normally do.

The problem is that that the state changes have to be grouped together, so =
that there are a minimal number of changes. I'm currently figuring out the =
best way to do this and will be asking on some OpenGL forums and the Apple =
OpenGL mailing list (mac-opengl). I think that these optimisations will =
probably be similar for most implementations.

Also note that with Catmull-Clark subdivision you end up with all the =
faces as quads, so there are no changes between glBegin(GL_TRIANGLES) and =
glBegin(GL_QUADS). For generic meshes I guess I'm going to have to sort =
between triangles and quads as well otherwise there will be a lot of calls =
to glEnd / glBegin.

r i c k