Beispiel #1
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;
}
Beispiel #2
0
void CTextureAtlas::CreateTexture()
{
	PBO pbo;
	pbo.Bind();
	pbo.Resize(xsize * ysize * 4);
	unsigned char* data = (unsigned char*)pbo.MapBuffer(GL_WRITE_ONLY);
	std::memset(data, 0, xsize * ysize * 4); //! make spacing between textures black transparent to avoid ugly lines with linear filtering

	for (size_t i = 0; i < memtextures.size(); ++i) {
		MemTex& tex = *memtextures[i];
		for (int y = 0; y < tex.ysize; ++y) {
			int* dst = ((int*)data) + tex.xpos + (tex.ypos + y) * xsize;
			int* src = ((int*)tex.data) + y * tex.xsize;
			memcpy(dst, src, tex.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);

		//! even pbo.MapBuffer(GL_WRITE_ONLY) we can readback from it. GL_READ is only needed if we want to readback GPU data!
		CBitmap save(data,xsize,ysize);
		save.Save(fname);
		logOutput.Print("Saved finalized textureatlas to '%s'.", fname);
	}

	pbo.UnmapBuffer();

	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, GL_NEAREST/*GL_NEAREST_MIPMAP_LINEAR*/);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_CLAMP);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, xsize, ysize, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr());

	pbo.Unbind();

	initialized = true;
}
Beispiel #3
0
PBO* GLResource::getPBO( int size )
{
	int i;
	int supindex = -1, infindex = -1;
	int supdelta = 0, infdelta = 0;

	/*int total = 0;
	for ( i = 0; i < pboList.count(); ++i )
		total += pboList.at(i)->size();
	qDebug() << "Total PBO bytes :" << total << pboList.count();*/

	for ( i = 0; i < pboList.count(); ++i ) {
		PBO *p = pboList.at(i);
		if ( p->isFree() ) {
			if ( p->size() == size ) {
				p->setFree( false );
				return p;
			}
			if ( p->size() > size ) {
				int d = p->size() - size;
				if ( supindex == -1 || d < supdelta ) {
					supdelta = d;
					supindex = i;
				}
			}
			else {
				int d = size - p->size();
				if ( infindex == -1 || d < infdelta ) {
					infdelta = d;
					infindex = i;
				}
			}
		}
	}

	if ( supindex != -1 ) {
		PBO *p = pboList.at( supindex );
		p->setFree( false );
		return p;
	}

	if ( infindex != -1 ) {
		PBO *p = pboList.at( infindex );
		if ( !p->resize( size ) ) {
			qDebug() << "pbo resize error";
			return NULL;
		}
		p->setFree( false );
		return p;
	}

	PBO *p = new PBO( size );
	if ( !p->isValid() ) {
		delete p;
		qDebug() << "new pbo error";
		return NULL;
	}

	pboList.append( p );
	p->setFree( false );
	return p;
}
Beispiel #4
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;
}
Beispiel #5
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);
}