Esempio n. 1
0
void CSMFReadMap::CreateSplatDetailTextures()
{
	if (!haveSplatTexture) {
		return;
	}
	
	CBitmap splatDistrTexBM;
	CBitmap splatDetailTexBM;

	// if the map supplies an intensity- AND a distribution-texture for
	// detail-splat blending, the regular detail-texture is not used
	if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) {
		// default detail-texture should be all-grey
		splatDetailTexBM.channels = 4;
		splatDetailTexBM.Alloc(1, 1);
		splatDetailTexBM.mem[0] = 127;
		splatDetailTexBM.mem[1] = 127;
		splatDetailTexBM.mem[2] = 127;
		splatDetailTexBM.mem[3] = 127;
	}

	if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) {
		splatDistrTexBM.channels = 4;
		splatDistrTexBM.Alloc(1, 1);
		splatDistrTexBM.mem[0] = 255;
		splatDistrTexBM.mem[1] = 0;
		splatDistrTexBM.mem[2] = 0;
		splatDistrTexBM.mem[3] = 0;
	}

	splatDetailTex = splatDetailTexBM.CreateTexture(true);
	splatDistrTex = splatDistrTexBM.CreateTexture(true);
}
Esempio n. 2
0
void CUnitDefHandler::SetUnitDefImage(const UnitDef* unitDef, const std::string& texName)
{
	if (unitDef->buildPic == NULL) {
		unitDef->buildPic = new UnitDefImage();
	} else {
		unitDef->buildPic->Free();
	}

	CBitmap bitmap;

	if (!texName.empty()) {
		bitmap.Load("unitpics/" + texName);
	}
	else {
		if (!LoadBuildPic("unitpics/" + unitDef->name + ".dds", bitmap) &&
		    !LoadBuildPic("unitpics/" + unitDef->name + ".png", bitmap) &&
		    !LoadBuildPic("unitpics/" + unitDef->name + ".pcx", bitmap) &&
		    !LoadBuildPic("unitpics/" + unitDef->name + ".bmp", bitmap)) {
			bitmap.Alloc(1, 1); // last resort
		}
	}

	const unsigned int texID = bitmap.CreateTexture(false);

	UnitDefImage* unitImage = unitDef->buildPic;
	unitImage->textureID = texID;
	unitImage->imageSizeX = bitmap.xsize;
	unitImage->imageSizeY = bitmap.ysize;
}
Esempio n. 3
0
void CBitmap::Blur(int iterations, float weight)
{
	if (type == BitmapTypeDDS) {
		return;
	}

	CBitmap* src = this;
	CBitmap* dst = new CBitmap();
	dst->channels = src->channels;
	dst->Alloc(xsize,ysize);

	for (int i=0; i < iterations; ++i){
		{
			int j,y,x;
//			Threading::OMPCheck();
//			This is currently used too early, OMP is not initialized here
//			#pragma omp parallel for private(j,x,y)
			for (y=0; y < ysize; y++) {
				for (x=0; x < xsize; x++) {
					for (j=0; j < channels; j++) {
						kernelBlur(dst, src->mem, x, y, j, weight);
					}
				}
			}
		}
		std::swap(src, dst);
	}

	if (dst == this) {
		// make sure we don't delete `this`
		std::swap(src, dst);
	}

	delete dst;
}
Esempio n. 4
0
void CBitmap::Blur(int iterations, float weight)
{
	if (type == BitmapTypeDDS) {
		return;
	}

	CBitmap* src = this;
	CBitmap* dst = new CBitmap();
	dst->channels = src->channels;
	dst->Alloc(xsize,ysize);

	for (int i=0; i < iterations; ++i){
		{
			for_mt(0, ysize, [&](const int y) {
				for (int x=0; x < xsize; x++) {
					for (int j=0; j < channels; j++) {
						kernelBlur(dst, src->mem, x, y, j, weight);
					}
				}
			});
		}
		std::swap(src, dst);
	}

	if (dst == this) {
		// make sure we don't delete `this`
		std::swap(src, dst);
	}

	delete dst;
}
Esempio n. 5
0
void glSaveTexture(const GLuint textureID, const char* filename)
{
	const GLenum target = GL_TEXTURE_2D;
	GLenum format = GL_RGBA8;
	int sizeX, sizeY;

	int bits = 0;
	{
		glBindTexture(GL_TEXTURE_2D, textureID);

		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sizeX);
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &sizeY);
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&format);

		GLint _cbits;
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &_cbits); bits += _cbits;
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &_cbits); bits += _cbits;
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &_cbits); bits += _cbits;
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &_cbits); bits += _cbits;
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH_SIZE, &_cbits); bits += _cbits;
	}
	assert(bits == 32);
	assert(format == GL_RGBA8);

	CBitmap bmp;
	bmp.Alloc(sizeX, sizeY, 4);
	glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, bmp.GetRawMem());
	bmp.Save(filename, false);
}
Esempio n. 6
0
bool CMouseCursor::LoadCursorImage(const string& name, ImageData& image)
{
	CFileHandler f(name);
	if (!f.FileExists()) {
		return false;
	}

	CBitmap b;
	if (!b.Load(name)) {
		LOG_L(L_ERROR, "CMouseCursor: Bad image file: %s", name.c_str());
		return false;
	}

	// hardcoded bmp transparency mask
	if (FileSystem::GetExtension(name) == "bmp") {
		b.SetTransparent(SColor(84, 84, 252));
	}

	if (hwCursor->NeedsYFlip()) {
		//WINDOWS
		b.ReverseYAxis();
		hwCursor->PushImage(b.xsize,b.ysize,&b.mem[0]);
	}else{
		//X11
		hwCursor->PushImage(b.xsize,b.ysize,&b.mem[0]);
		b.ReverseYAxis();
	}


	const int nx = next_power_of_2(b.xsize);
	const int ny = next_power_of_2(b.ysize);

	if (b.xsize != nx || b.ysize != ny) {
		CBitmap bn;
		bn.Alloc(nx, ny);
		bn.CopySubImage(b, 0, ny - b.ysize);

		image.texture = bn.CreateTexture();
		image.xOrigSize = b.xsize;
		image.yOrigSize = b.ysize;
		image.xAlignedSize = bn.xsize;
		image.yAlignedSize = bn.ysize;
	} else {
		image.texture = b.CreateTexture();
		image.xOrigSize = b.xsize;
		image.yOrigSize = b.ysize;
		image.xAlignedSize = b.xsize;
		image.yAlignedSize = b.ysize;
	}

	return true;
}
Esempio n. 7
0
void CSMFReadMap::CreateSplatDetailTextures()
{
	if (!haveSplatDetailDistribTexture)
		return;

	CBitmap splatDistrTexBM;
	CBitmap splatDetailTexBM;

	// if the map supplies an intensity- AND a distribution-texture for
	// detail-splat blending, the regular detail-texture is not used
	if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) {
		// default detail-texture should be all-grey
		splatDetailTexBM.channels = 4;
		splatDetailTexBM.AllocDummy(SColor(127,127,127,127));
	}

	if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) {
		splatDistrTexBM.channels = 4;
		splatDistrTexBM.AllocDummy(SColor(255,0,0,0));
	}

	splatDetailTex.SetRawTexID(splatDetailTexBM.CreateTexture(texAnisotropyLevels[true], true));
	splatDetailTex.SetRawSize(int2(splatDetailTexBM.xsize, splatDetailTexBM.ysize));

	splatDistrTex.SetRawTexID(splatDistrTexBM.CreateTexture(texAnisotropyLevels[true], true));
	splatDistrTex.SetRawSize(int2(splatDistrTexBM.xsize, splatDistrTexBM.ysize));

	// only load the splat detail normals if any of them are defined and present
	if (!haveSplatNormalDistribTexture)
		return;

	for (size_t i = 0; i < mapInfo->smf.splatDetailNormalTexNames.size(); i++) {
		if (i == NUM_SPLAT_DETAIL_NORMALS)
			break;

		CBitmap splatDetailNormalTextureBM;

		if (!splatDetailNormalTextureBM.Load(mapInfo->smf.splatDetailNormalTexNames[i])) {
			splatDetailNormalTextureBM.channels = 4;
			splatDetailNormalTextureBM.Alloc(1, 1);
			splatDetailNormalTextureBM.mem[0] = 127; // RGB is packed standard normal map
			splatDetailNormalTextureBM.mem[1] = 127;
			splatDetailNormalTextureBM.mem[2] = 255; // With a single upward (+Z) pointing vector
			splatDetailNormalTextureBM.mem[3] = 127; // Alpha is diffuse as in old-style detail textures
		}

		splatNormalTextures[i].SetRawTexID(splatDetailNormalTextureBM.CreateTexture(texAnisotropyLevels[true], true));
		splatNormalTextures[i].SetRawSize(int2(splatDetailNormalTextureBM.xsize, splatDetailNormalTextureBM.ysize));
	}

}
Esempio n. 8
0
CBitmap CBitmap::CreateRescaled(int newx, int newy) const
{
	newx = std::max(1, newx);
	newy = std::max(1, newy);

	CBitmap bm;
	bm.Alloc(newx, newy);

	const float dx = (float) xsize / newx;
	const float dy = (float) ysize / newy;

	float cy = 0;
	for (int y=0; y < newy; ++y) {
		const int sy = (int) cy;
		cy += dy;
		int ey = (int) cy;
		if (ey == sy) {
			ey = sy+1;
		}

		float cx = 0;
		for (int x=0; x < newx; ++x) {
			const int sx = (int) cx;
			cx += dx;
			int ex = (int) cx;
			if (ex == sx) {
				ex = sx + 1;
			}

			int r=0, g=0, b=0, a=0;
			for (int y2 = sy; y2 < ey; ++y2) {
				for (int x2 = sx; x2 < ex; ++x2) {
					const int index = (y2*xsize + x2) * 4;
					r += mem[index + 0];
					g += mem[index + 1];
					b += mem[index + 2];
					a += mem[index + 3];
				}
			}
			const int index = (y*bm.xsize + x) * 4;
			const int denom = (ex - sx) * (ey - sy);
			bm.mem[index + 0] = r / denom;
			bm.mem[index + 1] = g / denom;
			bm.mem[index + 2] = b / denom;
			bm.mem[index + 3] = a / denom;
		}
	}

	return bm;
}
Esempio n. 9
0
CBasicWater::CBasicWater()
{
	CBitmap waterTexBM;
	if (!waterTexBM.Load(mapInfo->water.texture)) {
		LOG_L(L_WARNING, "[%s] could not read water texture from file \"%s\"", __FUNCTION__, mapInfo->water.texture.c_str());

		// fallback
		waterTexBM.channels = 4;
		waterTexBM.Alloc(1, 1);
		waterTexBM.mem[0] =   0;
		waterTexBM.mem[1] =   0;
		waterTexBM.mem[2] = 255;
		waterTexBM.mem[3] = 255;
	}

	// create mipmapped texture
	textureID = waterTexBM.CreateTexture(true);
	displistID = GenWaterQuadsList(waterTexBM.xsize, waterTexBM.ysize);
}
Esempio n. 10
0
int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model)
{
	GML_STDMUTEX_LOCK(model); // LoadS3OTextureNow

	string totalName = model->tex1 + model->tex2;

	if (s3oTextureNames.find(totalName) != s3oTextureNames.end()){
		return s3oTextureNames[totalName];
	}
	const int newNum = s3oTextures.size();
	S3oTex tex;
	tex.num = newNum;

	CBitmap bm;
	if (!bm.Load(std::string("unittextures/" + model->tex1))) {
		throw content_error("Could not load texture unittextures/" + model->tex1 + " from S3O model " + model->name);
	}
	tex.tex1 = bm.CreateTexture(true);
	tex.tex1SizeX = bm.xsize;
	tex.tex1SizeY = bm.ysize;
	tex.tex2 = 0;
	tex.tex2SizeX = 0;
	tex.tex2SizeY = 0;
	//if (unitDrawer->advShading)
	{
		CBitmap bm;
		// No error checking here... other code relies on an empty texture
		// being generated if it couldn't be loaded.
		// Also many map features specify a tex2 but don't ship it with the map,
		// so throwing here would cause maps to break.
		if (!bm.Load(std::string("unittextures/" + model->tex2))) {
			bm.Alloc(1, 1);
			bm.mem[3] = 255; // file not found, set alpha to white so unit is visible
		}
		tex.tex2 = bm.CreateTexture(true);
		tex.tex2SizeX = bm.xsize;
		tex.tex2SizeY = bm.ysize;
	}
	s3oTextures.push_back(tex);
	s3oTextureNames[totalName] = newNum;

	return newNum;
}
Esempio n. 11
0
void CSMFReadMap::CreateSpecularTex()
{
	if (!haveSpecularTexture) {
		return;
	}

	CBitmap specularTexBM;
	CBitmap skyReflectModTexBM;
	CBitmap detailNormalTexBM;
	CBitmap lightEmissionTexBM;
	CBitmap parallaxHeightTexBM;

	if (!specularTexBM.Load(mapInfo->smf.specularTexName)) {
		// maps wants specular lighting, but no moderation
		specularTexBM.channels = 4;
		specularTexBM.Alloc(1, 1);
		specularTexBM.mem[0] = 255;
		specularTexBM.mem[1] = 255;
		specularTexBM.mem[2] = 255;
		specularTexBM.mem[3] = 255;
	}

	specularTex = specularTexBM.CreateTexture(false);

	// no default 1x1 textures for these
	if (skyReflectModTexBM.Load(mapInfo->smf.skyReflectModTexName)) {
		skyReflectModTex = skyReflectModTexBM.CreateTexture(false);
	}

	if (detailNormalTexBM.Load(mapInfo->smf.detailNormalTexName)) {
		detailNormalTex = detailNormalTexBM.CreateTexture(false);
	}

	if (lightEmissionTexBM.Load(mapInfo->smf.lightEmissionTexName)) {
		lightEmissionTex = lightEmissionTexBM.CreateTexture(false);
	}

	if (parallaxHeightTexBM.Load(mapInfo->smf.parallaxHeightTexName)) {
		parallaxHeightTex = parallaxHeightTexBM.CreateTexture(false);
	}
}
Esempio n. 12
0
	/*
	* Class:     aflobby_CUnitSyncJNIBindings
	* Method:    WriteMiniMap
	* Signature: (II)I
	*/
	JNIEXPORT jboolean JNICALL Java_aflobby_CUnitSyncJNIBindings_WriteMiniMap
		(JNIEnv *env, jclass myobject, jstring mapfile, jstring imagename, jint miplevel){
			const char *filename = env->GetStringUTFChars(mapfile, 0);
			const char *bitmap_filename = env->GetStringUTFChars(imagename, 0);
			void* minimap = GetMinimap(filename, miplevel);
			if (!minimap){
				env->ReleaseStringUTFChars(mapfile, filename);
				env->ReleaseStringUTFChars(mapfile, bitmap_filename);
				return false;
			}
			int size = 1024 >> miplevel;
			CBitmap bm;
			bm.Alloc(size, size);
			unsigned short *src = (unsigned short*)minimap;
			unsigned char *dst = bm.mem;
			for (int y = 0; y < size; y++) {
				for (int x = 0; x < size; x++){
					dst[0] = RED_RGB565   ((*src)) << 3;
					dst[1] = GREEN_RGB565 ((*src)) << 2;
					dst[2] = BLUE_RGB565  ((*src)) << 3;
					dst[3] = 255;
					++src;
					dst += 4;
				}
			}
			remove(bitmap_filename); //somehow overwriting doesn't work??
			bm.Save(bitmap_filename);
			// check whether the bm.Save succeeded?
			
			
			FILE* f = fopen(bitmap_filename, "rb");
			bool success = !!f;
			if (success) {
				fclose(f);
			}
			env->ReleaseStringUTFChars(mapfile, filename);
			env->ReleaseStringUTFChars(mapfile, bitmap_filename);
			return success;
		}
Esempio n. 13
0
void CBitmap::Blur(int iterations, float weight)
{
	if (type == BitmapTypeDDS) {
		return;
	}

	CBitmap* src = this;
	CBitmap* dst = new CBitmap();
	dst->channels = src->channels;
	dst->Alloc(xsize,ysize);

	for (int i=0; i < iterations; ++i){
		{
			int j,y,x;
			#pragma omp parallel for private(j,x,y)
			for (y=0; y < ysize; y++) {
				for (x=0; x < xsize; x++) {
					for (j=0; j < channels; j++) {
						kernelBlur(dst, src->mem, x, y, j, weight);
					}
				}
			}
		}
		CBitmap* buf = dst;
		dst = src;
		src = buf;
	}

	if (dst == this) {
		CBitmap* buf = dst;
		dst = src;
		src = buf;
	}

	delete dst;
}
Esempio n. 14
0
void CBitmap::Blur(int iterations, float weight)
{
	if (type == BitmapTypeDDS) {
		return;
	}

	CBitmap* src = this;
	CBitmap* dst = new CBitmap();
	dst->channels = src->channels;
	dst->Alloc(xsize,ysize);

	for (int i=0; i < iterations; ++i){
		#pragma omp parallel private(y,x,i)
		{
			#pragma omp for
			for (int y=0; y < ysize; ++y) {
				for (int x=0; x < xsize; ++x) {
					for (int i=0; i < channels; ++i) {
						kernelBlur(dst, src->mem, x, y, i, weight);
					}
				}
			}
		}
		CBitmap* buf = dst;
		dst = src;
		src = buf;
	}

	if (dst == this) {
		CBitmap* buf = dst;
		dst = src;
		src = buf;
	}

	delete dst;
}
Esempio n. 15
0
CSMFReadMap::CSMFReadMap(std::string mapname): file(mapname)
{
	loadscreen->SetLoadMessage("Loading SMF");

	ConfigureAnisotropy();

	for (int a = 0; a < 1024; ++a) {
		for (int b = 0; b < 3; ++b) {
			const float absorbColor = mapInfo->water.baseColor[b] - mapInfo->water.absorb[b] * a;
			const float clampedColor = max(mapInfo->water.minColor[b], absorbColor);
			waterHeightColors[a * 4 + b] = clampedColor * 210;
		}
		waterHeightColors[a * 4 + 3] = 1;
	}

	const SMFHeader& header = file.GetHeader();
	const CMapInfo::smf_t& smf = mapInfo->smf;

	width  = header.mapx;
	height = header.mapy;

	numBigTexX      = (header.mapx / bigSquareSize);
	numBigTexY      = (header.mapy / bigSquareSize);
	bigTexSize      = (SQUARE_SIZE * bigSquareSize);
	tileMapSizeX    = (header.mapx / tileScale);
	tileMapSizeY    = (header.mapy / tileScale);
	tileCount       = (header.mapx * header.mapy) / (tileScale * tileScale);
	mapSizeX        = (header.mapx * SQUARE_SIZE);
	mapSizeZ        = (header.mapy * SQUARE_SIZE);
	maxHeightMapIdx = ((header.mapx + 1) * (header.mapy + 1)) - 1;
	heightMapSizeX  =  (header.mapx + 1);

	cornerHeightMapSynced.resize((width + 1) * (height + 1));
#ifdef USE_UNSYNCED_HEIGHTMAP
	cornerHeightMapUnsynced.resize((width + 1) * (height + 1));
#endif

	groundDrawer = NULL;

	const float minH = smf.minHeightOverride ? smf.minHeight : header.minHeight;
	const float maxH = smf.maxHeightOverride ? smf.maxHeight : header.maxHeight;

	file.ReadHeightmap(&cornerHeightMapSynced[0],  minH, (maxH - minH) / 65536.0f);
	CReadMap::Initialize();

	shadingTexPixelRow.resize(gs->mapxp1 * 4, 0);
	shadingTexUpdateIter = 0;
	shadingTexUpdateRate = std::max(1.0f, math::ceil((width + 1) / float(height + 1)));
	// with GLSL, the shading texture has very limited use (minimap etc) so we increase the update interval
	if (globalRendering->haveGLSL)
		shadingTexUpdateRate *= 10;


	for (unsigned int a = 0; a < mapname.size(); ++a) {
		mapChecksum += mapname[a];
		mapChecksum *= mapname[a];
	}



	haveSpecularLighting = !(mapInfo->smf.specularTexName.empty());
	haveSplatTexture = (!mapInfo->smf.splatDetailTexName.empty() && !mapInfo->smf.splatDistrTexName.empty());

	CBitmap detailTexBM;
	CBitmap grassShadingTexBM;

	detailTex        = 0;
	shadingTex       = 0;
	normalsTex       = 0;
	minimapTex       = 0;
	specularTex      = 0;
	splatDetailTex   = 0;
	splatDistrTex    = 0;
	skyReflectModTex = 0;
	detailNormalTex  = 0;
	lightEmissionTex = 0;

	if (haveSpecularLighting) {
		CBitmap specularTexBM;
		CBitmap skyReflectModTexBM;
		CBitmap detailNormalTexBM;
		CBitmap lightEmissionTexBM;

		if (!specularTexBM.Load(mapInfo->smf.specularTexName)) {
			// maps wants specular lighting, but no moderation
			specularTexBM.channels = 4;
			specularTexBM.Alloc(1, 1);
			specularTexBM.mem[0] = 255;
			specularTexBM.mem[1] = 255;
			specularTexBM.mem[2] = 255;
			specularTexBM.mem[3] = 255;
		}

		specularTex = specularTexBM.CreateTexture(false);

		if (haveSplatTexture) {
			CBitmap splatDistrTexBM;
			CBitmap splatDetailTexBM;
			// if the map supplies an intensity- and a distribution-texture for
			// detail-splat blending, the regular detail-texture is not used
			if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) {
				// default detail-texture should be all-grey
				splatDetailTexBM.channels = 4;
				splatDetailTexBM.Alloc(1, 1);
				splatDetailTexBM.mem[0] = 127;
				splatDetailTexBM.mem[1] = 127;
				splatDetailTexBM.mem[2] = 127;
				splatDetailTexBM.mem[3] = 127;
			}

			if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) {
				splatDistrTexBM.channels = 4;
				splatDistrTexBM.Alloc(1, 1);
				splatDistrTexBM.mem[0] = 255;
				splatDistrTexBM.mem[1] = 0;
				splatDistrTexBM.mem[2] = 0;
				splatDistrTexBM.mem[3] = 0;
			}

			splatDetailTex = splatDetailTexBM.CreateTexture(true);
			splatDistrTex = splatDistrTexBM.CreateTexture(true);
		}

		// no default 1x1 textures for these
		if (skyReflectModTexBM.Load(mapInfo->smf.skyReflectModTexName)) {
			skyReflectModTex = skyReflectModTexBM.CreateTexture(false);
		}

		if (detailNormalTexBM.Load(mapInfo->smf.detailNormalTexName)) {
			detailNormalTex = detailNormalTexBM.CreateTexture(false);
		}

		if (lightEmissionTexBM.Load(mapInfo->smf.lightEmissionTexName)) {
			lightEmissionTex = lightEmissionTexBM.CreateTexture(false);
		}
	}

	if (!detailTexBM.Load(mapInfo->smf.detailTexName)) {
		throw content_error("Could not load detail texture from file " + mapInfo->smf.detailTexName);
	}

	{
		glGenTextures(1, &detailTex);
		glBindTexture(GL_TEXTURE_2D, detailTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		if (anisotropy != 0.0f) {
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
		}
		glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, detailTexBM.xsize, detailTexBM.ysize, GL_RGBA, GL_UNSIGNED_BYTE, detailTexBM.mem);
	}


	{
		// the minimap is a static texture
		std::vector<unsigned char> minimapTexBuf(MINIMAP_SIZE, 0);
		file.ReadMinimap(&minimapTexBuf[0]);

		glGenTextures(1, &minimapTex);
		glBindTexture(GL_TEXTURE_2D, minimapTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MINIMAP_NUM_MIPMAP - 1);
		int offset = 0;
		for (unsigned int i = 0; i < MINIMAP_NUM_MIPMAP; i++) {
			const int mipsize = 1024 >> i;
			const int size = ((mipsize + 3) / 4) * ((mipsize + 3) / 4) * 8;
			glCompressedTexImage2DARB(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipsize, mipsize, 0, size, &minimapTexBuf[0] + offset);
			offset += size;
		}
	}

	{
		if (grassShadingTexBM.Load(mapInfo->smf.grassShadingTexName)) {
			// generate mipmaps for the grass shading-texture
			grassShadingTex = grassShadingTexBM.CreateTexture(true);
		} else {
			grassShadingTex = minimapTex;
		}
	}


	{
		// the shading/normal texture buffers must have PO2 dimensions
		// (excess elements that no vertices map into are left unused)
		glGenTextures(1, &shadingTex);
		glBindTexture(GL_TEXTURE_2D, shadingTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		if (anisotropy != 0.0f) {
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
		}

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	}

	{
		#if (SSMF_UNCOMPRESSED_NORMALS == 1)
		std::vector<float> normalsTexBuf(gs->pwr2mapx * gs->pwr2mapy * 4, 0.0f);
		#else
		GLenum texFormat = GL_LUMINANCE_ALPHA16F_ARB;

		if (configHandler->GetBool("GroundNormalTextureHighPrecision")) {
			texFormat = GL_LUMINANCE_ALPHA32F_ARB;
		}
		#endif

		glGenTextures(1, &normalsTex);
		glBindTexture(GL_TEXTURE_2D, normalsTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		#if (SSMF_UNCOMPRESSED_NORMALS == 1)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_FLOAT, &normalsTexBuf[0]);
		#else
		glTexImage2D(GL_TEXTURE_2D, 0, texFormat, gs->pwr2mapx, gs->pwr2mapy, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, NULL);
		#endif
	}

	file.ReadFeatureInfo();
}
Esempio n. 16
0
CGrassDrawer::CGrassDrawer()
: grassOff(false)
, grassDL(0)
, grassBladeTex(0)
, farTex(0)
, grassMap(nullptr)
{
	const int detail = configHandler->GetInt("GrassDetail");

	// some ATI drivers crash with grass enabled, default to disabled
	if ((detail == 0) || ((detail == 7) && globalRendering->haveATI)) {
		grassOff = true;
		return;
	}

	if (!GLEW_EXT_framebuffer_blit) {
		grassOff = true;
		return;
	}

	{
		MapBitmapInfo grassbm;
		unsigned char* grassdata = readMap->GetInfoMap("grass", &grassbm);

		if (!grassdata) {
			grassOff = true;
			return;
		}

		if (grassbm.width != gs->mapx / grassSquareSize || grassbm.height != gs->mapy / grassSquareSize) {
			char b[128];
			SNPRINTF(b, sizeof(b), "grass-map has wrong size (%dx%d, should be %dx%d)\n",
				grassbm.width, grassbm.height, gs->mapx / 4, gs->mapy / 4);
			throw std::runtime_error(b);
		}
		const int grassMapSize = gs->mapx * gs->mapy / (grassSquareSize * grassSquareSize);
		grassMap = new unsigned char[grassMapSize];
		memcpy(grassMap, grassdata, grassMapSize);
		readMap->FreeInfoMap("grass", grassdata);
	}

	ChangeDetail(detail);

	blocksX = gs->mapx / grassSquareSize / grassBlockSize;
	blocksY = gs->mapy / grassSquareSize / grassBlockSize;

	rng.Seed(15);
	grassDL = glGenLists(1);
	CreateGrassDispList(grassDL);

	{
		CBitmap grassBladeTexBM;
		if (!grassBladeTexBM.Load(mapInfo->grass.grassBladeTexName)) {
			//! map didn't define a grasstex, so generate one
			grassBladeTexBM.channels = 4;
			grassBladeTexBM.Alloc(256,64);

			for (int a = 0; a < 16; ++a) {
				CreateGrassBladeTex(&grassBladeTexBM.mem[a * 16 * 4]);
			}
		}

		glGenTextures(1, &grassBladeTex);
		glBindTexture(GL_TEXTURE_2D, grassBladeTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
		glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, grassBladeTexBM.xsize, grassBladeTexBM.ysize, GL_RGBA, GL_UNSIGNED_BYTE, &grassBladeTexBM.mem[0]);
	}

	CreateFarTex();
	LoadGrassShaders();
	configHandler->NotifyOnChange(this);
}
Esempio n. 17
0
CSmfReadMap::CSmfReadMap(std::string mapname): file(mapname)
{
	loadscreen->SetLoadMessage("Loading SMF");

	ConfigureAnisotropy();

	for (int a = 0; a < 1024; ++a) {
		for (int b = 0; b < 3; ++b) {
			float c = max(mapInfo->water.minColor[b], mapInfo->water.baseColor[b] - mapInfo->water.absorb[b] * a);
			waterHeightColors[a * 4 + b] = (unsigned char)(c * 210);
		}
		waterHeightColors[a * 4 + 3] = 1;
	}

	const SMFHeader& header = file.GetHeader();

	width  = header.mapx;
	height = header.mapy;

	heightmap = new float[(width + 1) * (height + 1)];
	groundDrawer = 0;

	const CMapInfo::smf_t& smf = mapInfo->smf;
	const float minH = smf.minHeightOverride ? smf.minHeight : header.minHeight;
	const float maxH = smf.maxHeightOverride ? smf.maxHeight : header.maxHeight;

	const float base = minH;
	const float mod = (maxH - minH) / 65536.0f;

	file.ReadHeightmap(heightmap, base, mod);

	CReadMap::Initialize();

	for (unsigned int a = 0; a < mapname.size(); ++a) {
		mapChecksum += mapname[a];
		mapChecksum *= mapname[a];
	}



	haveSpecularLighting = (!(mapInfo->smf.specularTexName.empty()) && globalRendering->haveGLSL);
	haveSplatTexture = (!mapInfo->smf.splatDetailTexName.empty() && !mapInfo->smf.splatDistrTexName.empty());

	CBitmap detailTexBM;
	CBitmap grassShadingTexBM;

	detailTex        = 0;
	shadingTex       = 0;
	normalsTex       = 0;
	minimapTex       = 0;
	specularTex      = 0;
	splatDetailTex   = 0;
	splatDistrTex    = 0;
	skyReflectModTex = 0;

	if (haveSpecularLighting) {
		CBitmap specularTexBM;
		CBitmap skyReflectModTexBM;
		if (!specularTexBM.Load(mapInfo->smf.specularTexName)) {
			// maps wants specular lighting, but no moderation
			specularTexBM.Alloc(1, 1);
			specularTexBM.mem[0] = 255;
			specularTexBM.mem[1] = 255;
			specularTexBM.mem[2] = 255;
			specularTexBM.mem[3] = 255;
		}

		specularTex = specularTexBM.CreateTexture(false);

		if (haveSplatTexture) {
			CBitmap splatDistrTexBM;
			CBitmap splatDetailTexBM;
			// if the map supplies an intensity- and a distribution-texture for
			// detail-splat blending, the regular detail-texture is not used
			if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) {
				// default detail-texture should be all-grey
				splatDetailTexBM.Alloc(1, 1);
				splatDetailTexBM.mem[0] = 127;
				splatDetailTexBM.mem[1] = 127;
				splatDetailTexBM.mem[2] = 127;
				splatDetailTexBM.mem[3] = 127;
			}

			if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) {
				splatDistrTexBM.Alloc(1, 1);
				splatDistrTexBM.mem[0] = 255;
				splatDistrTexBM.mem[1] = 0;
				splatDistrTexBM.mem[2] = 0;
				splatDistrTexBM.mem[3] = 0;
			}

			splatDetailTex = splatDetailTexBM.CreateTexture(true);
			splatDistrTex = splatDistrTexBM.CreateTexture(true);
		}

		if (skyReflectModTexBM.Load(mapInfo->smf.skyReflectModTexName)) {
			skyReflectModTex = skyReflectModTexBM.CreateTexture(false);
		}
	}

	if (!detailTexBM.Load(mapInfo->smf.detailTexName)) {
		throw content_error("Could not load detail texture from file " + mapInfo->smf.detailTexName);
	}

	{
		glGenTextures(1, &detailTex);
		glBindTexture(GL_TEXTURE_2D, detailTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		if (anisotropy != 0.0f) {
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
		}
		glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, detailTexBM.xsize, detailTexBM.ysize, GL_RGBA, GL_UNSIGNED_BYTE, detailTexBM.mem);
	}


	{
		// the minimap is a static texture
		std::vector<unsigned char> minimapTexBuf(MINIMAP_SIZE, 0);
		file.ReadMinimap(&minimapTexBuf[0]);

		glGenTextures(1, &minimapTex);
		glBindTexture(GL_TEXTURE_2D, minimapTex);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MINIMAP_NUM_MIPMAP - 1);
		int offset = 0;
		for (unsigned int i = 0; i < MINIMAP_NUM_MIPMAP; i++) {
			const int mipsize = 1024 >> i;
			const int size = ((mipsize + 3) / 4) * ((mipsize + 3) / 4) * 8;
			glCompressedTexImage2DARB(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipsize, mipsize, 0, size, &minimapTexBuf[0] + offset);
			offset += size;
		}
	}

	{
		if (grassShadingTexBM.Load(mapInfo->smf.grassShadingTexName)) {
			// generate mipmaps for the grass shading-texture
			grassShadingTex = grassShadingTexBM.CreateTexture(true);
		} else {
			grassShadingTex = minimapTex;
		}
	}


	{
		// the shading/normal texture buffers must have PO2 dimensions
		// (excess elements that no vertices map into are left unused)
		glGenTextures(1, &shadingTex);
		glBindTexture(GL_TEXTURE_2D, shadingTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		if (anisotropy != 0.0f) {
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
		}

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	}

	{
		#if (SSMF_UNCOMPRESSED_NORMALS == 1)
		std::vector<float> normalsTexBuf(gs->pwr2mapx * gs->pwr2mapy * 4, 0.0f);
		#else
		GLenum texFormat = GL_LUMINANCE_ALPHA16F_ARB;

		if (!!configHandler->Get("GroundNormalTextureHighPrecision", 0)) {
			texFormat = GL_LUMINANCE_ALPHA32F_ARB;
		}
		#endif

		glGenTextures(1, &normalsTex);
		glBindTexture(GL_TEXTURE_2D, normalsTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		#if (SSMF_UNCOMPRESSED_NORMALS == 1)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_FLOAT, &normalsTexBuf[0]);
		#else
		glTexImage2D(GL_TEXTURE_2D, 0, texFormat, gs->pwr2mapx, gs->pwr2mapy, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, NULL);
		#endif
	}

	file.ReadFeatureInfo();
}
Esempio n. 18
0
CGrassDrawer::CGrassDrawer()
: CEventClient("[GrassDrawer]", 199992, false)
, grassOff(false)
, blocksX(mapDims.mapx / grassSquareSize / grassBlockSize)
, blocksY(mapDims.mapy / grassSquareSize / grassBlockSize)
, grassDL(0)
, grassBladeTex(0)
, farTex(0)
, farnearVA(nullptr)
, updateBillboards(false)
, grassMap(nullptr)
{
	blockDrawer.ResetState();
	rng.Seed(15);

	const int detail = configHandler->GetInt("GrassDetail");

	// some ATI drivers crash with grass enabled, default to disabled
	if ((detail == 0) || ((detail == 7) && globalRendering->haveATI)) {
		grassOff = true;
		return;
	}

	// needed to create the far tex
	if (!GLEW_EXT_framebuffer_blit) {
		grassOff = true;
		return;
	}

	// load grass density from map
	{
		MapBitmapInfo grassbm;
		unsigned char* grassdata = readMap->GetInfoMap("grass", &grassbm);
		if (!grassdata) {
			grassOff = true;
			return;
		}

		if (grassbm.width != mapDims.mapx / grassSquareSize || grassbm.height != mapDims.mapy / grassSquareSize) {
			char b[128];
			SNPRINTF(b, sizeof(b), "grass-map has wrong size (%dx%d, should be %dx%d)\n",
				grassbm.width, grassbm.height, mapDims.mapx / 4, mapDims.mapy / 4);
			throw std::runtime_error(b);
		}
		const int grassMapSize = mapDims.mapx * mapDims.mapy / (grassSquareSize * grassSquareSize);
		grassMap = new unsigned char[grassMapSize];
		memcpy(grassMap, grassdata, grassMapSize);
		readMap->FreeInfoMap("grass", grassdata);
	}

	// create/load blade texture
	{
		CBitmap grassBladeTexBM;
		if (!grassBladeTexBM.Load(mapInfo->grass.bladeTexName)) {
			// map didn't define a grasstex, so generate one
			grassBladeTexBM.channels = 4;
			grassBladeTexBM.Alloc(256,64);

			for (int a = 0; a < 16; ++a) {
				CreateGrassBladeTex(&grassBladeTexBM.mem[a * 16 * 4]);
			}
		}
		//grassBladeTexBM.Save("blade.png", false);
		grassBladeTex = grassBladeTexBM.CreateTexture(true);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}

	// create shaders * finalize
	grass.resize(blocksX * blocksY);
	farnearVA = new CVertexArray;
	grassDL = glGenLists(1);

	ChangeDetail(detail);
	LoadGrassShaders();
	configHandler->NotifyOnChange(this);

	// eventclient
	autoLinkEvents = true;
	RegisterLinkedEvents(this);
	eventHandler.AddClient(this);
}
Esempio n. 19
0
CBasicTreeDrawer::CBasicTreeDrawer(): ITreeDrawer()
{
	LuaParser resourcesParser("gamedata/resources.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
	if (!resourcesParser.Execute()) {
		LOG_L(L_ERROR, "%s", resourcesParser.GetErrorLog().c_str());
	}

	const LuaTable treesTable = resourcesParser.GetRoot().SubTable("graphics").SubTable("trees");
	const float tintc[3] = {0.6f, 0.7f, 0.6f};

	std::string fn;
	CBitmap sprite;
	CBitmap TexImage;
	TexImage.Alloc(512, 512);

	{
		fn = "bitmaps/" + treesTable.GetString("gran1", "gran.bmp");

		if (!sprite.Load(fn))
			throw content_error("Could not load tree texture from " + fn);
		if (sprite.xsize != 256 || sprite.ysize != 256)
			throw content_error("texture " + fn + " must be 256x256!");
		sprite.ReverseYAxis();
		sprite.SetTransparent(SColor(72, 72, 72), SColor(33, 54, 29, 0));
		TexImage.CopySubImage(sprite, 0, 0);
	}

	{
		fn = "bitmaps/" + treesTable.GetString("gran2", "gran2.bmp");
		if (!sprite.Load(fn))
			throw content_error("Could not load tree texture from file " + fn);
		if (sprite.xsize != 256 && sprite.ysize != 256)
			throw content_error("texture " + fn + " must be 256x256!");
		sprite.ReverseYAxis();
		sprite.SetTransparent(SColor(72, 72, 72), SColor(33, 54, 29, 0));
		TexImage.CopySubImage(sprite, 255, 0);
	}

	{
		fn = "bitmaps/" + treesTable.GetString("birch1", "birch1.bmp");
		if (!sprite.Load(fn))
			throw content_error("Could not load tree texture from file " + fn);
		if (sprite.xsize != 128 || sprite.ysize != 256)
			throw content_error("texture " + fn + " must be 128x256!");
		sprite.ReverseYAxis();
		sprite.SetTransparent(SColor(72, 72, 72), SColor(75, 102, 49, 0));
		sprite.Tint(tintc);
		TexImage.CopySubImage(sprite, 0, 255);
	}

	{
		fn = "bitmaps/" + treesTable.GetString("birch2", "birch2.bmp");
		if (!sprite.Load(fn))
			throw content_error("Could not load tree texture from file " + fn);
		if (sprite.xsize != 128 || sprite.ysize != 256)
			throw content_error("texture " + fn + " must be 128x256!");
		sprite.ReverseYAxis();
		sprite.SetTransparent(SColor(72, 72, 72), SColor(75, 102, 49, 0));
		sprite.Tint(tintc);
		TexImage.CopySubImage(sprite, 127, 255);
	}

	{
		fn = "bitmaps/" + treesTable.GetString("birch3", "birch3.bmp");
		if (!sprite.Load(fn))
			throw content_error("Could not load tree texture from file " + fn);
		if (sprite.xsize != 256 || sprite.ysize != 256)
			throw content_error("texture " + fn + " must be 256x256!");
		sprite.ReverseYAxis();
		sprite.SetTransparent(SColor(72, 72, 72), SColor(75, 102, 49, 0));
		sprite.Tint(tintc);
		TexImage.CopySubImage(sprite, 255, 255);
	}

	// create mipmapped texture
	treetex = TexImage.CreateTexture(true);

	lastListClean = 0;
	treesX = mapDims.mapx / TREE_SQUARE_SIZE;
	treesY = mapDims.mapy / TREE_SQUARE_SIZE;
	nTrees = treesX * treesY;
	trees = new TreeSquareStruct[nTrees];

	for (TreeSquareStruct* pTSS = trees; pTSS < trees + nTrees; ++pTSS) {
		pTSS->dispList = 0;
		pTSS->farDispList = 0;
	}
}
Esempio n. 20
0
CUnitDrawer::CUnitDrawer(void)
:	showHealthBars(true),
	updateFace(0)
{
	if(texturehandler==0)
		texturehandler=SAFE_NEW CTextureHandler;

	unitDrawDist=configHandler.GetInt("UnitLodDist",200);
	unitIconDist=configHandler.GetInt("UnitIconDist",200);
	iconLength=750*unitIconDist*unitIconDist;

	CBitmap white;
	white.Alloc(1,1);
	for(int a=0;a<4;++a)
		white.mem[a]=255;

	whiteTex=white.CreateTexture(false);

	unitAmbientColor=readmap->mapDefParser.GetFloat3(float3(0.4f,0.4f,0.4f),"MAP\\LIGHT\\UnitAmbientColor");
	unitSunColor=readmap->mapDefParser.GetFloat3(float3(0.7f,0.7f,0.7f),"MAP\\LIGHT\\UnitSunColor");

	float3 specularSunColor=readmap->mapDefParser.GetFloat3(unitSunColor,"MAP\\LIGHT\\SpecularSunColor");
	readmap->mapDefParser.GetDef(unitShadowDensity,"0.8","MAP\\LIGHT\\UnitShadowDensity");

	advShading=!!configHandler.GetInt("AdvUnitShading", GLEW_ARB_fragment_program ? 1 : 0);
	if (advShading && !GLEW_ARB_fragment_program) {
		logOutput.Print("You are missing an OpenGL extension needed to use advanced unit shading (GL_ARB_fragment_program)");
		advShading = false;
	}

	if (advShading)
	{
		unitVP = LoadVertexProgram("unit.vp");
		unitFP = LoadFragmentProgram("unit.fp");
		unitS3oVP = LoadVertexProgram("units3o.vp");
		unitS3oFP = LoadFragmentProgram("units3o.fp");

		if (shadowHandler->canUseShadows) {
			unitShadowFP    = LoadFragmentProgram("unit_shadow.fp");
			unitShadowS3oFP = LoadFragmentProgram("units3o_shadow.fp");
			unitShadowGenVP = LoadVertexProgram("unit_genshadow.vp");
		} else {
			unitShadowFP = 0;
			unitShadowS3oFP = 0;
			unitShadowGenVP = 0;
		}

		glGenTextures(1,&boxtex);
		glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, boxtex);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0);

		glGenTextures(1,&specularTex);
		glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, specularTex);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,128,float3(1,1,1),float3(0,0,-2),float3(0,-2,0),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,128,float3(-1,1,-1),float3(0,0,2),float3(0,-2,0),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,128,float3(-1,1,-1),float3(2,0,0),float3(0,0,2),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,128,float3(-1,-1,1),float3(2,0,0),float3(0,0,-2),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,128,float3(-1,1,1),float3(2,0,0),float3(0,-2,0),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,128,float3(1,1,-1),float3(-2,0,0),float3(0,-2,0),gs->sunVector,100,specularSunColor);
	}
}