Example #1
0
void InMapDraw_QuadDrawer::DrawQuad(int x, int y)
{
	int drawQuadsX = imd->drawQuadsX;
	CInMapDraw::DrawQuad* dq = &imd->drawQuads[y * drawQuadsX + x];

	va->EnlargeArrays(dq->points.size()*12,0,VA_SIZE_TC);
	//! draw point markers
	for (std::list<CInMapDraw::MapPoint>::iterator pi = dq->points.begin(); pi != dq->points.end(); ++pi) {
		if (pi->MaySee(imd)) {
			float3 pos = pi->pos;
			float3 dif(pos - camera->pos);
			dif.ANormalize();
			float3 dir1(dif.cross(UpVector));
			dir1.ANormalize();
			float3 dir2(dif.cross(dir1));

			unsigned char col[4];
			col[0] = pi->color[0];
			col[1] = pi->color[1];
			col[2] = pi->color[2];
			col[3] = 200;

			float size = 6;
			float3 pos1 = pos;
			pos1.y += 5.0f;
			float3 pos2 = pos1;
			pos2.y += 100.0f;

			va->AddVertexQTC(pos1 - dir1 * size,               0.25f, 0, col);
			va->AddVertexQTC(pos1 + dir1 * size,               0.25f, 1, col);
			va->AddVertexQTC(pos1 + dir1 * size + dir2 * size, 0.00f, 1, col);
			va->AddVertexQTC(pos1 - dir1 * size + dir2 * size, 0.00f, 0, col);

			va->AddVertexQTC(pos1 - dir1 * size,               0.75f, 0, col);
			va->AddVertexQTC(pos1 + dir1 * size,               0.75f, 1, col);
			va->AddVertexQTC(pos2 + dir1 * size,               0.75f, 1, col);
			va->AddVertexQTC(pos2 - dir1 * size,               0.75f, 0, col);

			va->AddVertexQTC(pos2 - dir1 * size,               0.25f, 0, col);
			va->AddVertexQTC(pos2 + dir1 * size,               0.25f, 1, col);
			va->AddVertexQTC(pos2 + dir1 * size - dir2 * size, 0.00f, 1, col);
			va->AddVertexQTC(pos2 - dir1 * size - dir2 * size, 0.00f, 0, col);

			if (pi->label.size() > 0) {
				font->SetTextColor(pi->color[0]/255.0f, pi->color[1]/255.0f, pi->color[2]/255.0f, 1.0f); //FIXME (overload!)
				font->glWorldPrint(pos2 + UpVector * 6, 26.0f, pi->label);
			}
		}
	}

	lineva->EnlargeArrays(dq->lines.size()*2,0,VA_SIZE_C);
	//! draw line markers
	for (std::list<CInMapDraw::MapLine>::iterator li = dq->lines.begin(); li != dq->lines.end(); ++li) {
		if (li->MaySee(imd)) {
			lineva->AddVertexQC(li->pos - (li->pos - camera->pos).ANormalize() * 26, li->color);
			lineva->AddVertexQC(li->pos2 - (li->pos2 - camera->pos).ANormalize() * 26, li->color);
		}
	}
}
Example #2
0
void InMapDraw_QuadDrawer::DrawQuad(int x, int y)
{
	const int drawQuadsX = imd->drawQuadsX;
	CInMapDraw::DrawQuad* dq = &imd->drawQuads[y * drawQuadsX + x];

	va->EnlargeArrays(dq->points.size()*12,0,VA_SIZE_TC);
	//! draw point markers
	for (std::list<CInMapDraw::MapPoint>::iterator pi = dq->points.begin(); pi != dq->points.end(); ++pi) {
		if (pi->MaySee(imd)) {
			const float3 pos = pi->pos;
			const float3 dif = (pos - camera->pos).ANormalize();
			const float3 dir1 = (dif.cross(UpVector)).ANormalize();
			const float3 dir2 = (dif.cross(dir1));

			const unsigned char col[4] = {
				pi->color[0],
				pi->color[1],
				pi->color[2],
				200
			};

			const float size = 6.0f;
			const float3 pos1(pos.x,  pos.y  +   5.0f, pos.z);
			const float3 pos2(pos1.x, pos1.y + 100.0f, pos1.z);

			va->AddVertexQTC(pos1 - dir1 * size,               0.25f, 0, col);
			va->AddVertexQTC(pos1 + dir1 * size,               0.25f, 1, col);
			va->AddVertexQTC(pos1 + dir1 * size + dir2 * size, 0.00f, 1, col);
			va->AddVertexQTC(pos1 - dir1 * size + dir2 * size, 0.00f, 0, col);

			va->AddVertexQTC(pos1 - dir1 * size,               0.75f, 0, col);
			va->AddVertexQTC(pos1 + dir1 * size,               0.75f, 1, col);
			va->AddVertexQTC(pos2 + dir1 * size,               0.75f, 1, col);
			va->AddVertexQTC(pos2 - dir1 * size,               0.75f, 0, col);

			va->AddVertexQTC(pos2 - dir1 * size,               0.25f, 0, col);
			va->AddVertexQTC(pos2 + dir1 * size,               0.25f, 1, col);
			va->AddVertexQTC(pos2 + dir1 * size - dir2 * size, 0.00f, 1, col);
			va->AddVertexQTC(pos2 - dir1 * size - dir2 * size, 0.00f, 0, col);

			if (!pi->label.empty()) {
				visLabels->push_back(&*pi);
			}
		}
	}

	lineva->EnlargeArrays(dq->lines.size() * 2, 0, VA_SIZE_C);
	//! draw line markers
	for (std::list<CInMapDraw::MapLine>::iterator li = dq->lines.begin(); li != dq->lines.end(); ++li) {
		if (li->MaySee(imd)) {
			lineva->AddVertexQC(li->pos - (li->pos - camera->pos).ANormalize() * 26, li->color);
			lineva->AddVertexQC(li->pos2 - (li->pos2 - camera->pos).ANormalize() * 26, li->color);
		}
	}
}
void InMapDraw_QuadDrawer::DrawPoint(const CInMapDrawModel::MapPoint* point) const
{
	const float3& pos = point->GetPos();
	const float3 dif = (pos - camera->GetPos()).ANormalize();
	const float3 dir1 = (dif.cross(UpVector)).ANormalize();
	const float3 dir2 = (dif.cross(dir1));


	const unsigned char* color = point->IsBySpectator() ? color4::white : teamHandler->Team(point->GetTeamID())->color;
	const unsigned char col[4] = {
		color[0],
		color[1],
		color[2],
		200
	};

	const float size = 6.0f;
	const float3 pos1(pos.x,  pos.y  +   5.0f, pos.z);
	const float3 pos2(pos1.x, pos1.y + 100.0f, pos1.z);

	pointsVa->AddVertexQTC(pos1 - dir1 * size,               0.25f, 0, col);
	pointsVa->AddVertexQTC(pos1 + dir1 * size,               0.25f, 1, col);
	pointsVa->AddVertexQTC(pos1 + dir1 * size + dir2 * size, 0.00f, 1, col);
	pointsVa->AddVertexQTC(pos1 - dir1 * size + dir2 * size, 0.00f, 0, col);

	pointsVa->AddVertexQTC(pos1 - dir1 * size,               0.75f, 0, col);
	pointsVa->AddVertexQTC(pos1 + dir1 * size,               0.75f, 1, col);
	pointsVa->AddVertexQTC(pos2 + dir1 * size,               0.75f, 1, col);
	pointsVa->AddVertexQTC(pos2 - dir1 * size,               0.75f, 0, col);

	pointsVa->AddVertexQTC(pos2 - dir1 * size,               0.25f, 0, col);
	pointsVa->AddVertexQTC(pos2 + dir1 * size,               0.25f, 1, col);
	pointsVa->AddVertexQTC(pos2 + dir1 * size - dir2 * size, 0.00f, 1, col);
	pointsVa->AddVertexQTC(pos2 - dir1 * size - dir2 * size, 0.00f, 0, col);

	if (!point->GetLabel().empty()) {
		visibleLabels->push_back(point);
	}
}
Example #4
0
void CAdvWater::Draw(bool useBlending)
{
	if (!mapInfo->water.forceRendering && (readmap->currMinHeight > 1.0f)) {
		return;
	}

	float3 base = camera->CalcPixelDir(globalRendering->viewPosX, globalRendering->viewSizeY);
	float3 dv   = camera->CalcPixelDir(globalRendering->viewPosX, 0) - camera->CalcPixelDir(globalRendering->viewPosX, globalRendering->viewSizeY);
	float3 dh   = camera->CalcPixelDir(globalRendering->viewPosX + globalRendering->viewSizeX, 0) - camera->CalcPixelDir(globalRendering->viewPosX, 0);

	float3 xbase;
	const int numDivs = 20;

	base *= numDivs;
	float maxY = -0.1f;
	float yInc = 1.0f / numDivs;
	float screenY = 1;

	unsigned char col[4];
	col[0] = (unsigned char)(waterSurfaceColor.x * 255);
	col[1] = (unsigned char)(waterSurfaceColor.y * 255);
	col[2] = (unsigned char)(waterSurfaceColor.z * 255);

	glDisable(GL_ALPHA_TEST);
	if (useBlending) {
		glEnable(GL_BLEND);
	} else {
		glDisable(GL_BLEND);
	}
	glDepthMask(0);
	glActiveTextureARB(GL_TEXTURE1_ARB);
		glBindTexture(GL_TEXTURE_2D, bumpTexture);
		GLfloat plan[] = {0.02f, 0, 0, 0};
		glTexGeni(GL_S,GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
		glTexGenfv(GL_S,GL_EYE_PLANE, plan);
		glEnable(GL_TEXTURE_GEN_S);
			
		GLfloat plan2[] = {0, 0, 0.02f, 0};
		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
		glTexGenfv(GL_T, GL_EYE_PLANE, plan2);
		glEnable(GL_TEXTURE_GEN_T);
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glBindTexture(GL_TEXTURE_2D, reflectTexture);

	glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, waterFP);
	glEnable(GL_FRAGMENT_PROGRAM_ARB);

	float3 forward = camera->forward;
	forward.y = 0;
	forward.ANormalize();

	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, forward.z,  forward.x, 0, 0);
	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, -forward.x, forward.z, 0, 0);

	CVertexArray* va = GetVertexArray();
	va->Initialize();
	va->EnlargeArrays(5*numDivs*(numDivs + 1)*2, 5*numDivs, VA_SIZE_TC); //! alloc room for all vertexes and strips
	float3 dir, zpos;
	for (int a = 0; a < 5; ++a) { //! CAUTION: loop count must match EnlargeArrays above
		bool maxReached = false;
		for (int y = 0; y < numDivs; ++y) {
			dir = base;
			dir.ANormalize();

			if (dir.y >= maxY) {
				maxReached = true;
				break;
			}

			xbase = base;
			for (int x = 0; x < numDivs + 1; ++x) { //! CAUTION: loop count must match EnlargeArrays above
				dir = xbase + dv;
				dir.ANormalize();
				zpos = camera->pos + dir*(camera->pos.y / -dir.y);
				zpos.y = sin(zpos.z*0.1f + gs->frameNum*0.06f)*0.06f + 0.05f;
				col[3] = (unsigned char)((0.8f + 0.7f*dir.y)*255);
				va->AddVertexQTC(zpos, x*(1.0f/numDivs), screenY - yInc, col);

				dir = xbase;
				dir.ANormalize();
				zpos = camera->pos + dir*(camera->pos.y / -dir.y);
				zpos.y = sin(zpos.z*0.1f + gs->frameNum*0.06f)*0.06f + 0.05f;
				col[3] = (unsigned char)((0.8f + 0.7f*dir.y)*255);
				va->AddVertexQTC(zpos, x*(1.0f/numDivs), screenY, col);

				xbase += dh;
			}
			va->EndStripQ();
			base += dv;
			screenY -= yInc;
		}
		if (!maxReached) {
			break;
		}
		dv   *= 0.5f;
		maxY *= 0.5f;
		yInc *= 0.5f;
	}
	va->DrawArrayTC(GL_TRIANGLE_STRIP);

	glDepthMask(1);
	glDisable(GL_FRAGMENT_PROGRAM_ARB);
	glActiveTextureARB(GL_TEXTURE1_ARB);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
	glActiveTextureARB(GL_TEXTURE0_ARB);

	if (!useBlending) { // for translucent stuff like water, the default mode is blending and alpha testing enabled
		glEnable(GL_BLEND);
	}
}
void CProjectileDrawer::UpdatePerlin() {
	perlinFB.Bind();
	glViewport(perlintex->ixstart, perlintex->iystart, 128, 128);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0, 1,  0, 1,  -1, 1);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glDisable(GL_DEPTH_TEST);
	glDepthMask(GL_FALSE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_FOG);

	unsigned char col[4];
	float time = globalRendering->lastFrameTime * gs->speedFactor * 3;
	float speed = 1.0f;
	float size = 1.0f;

	for (int a = 0; a < 4; ++a) {
		perlinBlend[a] += time * speed;
		if (perlinBlend[a] > 1) {
			unsigned int temp = perlinTex[a * 2];
			perlinTex[a * 2    ] = perlinTex[a * 2 + 1];
			perlinTex[a * 2 + 1] = temp;

			GenerateNoiseTex(perlinTex[a * 2 + 1], 16);
			perlinBlend[a] -= 1;
		}

		float tsize = 8.0f / size;

		if (a == 0)
			glDisable(GL_BLEND);

		CVertexArray* va = GetVertexArray();
		va->Initialize();
		va->CheckInitSize(4 * VA_SIZE_TC, 0);

		for (int b = 0; b < 4; ++b)
			col[b] = int((1.0f - perlinBlend[a]) * 16 * size);

		glBindTexture(GL_TEXTURE_2D, perlinTex[a * 2]);
		va->AddVertexQTC(float3(0, 0, 0), 0,         0, col);
		va->AddVertexQTC(float3(0, 1, 0), 0,     tsize, col);
		va->AddVertexQTC(float3(1, 1, 0), tsize, tsize, col);
		va->AddVertexQTC(float3(1, 0, 0), tsize,     0, col);
		va->DrawArrayTC(GL_QUADS);

		if (a == 0)
			glEnable(GL_BLEND);

		va = GetVertexArray();
		va->Initialize();
		va->CheckInitSize(4 * VA_SIZE_TC, 0);

		for (int b = 0; b < 4; ++b)
			col[b] = int(perlinBlend[a] * 16 * size);

		glBindTexture(GL_TEXTURE_2D, perlinTex[a * 2 + 1]);
		va->AddVertexQTC(float3(0, 0, 0),     0,     0, col);
		va->AddVertexQTC(float3(0, 1, 0),     0, tsize, col);
		va->AddVertexQTC(float3(1, 1, 0), tsize, tsize, col);
		va->AddVertexQTC(float3(1, 0, 0), tsize,     0, col);
		va->DrawArrayTC(GL_QUADS);

		speed *= 0.6f;
		size *= 2;
	}

	perlinFB.Unbind();
	glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_DEPTH_TEST);
	glDepthMask(GL_TRUE);

	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}
void InMapDraw_QuadDrawer::DrawQuad(int x, int y)
{
	int drawQuadsX = imd->drawQuadsX;
	CInMapDraw::DrawQuad* dq = &imd->drawQuads[y * drawQuadsX + x];

	va->EnlargeArrays(dq->points.size()*12,0,VA_SIZE_TC);
	// draw point markers
	for (std::list<CInMapDraw::MapPoint>::iterator pi = dq->points.begin(); pi != dq->points.end(); ++pi) {
		const int allyteam = pi->senderAllyTeam;
		const bool spec = pi->senderSpectator;
		const bool allied = (gs->Ally(gu->myAllyTeam, allyteam) && gs->Ally(allyteam, gu->myAllyTeam));
		const bool maySee = (gu->spectating || (!spec && allied) || imd->drawAll);

		if (maySee) {
			float3 pos = pi->pos;
			float3 dif(pos - camera->pos);
			float camDist = dif.Length();
			dif /= camDist;
			float3 dir1(dif.cross(UpVector));
			dir1.Normalize();
			float3 dir2(dif.cross(dir1));

			unsigned char col[4];
			col[0] = pi->color[0];
			col[1] = pi->color[1];
			col[2] = pi->color[2];
			col[3] = 200;

			float size = 6;
			float3 pos1 = pos;
			float3 pos2 = pos1;
			pos2.y += 100;

			va->AddVertexQTC(pos1 - dir1 * size,               0.25f, 0, col);
			va->AddVertexQTC(pos1 + dir1 * size,               0.25f, 1, col);
			va->AddVertexQTC(pos1 + dir1 * size + dir2 * size, 0.00f, 1, col);
			va->AddVertexQTC(pos1 - dir1 * size + dir2 * size, 0.00f, 0, col);

			va->AddVertexQTC(pos1 - dir1 * size,               0.75f, 0, col);
			va->AddVertexQTC(pos1 + dir1 * size,               0.75f, 1, col);
			va->AddVertexQTC(pos2 + dir1 * size,               0.75f, 1, col);
			va->AddVertexQTC(pos2 - dir1 * size,               0.75f, 0, col);

			va->AddVertexQTC(pos2 - dir1 * size,               0.25f, 0, col);
			va->AddVertexQTC(pos2 + dir1 * size,               0.25f, 1, col);
			va->AddVertexQTC(pos2 + dir1 * size - dir2 * size, 0.00f, 1, col);
			va->AddVertexQTC(pos2 - dir1 * size - dir2 * size, 0.00f, 0, col);

			if (pi->label.size() > 0) {
				glPushMatrix();
				glTranslatef3(pi->pos + UpVector * 105);
				glScalef(1200, 1200, 1200);
				glColor4ub(pi->color[0], pi->color[1], pi->color[2], 250);
				font->glWorldPrint(pi->label.c_str());
				glPopMatrix();
			}
		}
	}

	va->EnlargeArrays(dq->lines.size()*2,0,VA_SIZE_C);
	// draw line markers
	for (std::list<CInMapDraw::MapLine>::iterator li = dq->lines.begin(); li != dq->lines.end(); ++li) {
		const int allyteam = li->senderAllyTeam;
		const bool spec = li->senderSpectator;
		const bool allied = (gs->Ally(gu->myAllyTeam, allyteam) && gs->Ally(allyteam, gu->myAllyTeam));
		const bool maySee = (gu->spectating || (!spec && allied) || imd->drawAll);

		if (maySee) {
			lineva->AddVertexQC(li->pos - (li->pos - camera->pos).ANormalize() * 26, li->color);
			lineva->AddVertexQC(li->pos2 - (li->pos2 - camera->pos).ANormalize() * 26, li->color);
		}
	}
}
void CGroundDecalHandler::Draw(void)
{
	if (!drawDecals) {
		return;
	}

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(-10, -200);
	glDepthMask(0);

	glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, readmap->GetShadingTexture());
		SetTexGen(1.0f / (gs->pwr2mapx * SQUARE_SIZE), 1.0f / (gs->pwr2mapy * SQUARE_SIZE), 0, 0);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
	CBaseGroundDrawer *gd = readmap->GetGroundDrawer();
	if (gd->DrawExtraTex()) {
			glActiveTextureARB(GL_TEXTURE3_ARB);
			glEnable(GL_TEXTURE_2D);
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_ADD_SIGNED_ARB);
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB,GL_MODULATE);
			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB,GL_PREVIOUS_ARB);
			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_ALPHA_ARB,GL_TEXTURE);
			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);

			SetTexGen(1.0f/(gs->pwr2mapx*SQUARE_SIZE),1.0f/(gs->pwr2mapy*SQUARE_SIZE),0,0);

			glBindTexture(GL_TEXTURE_2D, gd->infoTex);
	}
	glActiveTextureARB(GL_TEXTURE0_ARB);


	if (shadowHandler && shadowHandler->drawShadows) {
		glActiveTextureARB(GL_TEXTURE2_ARB);
			glEnable(GL_TEXTURE_2D);
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			glBindTexture(GL_TEXTURE_2D, shadowHandler->shadowTexture);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
			glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
		glActiveTextureARB(GL_TEXTURE0_ARB);

		if (readmap->GetShadingTexture() == 0) {
			glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, decalFPsm3);
		} else {
			// also used for SM3 maps with baked lighting
			glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, decalFPsmf);
		}
		glEnable(GL_FRAGMENT_PROGRAM_ARB);
		glBindProgramARB(GL_VERTEX_PROGRAM_ARB, decalVP);
		glEnable(GL_VERTEX_PROGRAM_ARB);

		const float3 ac = mapInfo->light.groundAmbientColor * (210.0f / 255.0f);

		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 10, 1.0f / (gs->pwr2mapx * SQUARE_SIZE), 1.0f / (gs->pwr2mapy * SQUARE_SIZE), 0, 1);
		glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 10, ac.x, ac.y, ac.z, 1);
		glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 11, 0, 0, 0, mapInfo->light.groundShadowDensity);
		glMatrixMode(GL_MATRIX0_ARB);
		glLoadMatrixf(shadowHandler->shadowMatrix.m);
		glMatrixMode(GL_MODELVIEW);
	}

	// create and draw the quads for each building decal
	for (std::vector<BuildingDecalType*>::iterator bdti = buildingDecalTypes.begin(); bdti != buildingDecalTypes.end(); ++bdti) {
		BuildingDecalType* bdt = *bdti;

		if (!bdt->buildingDecals.empty()) {

			glBindTexture(GL_TEXTURE_2D, bdt->texture);

			decalsToDraw.clear();
			{
				GML_STDMUTEX_LOCK(decal); // Draw

				set<BuildingGroundDecal*>::iterator bgdi = bdt->buildingDecals.begin();

				while (bgdi != bdt->buildingDecals.end()) {
					BuildingGroundDecal* decal = *bgdi;

					if (decal->owner && decal->owner->buildProgress >= 0) {
						decal->alpha = decal->owner->buildProgress;
					} else if (!decal->gbOwner) {
						decal->alpha -= decal->alphaFalloff * globalRendering->lastFrameTime * gs->speedFactor;
					}

					if (decal->alpha < 0.0f) {
						// make sure RemoveBuilding() won't try to modify this decal
						if (decal->owner) {
							decal->owner->buildingDecal = 0;
						}

						delete decal;

						set<BuildingGroundDecal*>::iterator next(bgdi); ++next;
						bdt->buildingDecals.erase(bgdi);
						bgdi = next;

						continue;
					}

					if (!decal->owner || (decal->owner->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_PREVLOS)) || gu->spectatingFullView) {
						decalsToDraw.push_back(decal);
					}

					bgdi++;
				}
			}

			for(std::vector<BuildingGroundDecal*>::iterator di = decalsToDraw.begin(); di != decalsToDraw.end(); ++di) {
				BuildingGroundDecal *decal = *di;
				if (camera->InView(decal->pos, decal->radius)) {
					DrawBuildingDecal(decal);
				}
			}

			//glBindTexture(GL_TEXTURE_2D, 0);
		}
	}


	if (shadowHandler && shadowHandler->drawShadows) {
		glDisable(GL_FRAGMENT_PROGRAM_ARB);
		glDisable(GL_VERTEX_PROGRAM_ARB);

		glActiveTextureARB(GL_TEXTURE2_ARB);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
			glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
			glDisable(GL_TEXTURE_2D);
		glActiveTextureARB(GL_TEXTURE1_ARB);

		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);

		glActiveTextureARB(GL_TEXTURE0_ARB);
	}

	glPolygonOffset(-10, -20);

	unsigned char color[4] = {255, 255, 255, 255};
	unsigned char color2[4] = {255, 255, 255, 255};

	{
		GML_STDMUTEX_LOCK(track); // Draw
		// Delayed addition of new tracks
		for (std::vector<TrackToAdd>::iterator ti = tracksToBeAdded.begin(); ti != tracksToBeAdded.end(); ++ti) {
			TrackToAdd *tta = &(*ti);
			if(tta->ts->owner == NULL) {
				delete tta->tp;
				if(tta->unit == NULL)
					tracksToBeDeleted.push_back(tta->ts);
				continue; // unit removed
			}

			CUnit *unit = tta->unit;
			if(unit == NULL) {
				unit = tta->ts->owner;
				trackTypes[unit->unitDef->trackType]->tracks.insert(tta->ts);
			}

			TrackPart *tp = tta->tp;
			//if the unit is moving in a straight line only place marks at half the rate by replacing old ones
			bool replace = false;
			if(unit->myTrack->parts.size()>1) {
				list<TrackPart *>::iterator pi = --unit->myTrack->parts.end();
				list<TrackPart *>::iterator pi2 = pi--;
				if(((tp->pos1+(*pi)->pos1)*0.5f).SqDistance((*pi2)->pos1)<1)
					replace = true;
			}
			if(replace) {
				delete unit->myTrack->parts.back();
				unit->myTrack->parts.back() = tp;
			}
			else {
				unit->myTrack->parts.push_back(tp);
			}
		}
		tracksToBeAdded.clear();
	}

	for (std::vector<UnitTrackStruct *>::iterator ti = tracksToBeDeleted.begin(); ti != tracksToBeDeleted.end(); ++ti) {
		delete *ti;
	}
	tracksToBeDeleted.clear();

	tracksToBeCleaned.clear();

	// create and draw the unit footprint quads
	for (std::vector<TrackType*>::iterator tti = trackTypes.begin(); tti != trackTypes.end(); ++tti) {
		TrackType* tt = *tti;
		if (!tt->tracks.empty()) {
			set<UnitTrackStruct*>::iterator utsi = tt->tracks.begin();

			CVertexArray* va = GetVertexArray();
			va->Initialize();
			glBindTexture(GL_TEXTURE_2D, tt->texture);

			while (utsi != tt->tracks.end()) {
				UnitTrackStruct* track = *utsi;
				if (track->parts.empty()) {
					tracksToBeCleaned.push_back(TrackToClean(track, &(tt->tracks)));
					continue;
				}
				if (track->parts.front()->creationTime < gs->frameNum - track->lifeTime) {
					tracksToBeCleaned.push_back(TrackToClean(track, &(tt->tracks)));
				}
				if (camera->InView((track->parts.front()->pos1 + track->parts.back()->pos1) * 0.5f, track->parts.front()->pos1.distance(track->parts.back()->pos1) + 500)) {
					list<TrackPart *>::iterator ppi = track->parts.begin();
					color2[3] = std::max(0, track->trackAlpha - (int) ((gs->frameNum - (*ppi)->creationTime) * track->alphaFalloff));

					va->EnlargeArrays(track->parts.size()*4,0,VA_SIZE_TC);
					for (list<TrackPart *>::iterator pi = ++track->parts.begin(); pi != track->parts.end(); ++pi) {
						color[3] = std::max(0, track->trackAlpha - (int) ((gs->frameNum - (*ppi)->creationTime) * track->alphaFalloff));
						if ((*pi)->connected) {
							va->AddVertexQTC((*ppi)->pos1, (*ppi)->texPos, 0, color2);
							va->AddVertexQTC((*ppi)->pos2, (*ppi)->texPos, 1, color2);
							va->AddVertexQTC((*pi)->pos2, (*pi)->texPos, 1, color);
							va->AddVertexQTC((*pi)->pos1, (*pi)->texPos, 0, color);
						}
						color2[3] = color[3];
						ppi = pi;
					}
				}
				utsi++;
			}
			va->DrawArrayTC(GL_QUADS);
		}
	}

	{
		GML_STDMUTEX_LOCK(track); // Draw
		// Cleanup old tracks
		for (std::vector<TrackToClean>::iterator ti = tracksToBeCleaned.begin(); ti != tracksToBeCleaned.end(); ++ti) {
			TrackToClean *ttc = &(*ti);
			UnitTrackStruct *track = ttc->track;
			while (!track->parts.empty() && track->parts.front()->creationTime < gs->frameNum - track->lifeTime) {
				delete track->parts.front();
				track->parts.pop_front();
			}
			if (track->parts.empty()) {
				if (track->owner) {
					track->owner->myTrack = 0;
					track->owner = 0;
				}
				ttc->tracks->erase(track);
				tracksToBeDeleted.push_back(track);
			}
		}
	}

	glBindTexture(GL_TEXTURE_2D, scarTex);
	glPolygonOffset(-10, -400);

	scarsToBeChecked.clear();
	{
		GML_STDMUTEX_LOCK(scar); // Draw

		for (std::vector<Scar*>::iterator si = scarsToBeAdded.begin(); si != scarsToBeAdded.end(); ++si)
			scarsToBeChecked.push_back(*si);

		scarsToBeAdded.clear();
	}

	for (std::vector<Scar*>::iterator si = scarsToBeChecked.begin(); si != scarsToBeChecked.end(); ++si) {
		Scar* s = *si;
		TestOverlaps(s);

		int x1 = s->x1 / 16;
		int x2 = min(scarFieldX - 1, s->x2 / 16);
		int y1 = s->y1 / 16;
		int y2 = min(scarFieldY - 1, s->y2 / 16);

		for (int y = y1; y <= y2; ++y) {
			for (int x = x1; x <= x2; ++x) {
				std::set<Scar*>* quad = &scarField[y * scarFieldX + x];
				quad->insert(s);
			}
		}

		scars.push_back(s); 
	}

	// create and draw the 16x16 quads for each ground scar
	for (std::list<Scar*>::iterator si = scars.begin(); si != scars.end(); ) {
		Scar* scar = *si;

		if (scar->lifeTime < gs->frameNum) {
			RemoveScar(*si, false);
			si = scars.erase(si);
			continue;
		}

		if (camera->InView(scar->pos, scar->radius + 16)) {
			DrawGroundScar(scar, groundScarAlphaFade);
		}

		++si;
	}


	glDisable(GL_POLYGON_OFFSET_FILL);
	glDisable(GL_BLEND);

	glActiveTextureARB(GL_TEXTURE1_ARB);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glActiveTextureARB(GL_TEXTURE3_ARB); //! infotex
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glActiveTextureARB(GL_TEXTURE0_ARB);
}