SKSpriteNode lighting doesn't work with textures from SKTextureAtlas
Asked Answered
S

0

6

I ran into a problem with SpriteKit (tried Xcode 7 beta and Xcode 6.4 on OS X 10.11 beta) where normal-mapped lighting breaks down if I create a SKTextureAtlas from the image and normal files that work when used individually. See this example:

enter image description here

From left to right:

  • Sprite with texture + normal + lighting (textures from atlas)
  • Sprite with texture + normal (textures from atlas)
  • Sprite with texture (texture from atlas)
  • Sprite with normal texture (texture from atlas)
  • Sprite with texture + normal + lighting (textures created from individual files via imageNamed:)

The atlas is created at runtime with SKTextureAtlas atlasWithDictionary: and it contains the following textures:

creating atlas with files: {
    "shield-normal.png" = "shield-normal.png";
    "shield.png" = "shield.png";
    "swords-normal.png" = "swords-normal.png";
    "swords.png" = "swords.png";
}

Note: I get the exact same problem if I create the Atlas in Xcode and load it via atlasNamed: - so the problem definitely isn't with how or when the atlas is created, but because the textures are obtained from the atlas in the first place.

If I create the sprite with individual files the lighting works (rightmost image):

tex = [SKTexture textureWithImageNamed:@"shield.png"];
normal = [SKTexture textureWithImageNamed:@"shield-normal.png"];
test2 = [SKSpriteNode spriteNodeWithTexture:tex normalMap:normal];
test2.position = CGPointMake(580, 400);
test2.lightingBitMask = 0xffffffff;
[self addChild:test2];

I do the exact same thing with the atlas files and the screenshot above proves that I do get the correct images (3rd and 4th from left) for the sprite texture and normal as textures from the atlas. Yet the result is the 1st image from the left, a lit sprite without normal mapping.

I wonder, do normal textures require a form of postprocessing that SKTextureAtlas doesn't apply? Or did anyone else have problems with normal textures in a atlas?

Or perhaps this might be a bug?


Update: I have reproduced this behavior in a new SpriteKit app (OS X, download it here and try for yourself) with the following code:

-(void)didMoveToView:(SKView *)view {
    SKLightNode* light = [SKLightNode node];
    light.position = CGPointMake(0, 0);
    [self addChild:light];

    id move1 = [SKAction moveByX:400 y:300 duration:3];
    id move2 = [SKAction moveByX:-400 y:-300 duration:3];
    id repeat = [SKAction repeatActionForever:[SKAction sequence:@[move1, move2]]];
    [light runAction:repeat];


    SKTexture* tex, *nor;
    SKSpriteNode* spr;
    {   // sprite with textures from individual files: lighting works
        tex = [SKTexture textureWithImageNamed:@"shield.png"];
        nor = [SKTexture textureWithImageNamed:@"shield-normal.png"];
        spr = [SKSpriteNode spriteNodeWithTexture:tex normalMap:nor];
        spr.position = CGPointMake(111, 111);
        spr.lightingBitMask = 0xffffffff;
        [self addChild:spr];
    }
    {   // sprite with textures from atlas: lighting does not work (no normal-map)
        SKTextureAtlas* atlas = [SKTextureAtlas atlasNamed:@"TicTac"];
        NSLog(@"atlas texture names: %@", atlas.textureNames);

        tex = [atlas textureNamed:@"shield.png"];
        nor = [atlas textureNamed:@"shield-normal.png"];
        spr = [SKSpriteNode spriteNodeWithTexture:tex normalMap:nor];
        spr.position = CGPointMake(222, 111);
        spr.lightingBitMask = 0xffffffff;
        [self addChild:spr];
    }
}
Sorcerer answered 25/8, 2015 at 9:28 Comment(10)
Filed a radar: 22416857Sorcerer
Also occurs on iOS device and simulator. Makes me question whether anyone is actually using these awesome SpriteKit features. :(Sorcerer
The same results on Swift and iOS in Xcode 6.4. I tried with my own images, and the same results...Unmusical
Thanks! I've had to look this up again but yes, lighting and normal textures have been around since iOS 8.0 - and it seems no one complained about this yet (according to google queries). Wow, ouch, wow, ouch ...Sorcerer
Test it on Xcode 7 B6 with new texture atlas on Assets Catalog and the same bug. Images on a Image Set inside the catalog works without problem, but in Texture Atlas doesn't work. Astonishing.Unmusical
Oh, there's a beta 6 now? Thanks for mentioning it. ;)Sorcerer
This is still broken with El Capitan GM seed and Xcode 7.1 beta 1 under both OS X and iOS (8 and 9, simulator and device). I've noticed the draw calls go up for each new object, when a normal map is used from the atlas, so there is no advantage to using an atlas anyway (this was an atlas generated from TexturePacker with the textures and normals in the same atlas).Valerianaceous
:-/ Just ran into this problem. This is bad... as @LearnCocos2D said ... this probably means that no one is using these features... which makes me think how much time they'll take to fix it. Also, if you load the normal map and the texture from different texture atlases it'll look pretty broken. Why would I have the normal map in a different atlas ? Because when I put them together as supposed, the [SKPhysicsBody bodyWithTexture] call failed. Also reported the bug: 23297334Rambling
Still broken :( haven't tested 9.3 beta yet... but might as well just avoid...Nonferrous
@LearnCocos2D I have a similar issue on iOS 10 only, where the normal map just gets flipped vertically. :SAbrahamsen

© 2022 - 2024 — McMap. All rights reserved.