Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use SKTextureFilteringNearest with SKTextureAtlas

I seem to be having a problem using SKTextureAtlas and nearest neighbor filtering for textures. When I used the nearest neighbor filtering without SKTextureAtlas it works fine, but everything is just changed to linear filtering when I use an SKTextureAtlas.

Code and Result Without SKTextureAtlas:

SKTexture* texture = [SKTexture textureWithImageNamed:@"grass"];
texture.filteringMode = SKTextureFilteringNearest;
SKSpriteNode* node = [SKSpriteNode spriteNodeWithTexture:texture size:CGSizeMake(512,512)];

Should Produce Nearest Neighbor Filtering & Does enter image description here

Code and Result With SKTextureAtlas:

SKTextureAtlas* atlas = [SKTextureAtlas atlasNamed:@"myAtlas"];
SKTexture* texture = [atlas textureNamed:@"grass"];
texture.filteringMode = SKTextureFilteringNearest;
SKSpriteNode* node = [SKSpriteNode spriteNodeWithTexture:texture size:CGSizeMake(512,512)];

Should Produce Nearest Neighbor Filtering & DOES NOT enter image description here

Any suggestions?

like image 927
Nico Cvitak Avatar asked Nov 15 '13 01:11

Nico Cvitak


3 Answers

I have been struggling with exactly the same problem.

It seems that when you set the filtering mode for a SKTexture coming from an SKTextureAtlas it sets the filtering mode for everything coming out of that atlas.

I ended up solving it by making two SKTextureAtlas's (AtlasLinear and AtlasNearest). One is for my normal artwork the other is for pixelart. This works as a charm.

However with very small atlasses I sometimes get weird small pixel errors. If this pops up for you, it actually helps to add some big white block png's to your pixel art atlas.

Good luck.

like image 132
Theis Egeberg Avatar answered Oct 14 '22 17:10

Theis Egeberg


This is indeed a bizarre problem. It seems to me that there is a missing API: [SKTextureAtlas atlasNamed:atlasName withFilteringMode:filteringMode]

In lieu of such an API for the time being, I use the following method:

-(SKTextureAtlas *) textureAtlasWithName:(NSString *)atlasName filteringMode:(SKTextureFilteringMode)filteringMode {

    SKTextureAtlas * result = [SKTextureAtlas atlasNamed:atlasName];

    NSArray * textureNames = [result textureNames];

    if ([textureNames count] > 0) {
        SKTexture * aTexture = [result textureNamed:[textureNames lastObject]];
        [aTexture setFilteringMode:filteringMode];

    } else {
        NSLog(@"WARNING: couldn't find any textures in the atlas %@; filtering mode set likely failed.", result);
    }

    return result;
}
like image 32
dave Avatar answered Oct 14 '22 16:10

dave


I managed to solve this problem in my program. What I have found out is that if a texture atlas is instantiated more than once, even if all texture loads from the atlases are set to SKTextureFilteringNearest, the textures are rendered with the linear filtering. What I ended up doing is provide my atlas through a singleton and made sure all textures load with filtering set to SKTextureFilteringNearest and it worked perfectly.

like image 40
Darren Avatar answered Oct 14 '22 16:10

Darren