void CBasicTreeDrawer::CreateTreeTex(GLuint& texnum, unsigned char *data, int xsize, int ysize)
{
	glGenTextures(1, &texnum);
	glBindTexture(GL_TEXTURE_2D, texnum);
	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, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
Exemple #2
0
void CTextureAtlas::CreateTexture()
{
	const int2 atlasSize = atlasAllocator->GetAtlasSize();

	PBO pbo;
	pbo.Bind();
	pbo.Resize(atlasSize.x * atlasSize.y * 4);

	unsigned char* data = (unsigned char*)pbo.MapBuffer(GL_WRITE_ONLY);

	{
		// make spacing between textures black transparent to avoid ugly lines with linear filtering
		std::memset(data, 0, atlasSize.x * atlasSize.y * 4);

		for (std::vector<MemTex*>::iterator it = memtextures.begin(); it != memtextures.end(); ++it) {
			const float4 texCoords = atlasAllocator->GetTexCoords((*it)->names[0]);
			const float4 absCoords = atlasAllocator->GetEntry((*it)->names[0]);
			const int xpos = absCoords.x;
			const int ypos = absCoords.y;

			AtlasedTexture tex(texCoords);
			for (size_t n = 0; n < (*it)->names.size(); ++n) {
				textures[(*it)->names[n]] = tex;
			}

			for (int y = 0; y < (*it)->ysize; ++y) {
				int* dst = ((int*)data) + xpos + (ypos + y) * atlasSize.x;
				int* src = ((int*)(*it)->data) + y * (*it)->xsize;
				memcpy(dst, src, (*it)->xsize * 4);
			}
		}

		if (debug) {
			CBitmap tex(data, atlasSize.x, atlasSize.y);
			tex.Save(name + "-" + IntToString(atlasSize.x) + "x" + IntToString(atlasSize.y) + ".png");
		}
	}

	pbo.UnmapBuffer();

	const int maxMipMaps = atlasAllocator->GetMaxMipMaps();
	glGenTextures(1, &atlasTexID);
		glBindTexture(GL_TEXTURE_2D, atlasTexID);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : 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);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  maxMipMaps);
		if (maxMipMaps > 0) {
			glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, atlasSize.x, atlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); //FIXME disable texcompression //FIXME 2 PBO!!!!
		} else {
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atlasSize.x, atlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr());
		}

	pbo.Unbind();

	initialized = true;
}
Exemple #3
0
const unsigned int CBitmap::CreateTexture(bool mipmaps) const
{
	ScopedTimer timer("Textures::CBitmap::CreateTexture");

	if (type == BitmapTypeDDS) {
		return CreateDDSTexture();
	}

	if (mem == NULL) {
		return 0;
	}

	// jcnossen: Some drivers return "2.0" as a version string,
	// but switch to software rendering for non-power-of-two textures.
	// GL_ARB_texture_non_power_of_two indicates that the hardware will actually support it.
	if (!globalRendering->supportNPOTs && (xsize != next_power_of_2(xsize) || ysize != next_power_of_2(ysize)))
	{
		CBitmap bm = CreateRescaled(next_power_of_2(xsize), next_power_of_2(ysize));
		return bm.CreateTexture(mipmaps);
	}

	unsigned int texture;

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	//FIXME add glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for NPOTs

	if (mipmaps) {
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

		glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, mem);
	} else {
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		//glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,xsize, ysize, 0,GL_RGBA, GL_UNSIGNED_BYTE, mem);
		//gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, mem);

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, xsize, ysize, 0, GL_RGBA, GL_UNSIGNED_BYTE, mem);
	}

	return texture;
}
Exemple #4
0
CInMapDraw::CInMapDraw(void)
{
	keyPressed = false;
	wantLabel = false;
	drawAll = false;
	allowSpecMapDrawing = true;
	allowLuaMapDrawing = true;
	lastLineTime = 0;
	lastLeftClickTime = 0;
	lastPos = float3(1, 1, 1);

	drawQuadsX = gs->mapx / DRAW_QUAD_SIZE;
	drawQuadsY = gs->mapy / DRAW_QUAD_SIZE;
	numQuads = drawQuadsX * drawQuadsY;
	drawQuads.resize(numQuads);

	unsigned char tex[64][128][4];
	for (int y = 0; y < 64; y++) {
		for (int x = 0; x < 128; x++) {
			tex[y][x][0] = 0;
			tex[y][x][1] = 0;
			tex[y][x][2] = 0;
			tex[y][x][3] = 0;
		}
	}

	#define SMOOTHSTEP(x,y,a) (unsigned char)(x * (1.0f - a) + y * a)

	for (int y = 0; y < 64; y++) {
		// circular thingy
		for (int x = 0; x < 64; x++) {
			float dist = sqrt((float)(x - 32) * (x - 32) + (y - 32) * (y - 32));
			if (dist > 31.0f) {
				// do nothing - leave transparent
			} else if (dist > 30.0f) {
				// interpolate (outline -> nothing)
				float a = (dist - 30.0f);
				tex[y][x][3] = SMOOTHSTEP(255,0,a);
			} else if (dist > 24.0f) {
				// black outline
				tex[y][x][3] = 255;
			} else if (dist > 23.0f) {
				// interpolate (inner -> outline)
				float a = (dist - 23.0f);
				tex[y][x][0] = SMOOTHSTEP(255,0,a);
				tex[y][x][1] = SMOOTHSTEP(255,0,a);
				tex[y][x][2] = SMOOTHSTEP(255,0,a);
				tex[y][x][3] = SMOOTHSTEP(200,255,a);
			} else {
				tex[y][x][0] = 255;
				tex[y][x][1] = 255;
				tex[y][x][2] = 255;
				tex[y][x][3] = 200;
			}
		}
	}
	for (int y = 0; y < 64; y++) {
		// linear falloff
		for (int x = 64; x < 128; x++) {
			float dist = abs(y - 32);
			if (dist > 31.0f) {
				// do nothing - leave transparent
			} else if (dist > 30.0f) {
				// interpolate (outline -> nothing)
				float a = (dist - 30.0f);
				tex[y][x][3] = SMOOTHSTEP(255,0,a);
			} else if (dist > 24.0f) {
				// black outline
				tex[y][x][3] = 255;
			} else if (dist > 23.0f) {
				// interpolate (inner -> outline)
				float a = (dist - 23.0f);
				tex[y][x][0] = SMOOTHSTEP(255,0,a);
				tex[y][x][1] = SMOOTHSTEP(255,0,a);
				tex[y][x][2] = SMOOTHSTEP(255,0,a);
				tex[y][x][3] = SMOOTHSTEP(200,255,a);
			} else {
				tex[y][x][0] = 255;
				tex[y][x][1] = 255;
				tex[y][x][2] = 255;
				tex[y][x][3] = 200;
			}
		}
	}

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	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_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, 128, 64, GL_RGBA, GL_UNSIGNED_BYTE, tex[0]);

	blippSound = sound->GetSoundId("MapPoint", false);
}
Exemple #5
0
void CTextureAtlas::CreateTexture()
{
	const int2 atlasSize = atlasAllocator->GetAtlasSize();
	xsize = atlasSize.x;
	ysize = atlasSize.y;

	PBO pbo;
	pbo.Bind();
	pbo.Resize(atlasSize.x * atlasSize.y * 4);

	unsigned char* data = (unsigned char*)pbo.MapBuffer(GL_WRITE_ONLY);
		std::memset(data, 0, atlasSize.x * atlasSize.y * 4); // make spacing between textures black transparent to avoid ugly lines with linear filtering

		for(std::vector<MemTex*>::iterator it = memtextures.begin(); it != memtextures.end(); ++it) {
			float4 texCoords = atlasAllocator->GetTexCoords((*it)->names[0]);
			float4 absCoords = atlasAllocator->GetEntry((*it)->names[0]);
			const int xpos = absCoords.x;
			const int ypos = absCoords.y;

			AtlasedTexture tex(texCoords);
			for (size_t n = 0; n < (*it)->names.size(); ++n) {
				textures[(*it)->names[n]] = tex;
			}

			for (int y = 0; y < (*it)->ysize; ++y) {
				int* dst = ((int*)data) + xpos + (ypos + y) * atlasSize.x;
				int* src = ((int*)(*it)->data) + y * (*it)->xsize;
				memcpy(dst, src, (*it)->xsize * 4);
			}
		}

		if (debug) {
			// hack to make sure we don't overwrite our own atlases
			static int count = 0;
			char fname[256];
			SNPRINTF(fname, sizeof(fname), "textureatlas%d.png", ++count);

			CBitmap save(data, atlasSize.x, atlasSize.y);
			save.Save(fname);
			LOG("Saved finalized texture-atlas to '%s'.", fname);
		}
	pbo.UnmapBuffer();

	const int maxMipMaps = atlasAllocator->GetMaxMipMaps();
	glGenTextures(1, &gltex);
		glBindTexture(GL_TEXTURE_2D, gltex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : 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);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  maxMipMaps);
		if (maxMipMaps > 0) {
			glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, atlasSize.x, atlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); //FIXME disable texcompression //FIXME 2 PBO!!!!
		} else {
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atlasSize.x, atlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr());
		}

	pbo.Unbind();

	initialized = true;
}
CInMapDrawView::CInMapDrawView()
{
	unsigned char tex[64][128][4];
	for (int y = 0; y < 64; y++) {
		for (int x = 0; x < 128; x++) {
			tex[y][x][0] = 0;
			tex[y][x][1] = 0;
			tex[y][x][2] = 0;
			tex[y][x][3] = 0;
		}
	}

	for (int y = 0; y < 64; y++) {
		// circular thingy
		for (int x = 0; x < 64; x++) {
			float dist = math::sqrt((float)(x - 32) * (x - 32) + (y - 32) * (y - 32));
			if (dist > 31.0f) {
				// do nothing - leave transparent
			} else if (dist > 30.0f) {
				// interpolate (outline -> nothing)
				float a = (dist - 30.0f);
				tex[y][x][3] = smoothStep(255,   0, a);
			} else if (dist > 24.0f) {
				// black outline
				tex[y][x][3] = 255;
			} else if (dist > 23.0f) {
				// interpolate (inner -> outline)
				float a = (dist - 23.0f);
				tex[y][x][0] = smoothStep(255,   0, a);
				tex[y][x][1] = smoothStep(255,   0, a);
				tex[y][x][2] = smoothStep(255,   0, a);
				tex[y][x][3] = smoothStep(200, 255, a);
			} else {
				tex[y][x][0] = 255;
				tex[y][x][1] = 255;
				tex[y][x][2] = 255;
				tex[y][x][3] = 200;
			}
		}
	}
	for (int y = 0; y < 64; y++) {
		// linear falloff
		for (int x = 64; x < 128; x++) {
			float dist = abs(y - 32);
			if (dist > 31.0f) {
				// do nothing - leave transparent
			} else if (dist > 30.0f) {
				// interpolate (outline -> nothing)
				float a = (dist - 30.0f);
				tex[y][x][3] = smoothStep(255,   0, a);
			} else if (dist > 24.0f) {
				// black outline
				tex[y][x][3] = 255;
			} else if (dist > 23.0f) {
				// interpolate (inner -> outline)
				float a = (dist - 23.0f);
				tex[y][x][0] = smoothStep(255,   0, a);
				tex[y][x][1] = smoothStep(255,   0, a);
				tex[y][x][2] = smoothStep(255,   0, a);
				tex[y][x][3] = smoothStep(200, 255, a);
			} else {
				tex[y][x][0] = 255;
				tex[y][x][1] = 255;
				tex[y][x][2] = 255;
				tex[y][x][3] = 200;
			}
		}
	}

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	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_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, 128, 64, GL_RGBA, GL_UNSIGNED_BYTE, tex[0]);
}
Lightmap::Lightmap(Heightmap *orghm, int level, int shadowLevelDif, LightingInfo *li)
{
	int startTicks = SDL_GetTicks();
	tilesize.x = orghm->w-1;
	tilesize.y = orghm->h-1;
	name = "lightmap";

	Heightmap *hm;
	int w;

	for(;;) {
		hm = orghm->GetLevel(-level);
		w=hm->w-1;

		GLint maxw;
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxw);

		if (w > maxw) level ++;
		else break;
	}

	shadowLevelDif=0;
	Heightmap *shadowhm = orghm->GetLevel(-(level+shadowLevelDif));
	int shadowScale=1<<shadowLevelDif;
	int shadowW=shadowhm->w-1;
	assert (w/shadowW == shadowScale);
	//float org2c = w/float(orghm->w-1);
	//float c2org = (float)(orghm->w-1)/w;

	float *centerhm = SAFE_NEW float[w*w];
	Vector3 *shading = SAFE_NEW Vector3[w*w];
	for (int y=0;y<w;y++)
		for (int x=0;x<w;x++) {
			centerhm[y*w+x] =/* hm->scale * */ 0.25f * ( (int)hm->at(x,y)+ (int)hm->at(x+1,y)+ (int)hm->at(x,y+1) + (int)hm->at(x+1,y+1) ); //+ hm->offset;
			shading[y*w+x] = li->ambient;
		}

	uchar *lightMap = SAFE_NEW uchar[shadowW*shadowW];
	for (std::vector<StaticLight>::const_iterator l=li->staticLights.begin();l!=li->staticLights.end();++l)
	{
		float lightx;
		float lighty;

		if (l->directional) {
			lightx = l->position.x;
			lighty = l->position.y;
		} else {
			lightx = (int)(l->position.x / shadowhm->squareSize);
			lighty = (int)(l->position.z / shadowhm->squareSize);
		}
		CalculateShadows(lightMap, shadowW, lightx, lighty,
			l->position.y, centerhm, w, shadowScale, l->directional);

		for (int y=0;y<w;y++)
		{
			for (int x=0;x<w;x++)
			{
				if (!lightMap[(y*shadowW+x)/shadowScale])
					continue;

				Vector3 wp;
				if (l->directional)
					wp = l->position;
				else
					wp = l->position - Vector3((x+0.5f)*hm->squareSize,centerhm[y*w+x],(y+0.5f)*hm->squareSize);

				uchar* normal = hm->GetNormal (x,y);
				Vector3 normv((2 * (int)normal[0] - 256)/255.0f, (2 * (int)normal[1] - 256)/255.0f, (2 * (int)normal[2] - 256)/255.0f);

				wp.Normalize();
				float dot = wp.dot(normv);
				if(dot < 0.0f) dot = 0.0f;
				if(dot > 1.0f) dot = 1.0f;
				dot *= lightMap[(y*shadowW+x)/shadowScale]*(1.0f/255.0f);
				shading[y*w+x] += l->color * dot;
			}
		}

	}
	delete[] lightMap;

	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_LINEAR_MIPMAP_LINEAR);

	uchar *shadingTexData=SAFE_NEW uchar[w*w*4];
	for(int y=0;y<w;y++) {
		for (int x=0;x<w;x++) {
			shadingTexData[(y*w+x)*4+0] = (uchar)(min(1.0f, shading[y*w+x].x) * 255);
			shadingTexData[(y*w+x)*4+1] = (uchar)(min(1.0f, shading[y*w+x].y) * 255);
			shadingTexData[(y*w+x)*4+2] = (uchar)(min(1.0f, shading[y*w+x].z) * 255);
			shadingTexData[(y*w+x)*4+3] = CReadMap::EncodeHeight(centerhm[w*y+x]);
		}
	}

	SaveImage ("lightmap.png", 4, IL_UNSIGNED_BYTE, w,w, shadingTexData);

	glBuildMipmaps(GL_TEXTURE_2D, 4, w,w, GL_RGBA, GL_UNSIGNED_BYTE, shadingTexData);
	delete[] shadingTexData;

	id = shadingTex;

	delete[] shading;
	delete[] centerhm;

	int numTicks = SDL_GetTicks() - startTicks;
	d_trace ("Lightmap generation: %2.3f seconds\n", numTicks * 0.001f);
}
Exemple #8
0
/*
#define W_SIZE 4
#define WF_SIZE 4096
#define WH_SIZE 2048
*/
CDynWater::CDynWater(void)
{
	if (!FBO::IsSupported())
		throw content_error("DynWater Error: missing FBO support");

	lastWaveFrame=0;
	noWakeProjectiles=true;
	firstDraw=true;
	drawSolid=true;
	camPosBig=float3(2048,0,2048);
	refractSize=gu->viewSizeY>=1024 ? 1024:512;

	glGenTextures(1, &reflectTexture);
	glBindTexture(GL_TEXTURE_2D, reflectTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,512, 512, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);

	glGenTextures(1, &refractTexture);
	glBindTexture(GL_TEXTURE_2D, refractTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,refractSize, refractSize, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);

	glGenTextures(1, &detailNormalTex);
	glBindTexture(GL_TEXTURE_2D, detailNormalTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,256, 256, 0,GL_RGBA, GL_FLOAT, 0);
	glGenerateMipmapEXT(GL_TEXTURE_2D);

	float* temp=new float[1024*1024*4];

	for(int y=0;y<64;++y){
		for(int x=0;x<64;++x){
			temp[(y*64+x)*4+0]=(sin(x*PI*2.0f/64.0f)) + (x<32 ? -1:1)*0.3f;
			temp[(y*64+x)*4+1]=temp[(y*64+x)*4+0];
			temp[(y*64+x)*4+2]=(cos(x*PI*2.0f/64.0f)) + (x<32 ? 16-x:x-48)/16.0f*0.3f;
			temp[(y*64+x)*4+3]=0;
		}
	}
	glGenTextures(3, rawBumpTexture);
	glBindTexture(GL_TEXTURE_2D, rawBumpTexture[0]);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp);

	CBitmap foam;
	if (!foam.Load(mapInfo->water.foamTexture))
		throw content_error("Could not load foam from file " + mapInfo->water.foamTexture);
	if (count_bits_set(foam.xsize)!=1 || count_bits_set(foam.ysize)!=1)
		throw content_error("Foam texture not power of two!");
	unsigned char* scrap=new unsigned char[foam.xsize*foam.ysize*4];
	for(int a=0;a<foam.xsize*foam.ysize;++a)
		scrap[a]=foam.mem[a*4];

	glGenTextures(1, &foamTex);
	glBindTexture(GL_TEXTURE_2D, foamTex);
	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_LUMINANCE,foam.xsize,foam.ysize, GL_LUMINANCE, GL_UNSIGNED_BYTE, scrap);

	delete[] scrap;

	if(ProgramStringIsNative(GL_VERTEX_PROGRAM_ARB,"waterDyn.vp"))
		waterVP=LoadVertexProgram("waterDyn.vp");
	else
		waterVP=LoadVertexProgram("waterDynNT.vp");

	waterFP=LoadFragmentProgram("waterDyn.fp");
	waveFP=LoadFragmentProgram("waterDynWave.fp");
	waveVP=LoadVertexProgram("waterDynWave.vp");
	waveFP2=LoadFragmentProgram("waterDynWave2.fp");
	waveVP2=LoadVertexProgram("waterDynWave2.vp");
	waveNormalFP=LoadFragmentProgram("waterDynNormal.fp");
	waveNormalVP=LoadVertexProgram("waterDynNormal.vp");
	waveCopyHeightFP=LoadFragmentProgram("waterDynWave3.fp");
	waveCopyHeightVP=LoadVertexProgram("waterDynWave3.vp");
	dwGroundRefractVP=LoadVertexProgram("dwgroundrefract.vp");
	dwGroundReflectIVP=LoadVertexProgram("dwgroundreflectinverted.vp");
	dwDetailNormalFP=LoadFragmentProgram("dwDetailNormal.fp");
	dwDetailNormalVP=LoadVertexProgram("dwDetailNormal.vp");
	dwAddSplashFP=LoadFragmentProgram("dwAddSplash.fp");
	dwAddSplashVP=LoadVertexProgram("dwAddSplash.vp");

	waterSurfaceColor = mapInfo->water.surfaceColor;

	for(int y=0;y<1024;++y){
		for(int x=0;x<1024;++x){
			temp[(y*1024+x)*4+0]=0;
			temp[(y*1024+x)*4+1]=0;
			temp[(y*1024+x)*4+2]=0;
			temp[(y*1024+x)*4+3]=0;
		}
	}
	glGenTextures(1, &waveHeight32);
	glBindTexture(GL_TEXTURE_2D, waveHeight32);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	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);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F_ARB ,256, 256, 0,GL_RGBA, GL_FLOAT, temp);

	glGenTextures(1, &waveTex1);
	glBindTexture(GL_TEXTURE_2D, waveTex1);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp);

	for(int y=0;y<1024;++y){
		for(int x=0;x<1024;++x){
			//float dist=(x-500)*(x-500)+(y-450)*(y-450);
			temp[(y*1024+x)*4+0]=0;//max(0.0f,15-sqrt(dist));//sin(y*PI*2.0f/64.0f)*0.5f+0.5f;
			temp[(y*1024+x)*4+1]=0;
			temp[(y*1024+x)*4+2]=0;
			temp[(y*1024+x)*4+3]=0;
		}
	}
	glGenTextures(1, &waveTex2);
	glBindTexture(GL_TEXTURE_2D, waveTex2);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp);

	for(int y=0;y<1024;++y){
		for(int x=0;x<1024;++x){
			temp[(y*1024+x)*4+0]=0;
			temp[(y*1024+x)*4+1]=1;
			temp[(y*1024+x)*4+2]=0;
			temp[(y*1024+x)*4+3]=0;
		}
	}
	glGenTextures(1, &waveTex3);
	glBindTexture(GL_TEXTURE_2D, waveTex3);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp);

	for(int y=0;y<64;++y){
		float dy=y-31.5f;
		for(int x=0;x<64;++x){
			float dx=x-31.5f;
			float dist=sqrt(dx*dx+dy*dy);
			temp[(y*64+x)*4+0]=std::max(0.0f,1-dist/30.f)*std::max(0.0f,1-dist/30.f);
			temp[(y*64+x)*4+1]=std::max(0.0f,1-dist/30.f);
			temp[(y*64+x)*4+2]=std::max(0.0f,1-dist/30.f)*std::max(0.0f,1-dist/30.f);
			temp[(y*64+x)*4+3]=0;
		}
	}

	glGenTextures(1, &splashTex);
	glBindTexture(GL_TEXTURE_2D, splashTex);
	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_WRAP_S,GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	//gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA32F_ARB ,64, 64, GL_RGBA, GL_FLOAT, temp);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp);

	unsigned char temp2[]={0,0,0,0};
	glGenTextures(1, &zeroTex);
	glBindTexture(GL_TEXTURE_2D, zeroTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,1, 1, 0,GL_RGBA, GL_UNSIGNED_BYTE, temp2);

	unsigned char temp3[]={0,255,0,0};
	glGenTextures(1, &fixedUpTex);
	glBindTexture(GL_TEXTURE_2D, fixedUpTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,1, 1, 0,GL_RGBA, GL_UNSIGNED_BYTE, temp3);

	CBitmap bm;
	if (!bm.Load("bitmaps/boatshape.bmp"))
		throw content_error("Could not load boatshape from file bitmaps/boatshape.bmp");
	for(int a=0;a<bm.xsize*bm.ysize;++a){
		bm.mem[a*4+2]=bm.mem[a*4];
		bm.mem[a*4+3]=bm.mem[a*4];
	}
	boatShape=bm.CreateTexture();

	CBitmap bm2;
	if (!bm.Load("bitmaps/hovershape.bmp"))
		throw content_error("Could not load hovershape from file bitmaps/hovershape.bmp");
	for(int a=0;a<bm2.xsize*bm2.ysize;++a){
		bm2.mem[a*4+2]=bm2.mem[a*4];
		bm2.mem[a*4+3]=bm2.mem[a*4];
	}
	hoverShape=bm2.CreateTexture();

	delete[] temp;
	glGenFramebuffersEXT(1,&frameBuffer);

	reflectFBO.Bind();
	reflectFBO.AttachTexture(reflectTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT);
	reflectFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT32, 512, 512);
	refractFBO.Bind();
	refractFBO.AttachTexture(refractTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT);
	refractFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT32, refractSize, refractSize);
	FBO::Unbind();

	if (!reflectFBO.IsValid() || !refractFBO.IsValid())
		throw content_error("DynWater Error: Invalid FBO");
}
bool CNamedTextures::Load(const string& texName, GLuint texID)
{
	//! strip off the qualifiers
	string filename = texName;
	bool border  = false;
	bool clamped = false;
	bool nearest = false;
	bool linear  = false;
	bool aniso   = false;
	bool invert  = false;
	bool greyed  = false;
	bool tint    = false;
	float tintColor[3];
	bool resize  = false;
	int2 resizeDimensions;

	if (filename[0] == ':') {
		int p;
		for (p = 1; p < (int)filename.size(); p++) {
			const char ch = filename[p];
			if (ch == ':')      { break; }
			else if (ch == 'n') { nearest = true; }
			else if (ch == 'l') { linear  = true; }
			else if (ch == 'a') { aniso   = true; }
			else if (ch == 'i') { invert  = true; }
			else if (ch == 'g') { greyed  = true; }
			else if (ch == 'c') { clamped = true; }
			else if (ch == 'b') { border  = true; }
			else if (ch == 't') {
				const char* cstr = filename.c_str() + p + 1;
				const char* start = cstr;
				char* endptr;
				tintColor[0] = (float)strtod(start, &endptr);
				if ((start != endptr) && (*endptr == ',')) {
					start = endptr + 1;
					tintColor[1] = (float)strtod(start, &endptr);
					if ((start != endptr) && (*endptr == ',')) {
						start = endptr + 1;
						tintColor[2] = (float)strtod(start, &endptr);
						if (start != endptr) {
							tint = true;
							p += (endptr - cstr);
						}
					}
				}
			}
			else if (ch == 'r') {
				const char* cstr = filename.c_str() + p + 1;
				const char* start = cstr;
				char* endptr;
				resizeDimensions.x = (int)strtoul(start, &endptr, 10);
				if ((start != endptr) && (*endptr == ',')) {
					start = endptr + 1;
					resizeDimensions.y = (int)strtoul(start, &endptr, 10);
					if (start != endptr) {
						resize = true;
						p += (endptr - cstr);
					}
				}
			}
		}
		if (p < (int)filename.size()) {
			filename = filename.substr(p + 1);
		} else {
			filename.clear();
		}
	}

	//! get the image
	CBitmap bitmap;
	TexInfo texInfo;

	if (!bitmap.Load(filename)) {
		texMap[texName] = texInfo;
		glBindTexture(GL_TEXTURE_2D, 0);
		return false;
	}

	if (bitmap.type == CBitmap::BitmapTypeDDS) {
		texID = bitmap.CreateDDSTexture(texID);
	} else {
		if (resize) {
			bitmap = bitmap.CreateRescaled(resizeDimensions.x,resizeDimensions.y);
		}
		if (invert) {
			bitmap.InvertColors();
		}
		if (greyed) {
			bitmap.GrayScale();
		}
		if (tint) {
			bitmap.Tint(tintColor);
		}


		//! make the texture
		glBindTexture(GL_TEXTURE_2D, texID);

		if (clamped) {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		}

		if (nearest || linear) {
			if (border) {
				GLfloat white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
				glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, white);
			}

			if (nearest) {
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			} else {
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			}

			//! Note: NPOTs + nearest filtering seems broken on ATIs
			if ( !(count_bits_set(bitmap.xsize)==1 && count_bits_set(bitmap.ysize)==1) &&
				(!GLEW_ARB_texture_non_power_of_two || (gu->atiHacks && nearest)) )
			{
				bitmap = bitmap.CreateRescaled(next_power_of_2(bitmap.xsize),next_power_of_2(bitmap.ysize));
			}

			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
						bitmap.xsize, bitmap.ysize, border ? 1 : 0,
						GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
		} else {
			//! MIPMAPPING (default)
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

			if ((count_bits_set(bitmap.xsize)==1 && count_bits_set(bitmap.ysize)==1) ||
				GLEW_ARB_texture_non_power_of_two)
			{
				glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, bitmap.xsize, bitmap.ysize,
							GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
			} else {
				//! glu auto resizes to next POT
				gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, bitmap.xsize, bitmap.ysize,
								GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
			}
		}

		if (aniso && GLEW_EXT_texture_filter_anisotropic) {
			static GLfloat maxAniso = -1.0f;
			if (maxAniso == -1.0f) {
				glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
			}
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
		}
	}

	texInfo.id    = texID;
	texInfo.type  = bitmap.type;
	texInfo.xsize = bitmap.xsize;
	texInfo.ysize = bitmap.ysize;

	texMap[texName] = texInfo;

	return true;
}
Exemple #10
0
bool CTextureAtlas::CreateTexture()
{
	const int2 atlasSize = atlasAllocator->GetAtlasSize();
	const int maxMipMaps = atlasAllocator->GetMaxMipMaps();

	// ATI drivers like to *crash* in glTexImage if x=0 or y=0
	if (atlasSize.x <= 0 || atlasSize.y <= 0) {
		LOG_L(L_ERROR, "[TextureAtlas::%s] bad allocation for atlas \"%s\" (size=<%d,%d>)", __func__, name.c_str(), atlasSize.x, atlasSize.y);
		return false;
	}

	PBO pbo;
	pbo.Bind();
	pbo.New(atlasSize.x * atlasSize.y * 4);

	unsigned char* data = reinterpret_cast<unsigned char*>(pbo.MapBuffer(GL_WRITE_ONLY));

	if (data != nullptr) {
		// make spacing between textures black transparent to avoid ugly lines with linear filtering
		std::memset(data, 0, atlasSize.x * atlasSize.y * 4);

		for (const MemTex& memTex: memTextures) {
			const float4 texCoords = atlasAllocator->GetTexCoords(memTex.names[0]);
			const float4 absCoords = atlasAllocator->GetEntry(memTex.names[0]);

			const int xpos = absCoords.x;
			const int ypos = absCoords.y;

			const AtlasedTexture tex(texCoords);

			for (size_t n = 0; n < memTex.names.size(); ++n) {
				textures[memTex.names[n]] = tex;
			}

			for (int y = 0; y < memTex.ysize; ++y) {
				int* dst = ((int*)           data  ) + xpos + (ypos + y) * atlasSize.x;
				int* src = ((int*)memTex.mem.data()) +        (       y) * memTex.xsize;

				memcpy(dst, src, memTex.xsize * 4);
			}
		}

		if (debug) {
			CBitmap tex(data, atlasSize.x, atlasSize.y);
			tex.Save(name + "-" + IntToString(atlasSize.x) + "x" + IntToString(atlasSize.y) + ".png");
		}
	} else {
		LOG_L(L_ERROR, "[TextureAtlas::%s] failed to map PBO for atlas \"%s\" (size=<%d,%d>)", __func__, name.c_str(), atlasSize.x, atlasSize.y);
	}

	pbo.UnmapBuffer();


	glGenTextures(1, &atlasTexID);
	glBindTexture(GL_TEXTURE_2D, atlasTexID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : 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);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  maxMipMaps);
	if (maxMipMaps > 0) {
		glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, atlasSize.x, atlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); //FIXME disable texcompression, PBO
	} else {
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atlasSize.x, atlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr());
	}

	pbo.Invalidate();
	pbo.Unbind();

	return (data != nullptr);
}
Exemple #11
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);
}
C3DOTextureHandler::C3DOTextureHandler()
{
	std::vector<TexFile*> texfiles = LoadTexFiles();

	// TODO: make this use TextureAtlas directly
	CTextureAtlas atlas;
	atlas.SetName("3DOModelTextureAtlas");

	IAtlasAllocator* atlasAlloc = atlas.GetAllocator();

	// NOTE: most Intels report maxTextureSize=2048, some even 1024 (!)
	atlasAlloc->SetNonPowerOfTwo(globalRendering->supportNPOTs);
	atlasAlloc->SetMaxSize(std::min(globalRendering->maxTextureSize, 2048), std::min(globalRendering->maxTextureSize, 2048));

	// default for 3DO primitives that point to non-existing textures
	textures["___dummy___"] = UnitTexture(0.0f, 0.0f, 1.0f, 1.0f);

	for (std::vector<TexFile*>::iterator it = texfiles.begin(); it != texfiles.end(); ++it) {
		atlasAlloc->AddEntry((*it)->name, int2((*it)->tex.xsize, (*it)->tex.ysize));
	}

	const bool allocated = atlasAlloc->Allocate();
	const int2 curAtlasSize = atlasAlloc->GetAtlasSize();
	const int2 maxAtlasSize = atlasAlloc->GetMaxSize();

	if (!allocated) {
		// either the algorithm simply failed to fit all
		// textures or the textures would really not fit
		LOG_L(L_WARNING,
			"[%s] failed to allocate 3DO texture-atlas memory (size=%dx%d max=%dx%d)",
			__FUNCTION__,
			curAtlasSize.x, curAtlasSize.y,
			maxAtlasSize.x, maxAtlasSize.y
		);
		return;
	} else {
		assert(curAtlasSize.x <= maxAtlasSize.x);
		assert(curAtlasSize.y <= maxAtlasSize.y);
	}

	unsigned char* bigtex1 = new unsigned char[curAtlasSize.x * curAtlasSize.y * 4];
	unsigned char* bigtex2 = new unsigned char[curAtlasSize.x * curAtlasSize.y * 4];

	for (int a = 0; a < (curAtlasSize.x * curAtlasSize.y); ++a) {
		bigtex1[a*4 + 0] = 128;
		bigtex1[a*4 + 1] = 128;
		bigtex1[a*4 + 2] = 128;
		bigtex1[a*4 + 3] = 0;

		bigtex2[a*4 + 0] = 0;
		bigtex2[a*4 + 1] = 128;
		bigtex2[a*4 + 2] = 0;
		bigtex2[a*4 + 3] = 255;
	}

	for (std::vector<TexFile*>::iterator it = texfiles.begin(); it != texfiles.end(); ++it) {
		CBitmap& curtex1 = (*it)->tex;
		CBitmap& curtex2 = (*it)->tex2;

		const size_t foundx = atlasAlloc->GetEntry((*it)->name).x;
		const size_t foundy = atlasAlloc->GetEntry((*it)->name).y;
		const float4 texCoords = atlasAlloc->GetTexCoords((*it)->name);

		for (int y = 0; y < curtex1.ysize; ++y) {
			for (int x = 0; x < curtex1.xsize; ++x) {
				for (int col = 0; col < 4; ++col) {
					bigtex1[(((foundy + y) * curAtlasSize.x + (foundx + x)) * 4) + col] = curtex1.mem[(((y * curtex1.xsize) + x) * 4) + col];
					bigtex2[(((foundy + y) * curAtlasSize.x + (foundx + x)) * 4) + col] = curtex2.mem[(((y * curtex1.xsize) + x) * 4) + col];
				}
			}
		}

		textures[(*it)->name] = UnitTexture(texCoords);

		delete (*it);
	}

	const int maxMipMaps = atlasAlloc->GetMaxMipMaps();

	{
		glGenTextures(1, &atlas3do1);
		glBindTexture(GL_TEXTURE_2D, atlas3do1);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  maxMipMaps);
		if (maxMipMaps > 0) {
			glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, curAtlasSize.x, curAtlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); //FIXME disable texcompression
		} else {
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, curAtlasSize.x, curAtlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1);
		}
	}
	{
		glGenTextures(1, &atlas3do2);
		glBindTexture(GL_TEXTURE_2D, atlas3do2);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_NEAREST_MIPMAP_NEAREST : 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);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  maxMipMaps);
		if (maxMipMaps > 0) {
			glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, curAtlasSize.x, curAtlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); //FIXME disable texcompression
		} else {
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, curAtlasSize.x, curAtlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2);
		}
	}

	if (CTextureAtlas::GetDebug()) {
		CBitmap tex1(bigtex1, curAtlasSize.x, curAtlasSize.y);
		CBitmap tex2(bigtex2, curAtlasSize.x, curAtlasSize.y);

		tex1.Save(atlas.GetName() + "-1-" + IntToString(curAtlasSize.x) + "x" + IntToString(curAtlasSize.y) + ".png");
		tex2.Save(atlas.GetName() + "-2-" + IntToString(curAtlasSize.x) + "x" + IntToString(curAtlasSize.y) + ".png");
	}

	delete[] bigtex1;
	delete[] bigtex2;
}