Question about AtlasedTexture

Question about AtlasedTexture

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Question about AtlasedTexture

Post by Argh »

Very simple (at least, I hope) question:

What order are the pictures put into AtlasedTexture? By alphanumeric name?

If so, I probably have a perma-fix for the black-lines bug.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

No.

If I recall correctly, they are sorted on size. The biggest texture goes first, in the top left corner, smaller textures around that one, etc. That way you have the least amount of unused texture surface.

No clue what happens if all sizes are equal tho, possibly they're in the order read from the tdf then, but (more probably) it is random.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

At random??? Doh... that might just put a wee crimp on things. Size, I can deal with, though. I will get back to y'all about this... had another bright idea that might cure it, while I've been away from my desk at home.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

Well, "undefined" order. That's a better word for it. Obviously they aren't intentionally shuffled everytime spring runs or something stupid like that.

ProjectileHandler.cpp:

Code: Select all

	//add all textures in projectiletextures section
	std::map<std::string,std::string> ptex = resources.GetAllValues("resources\\graphics\\projectiletextures");
	for(std::map<std::string,std::string>::iterator pi=ptex.begin(); pi!=ptex.end(); ++pi)
	{
		textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
	}
	//add all texture from sections within projectiletextures section
	std::vector<std::string> seclist = resources.GetSectionList("resources\\graphics\\projectiletextures");
	for(int i=0; i<seclist.size(); i++)
	{
		std::map<std::string,std::string> ptex2 = resources.GetAllValues("resources\\graphics\\projectiletextures\\" + seclist[i]);
		for(std::map<std::string,std::string>::iterator pi=ptex2.begin(); pi!=ptex2.end(); ++pi)
		{
			textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
		}
	}

	for(int i=0; i<12; i++)
	{
		char num[10];
		sprintf(num, "%02i", i);
		textureAtlas->AddTexFromFile(std::string("ismoke") + num, std::string("bitmaps/")+resources.SGetValueDef(std::string("smoke/smoke") + num +".tga",std::string("resources\\graphics\\smoke\\smoke")+num+"alpha"));
	}

	char tex[128][128][4];
	for(int y=0;y<128;y++){//shield
		for(int x=0;x<128;x++){
			tex[y][x][0]=70;
			tex[y][x][1]=70;
			tex[y][x][2]=70;
			tex[y][x][3]=70;
		}
	}
	textureAtlas->AddTexFromMem("perlintex", 128, 128, CTextureAtlas::RGBA32, tex);
Within the first two loops, std::map is used, which is a sorted container (ascending on the first item, the key), so per loop (read: per section in the resources.tdf) the textures are inserted in alphabetical lexicographical order (of the key, ie. the word before the '=' in the tdf ;-) ).

When the atlas is finalized however, the array of textures is sorted on size (first descending y size, second descending x size) using std::sort. std::sort isn't guaranteed to keep the ordering of equal elements in tact. In this case, equal means "of equal size". Hence the order is undefined.

What would your perma fix be anyway?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

That depends on the results of some tests, but here are the two things that could fix this, short of doing so automatically:

1. Insert named bitmaps with 0,0,0 alpha values into the AtlasedTexture (now that I understand the rules, this should be trivial) forming "rows" of clear-alpha textures. I'd use names and sizes to sort them and put buffers in between them.

2. Hopefully, this will work, as this is a better plan... I'd just re-adjust the textures that are not using the alpha, and give them a mask around non-black pixels, so that they will have a border of clear... and readjust texture sizes, if needbe, to provide a 1-5 pixel pure black border around them.

Basically, I think that what's happening is that textures aren't quite clamping right. They're occasionally reading nearby textures that have pure-white alpha channels, which results in the black lines- they're actually reading pixels from the texture to one side or another. This would account for the fact that this problem doesn't affect every single texture- just some of them.

A truely permanent fix for this problem would be to place all the textures with a 4-pixel clear offset between them, so that anisotropic filtering / antialiasing could be used without causing a problem. This would, of course, waste texture space, but I have yet to use up anywhere near the max. Yes, future mods might possibly use it all up... but I doubt it, until we have the ability to animate our particles (heh, yeah, I want that of course).
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

The solution for this turned out to be a lot easier than I thought it would be. Basically, I just identified the bitmaps that were causing problems (not all of them were- it was mainly some smoke/fire stuff that I re-use a lot) and added a 5-pixel border of pure black around them both in texture and in alpha. That seems to have totally cured this problem. I was being too aggressive about getting up to the edges of the squares, and was also being too aggressive about keeping them as small as possible and always keeping them powers of 2, when I have plenty of texture space to waste.

Now, that said... is there a way to get the AtlasedTexture DDS file to be output to disk, so that I can actually SEE what Spring has been doing? That would help tremendously in further thinking about this problem, and seeing if I can come up with a more... elegant... solution.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

Not without recompiling at this moment, but I could try to remember to add an commandline option to do that (code is there, just commented out ;-)).

And btw, they aren't DDS, they're a "normal" texture IIRC.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Ah. Thought it was a DDS, based on some stuff that I remember reading from SJ, but that had to do with the atlas for 3DO files, so I'm probably just completely confused ;)

And yeah, I think that might be worth it. Especially if we get to the point where we are able to animate the textures being displayed on the particles- optimization and clever use of the available space is going to be a bigger deal then.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

Latest build has a /t commandline option that causes spring to save all finalized textureatlases to disk. (textureatlas1.png etc.)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Cool! I'll test it out, and see what it's doing/not doing. It may give me some additional answers to these problems. My quick-and-dirty fix for the black-lines problem seems to have worked, but understanding the results of the process might be very handy :-)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Thanks Tobi! I solved a couple of nagging graphical glitches very easily, by studying the PNG output and seeing how it sorts the files.

Basically, for those interested, it sorts by size Y, then size X, then by name. So, for example, if you have a fairly long texture and you need a "buffer" of blank between it and its neighbors, you can simply make two blank clones of the same dimensions, and name them, "001_blank, 002_theRealTexture, 003_blank" in the filenames and in Resources, and Spring will always sort them so that the two blanks are to either side.
Post Reply

Return to “Engine”