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.
Question about AtlasedTexture
Moderator: Moderators
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.
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.
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:
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?
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);

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?
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).
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).
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.
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.
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.

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.
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.
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.