9

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?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Nico Cvitak
  • 471
  • 4
  • 7
  • 1
    Try spriteNodeWithTexture: without specifying size, does that make a difference? For me nearest filter with atlas textures works, I haven't tried changing the sprite rect on init though. You can still scale the sprite after creating it via xScale/yScale. – CodeSmile Nov 15 '13 at 12:30
  • Alright I tried that and I get the same result :( – Nico Cvitak Nov 15 '13 at 18:51
  • I couldn't get your way working but isntead of setting the size in the init, i set the size afterwards is `[node setSize:];` and it worked – John Riselvato Nov 17 '13 at 21:52
  • I am using a 64x64 texture and I have an object called GrassNode which inherits from SKSpriteNode, which I originally had the size and scale code which failed. Now when I declare the GrassNode in the scene and use [grass setSize:CGSizeMake(1,1)]; it still fails. Can you describe to me your layout and maybe I can figure it out. – Nico Cvitak Nov 18 '13 at 00:31
  • If it comes out that there is not actual solution to my problem, I'll probably just upscale my textures so they remain sharp at higher resolutions. – Nico Cvitak Nov 18 '13 at 04:08

3 Answers3

4

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.

Theis Egeberg
  • 2,556
  • 21
  • 30
  • 1
    It's not two different instantiations of the same texture atlas. It's actually two physically different folders (pixelArt.atlas and normalTextures.atlas). When I load them in I set the filtering mode on them and it affects all the sprites with textures from them. – Theis Egeberg Mar 07 '14 at 18:40
3

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;
}
dave
  • 1,150
  • 1
  • 13
  • 22
1

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.

Darren
  • 11
  • 1