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:
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];
}
}