Sign in to follow this  
cozzie

Why not blend your whole scene?

Recommended Posts

Hi, When I was trying to optimize my render::Scene function of my 3d engine, I was thinking. Why not render every object with glBlending enabled. Is it an option to include an alpha layer to every texture you use, and use the textures that are not transparent to draw the non transparent objects? What will give better performance/reliability? (it would mean that there are no separate loops for transparent and non-transparent materials, and you wouldn't need to enable/disable blending) Doing this would mean you'd have to sort all objects by Z value, to make sure objects don't mess up eachother. What I'm doing now is make a list of objects per material, then draw the objects with that material (material includes texture id). After rendering all non transparent object I turn on blending and render the transparent objects from back to front sorted. Will the performance winning when not enabling/disabling glBlend and not having extra loops do any good? All suggestions to my renderscene function are welcome ;-) Here's my current renderscene function:
int GLscene::Render(int width, int height)
{
	static int mc, oc;
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();						

	xTrans = -cam->pos.x;
	yTrans = -cam->pos.y;
	zTrans = -cam->pos.z;
	sceneRoty = 360 - cam->rot.y;
	sceneRotx = 360 - cam->rot.x;

	glRotatef(sceneRotx, 1, 0, 0);
	glRotatef(sceneRoty, 0, 1, 0);
	glTranslatef(xTrans, yTrans, zTrans);

	frustum.CalculateFrustum();

	glPushMatrix();
	for(c=0;c<nr_lights;c++)
	{
		glLightfv(lights[c].id, GL_POSITION, lights[c].pos);
		if(lights[c].spot) glLightfv(lights[c].id, GL_SPOT_DIRECTION, lights[c].spotDirection);
	}

	glPopMatrix();

	for(mc=0;mc<m_trans;mc++)
	{
		materials[matIndex[mc]].Select(textures.texture);
		for(oc=0;oc<materials[matIndex[mc]].nr_objects;oc++)
		{
			if(frustum.ObjectInFrustum(
				objects[materials[matIndex[mc]].objectIndex[oc]].pos.x,
				objects[materials[matIndex[mc]].objectIndex[oc]].pos.y,
				objects[materials[matIndex[mc]].objectIndex[oc]].pos.z,
				objects[materials[matIndex[mc]].objectIndex[oc]].radius))
			{
				glPushMatrix();
				glTranslatef(objects[materials[matIndex[mc]].objectIndex[oc]].pos.x, 
					         objects[materials[matIndex[mc]].objectIndex[oc]].pos.y, 
							 objects[materials[matIndex[mc]].objectIndex[oc]].pos.z);

				glRotatef(objects[materials[matIndex[mc]].objectIndex[oc]].rot.x, 1, 0, 0);
				glRotatef(objects[materials[matIndex[mc]].objectIndex[oc]].rot.y, 0, 1, 0);
				glRotatef(objects[materials[matIndex[mc]].objectIndex[oc]].rot.z, 0, 0, 1);

				glVertexPointer(3,GL_FLOAT,0, (float *)objects[materials[matIndex[mc]].objectIndex[oc]].vertices);
				glTexCoordPointer(2,GL_FLOAT,0, (float *)objects[materials[matIndex[mc]].objectIndex[oc]].texCoords);
				glNormalPointer(GL_FLOAT,0, (float *)objects[materials[matIndex[mc]].objectIndex[oc]].normals);

				glDrawElements(GL_TRIANGLES, 
							   objects[materials[matIndex[mc]].objectIndex[oc]].nr_faces*3,
							   GL_UNSIGNED_INT,
							   (unsigned int *)objects[materials[matIndex[mc]].objectIndex[oc]].faces);

				glPopMatrix();
			}
		}
	}

//	transparant material groups

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDepthMask(GL_FALSE);

	for(mc=m_trans;mc<nr_materials;mc++)
	{
		materials[matIndex[mc]].Select(textures.texture);
		for(oc=0;oc<materials[matIndex[mc]].nr_objects;oc++)
		{
			if(frustum.ObjectInFrustum(
				objects[materials[matIndex[mc]].objectIndex[oc]].pos.x,
				objects[materials[matIndex[mc]].objectIndex[oc]].pos.y,
				objects[materials[matIndex[mc]].objectIndex[oc]].pos.z,
				objects[materials[matIndex[mc]].objectIndex[oc]].radius))
			{
				glPushMatrix();
				glTranslatef(objects[materials[matIndex[mc]].objectIndex[oc]].pos.x, 
						     objects[materials[matIndex[mc]].objectIndex[oc]].pos.y, 
							 objects[materials[matIndex[mc]].objectIndex[oc]].pos.z);

				glRotatef(objects[materials[matIndex[mc]].objectIndex[oc]].rot.x, 1, 0, 0);
				glRotatef(objects[materials[matIndex[mc]].objectIndex[oc]].rot.y, 0, 1, 0);
				glRotatef(objects[materials[matIndex[mc]].objectIndex[oc]].rot.z, 0, 0, 1);

				glVertexPointer(3,GL_FLOAT,0, (float *)objects[materials[matIndex[mc]].objectIndex[oc]].vertices);
				glTexCoordPointer(2,GL_FLOAT,0, (float *)objects[materials[matIndex[mc]].objectIndex[oc]].texCoords);
				glNormalPointer(GL_FLOAT,0, (float *)objects[materials[matIndex[mc]].objectIndex[oc]].normals);

				glDrawElements(GL_TRIANGLES, 
							   objects[materials[matIndex[mc]].objectIndex[oc]].nr_faces*3,
							   GL_UNSIGNED_INT,
							   (unsigned int *)objects[materials[matIndex[mc]].objectIndex[oc]].faces);

				glPopMatrix();
			}
		}
	}
	glDepthMask(GL_TRUE);
	return true;
}

Share this post


Link to post
Share on other sites
With blending enabled, every pixel you write would be accompanied with an extra read from the framebuffer. Depending on how many pixels are actually written and overdrawn, it could (and probably will) really kill your bandwidth.

Share this post


Link to post
Share on other sites
Well actually, that will most likely kill your fillrate, since every pixel is drawn(because you would have to draw back to front, and any pixel could be translucent). A gl state switch is far less expensive than drawing everything blended. If you want to optimize your engine look into sorting by state. Here is a decent article on delphi3D. There are better ones just search gamedev articles.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this