SKLightNode 投射阴影问题

7

我在尝试让 SKSpriteNode 同时投射阴影并在进入同一光源的阴影中消失时没有成功。我可以做到其中一个,但不是两个都能实现。

根据文档: 如果精灵在光线投射的阴影内,并且精灵的z位置低于光线,则阴影会影响精灵的照明。 我已经完成了所有这些操作。我的SKLightNode的zPosition为100,所有其他节点的zPositions都较低。

我尝试过所有关于 lightingBitMask、shadowCastBitMask 和 shadowedBitMask 的设置组合,但都没有效果。

我在下面发布了复制了问题的代码。蓝色的方块投射出阴影,但没有被墙上的阴影覆盖。紫色的方块不投射阴影,并被墙上的阴影覆盖。

光源会响应触摸移动,欢迎随意在屏幕上移动它。该项目处于横向模式。

我缺少什么或者没有看到什么?

#import "GameScene.h"

@implementation GameScene {
    SKSpriteNode *lightBulb;
}

-(void)didMoveToView:(SKView *)view {

    typedef NS_OPTIONS(uint32_t, Level1LightCategory)
    {
        CategoryLightPlayer            = 1 << 0,
    };

    SKSpriteNode *worldNode = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(1136, 640)];
    worldNode.zPosition = 10;
    //worldNode.position = CGPointMake(self.size.width/2, self.size.height/2);
    [self addChild:worldNode];

    lightBulb = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(20, 20)];
    lightBulb.zPosition = 100;
    lightBulb.position = CGPointMake(50, 50);
    [worldNode addChild:lightBulb];

    SKLightNode *light = [[SKLightNode alloc] init];
    //light.zPosition = 100; // <- tried setting this again but to no effect
    light.categoryBitMask = CategoryLightPlayer;
    light.falloff = 0.3;
    light.ambientColor = [UIColor whiteColor];
    light.lightColor = [[UIColor alloc] initWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
    light.shadowColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
    [lightBulb addChild:light];

    SKSpriteNode *wall = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10, 300)];
    wall.zPosition = 50;
    wall.position = CGPointMake(500, 200);
    wall.lightingBitMask = CategoryLightPlayer;
    wall.shadowCastBitMask = CategoryLightPlayer;
    wall.shadowedBitMask = 0x00000000;
    [worldNode addChild:wall];

    SKSpriteNode *box0 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(30, 30)];
    box0.zPosition = 40;
    box0.position = CGPointMake(800, 200);
    box0.lightingBitMask = CategoryLightPlayer;
    box0.shadowCastBitMask = CategoryLightPlayer;
    box0.shadowedBitMask = CategoryLightPlayer;
    [worldNode addChild:box0];

    SKSpriteNode *box1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(30, 30)];
    box1.zPosition = 40;
    box1.position = CGPointMake(800, 300);
    box1.lightingBitMask = CategoryLightPlayer;
    //box1.shadowCastBitMask = CategoryLightPlayer;
    //box1.shadowedBitMask = CategoryLightPlayer;
    [worldNode addChild:box1];  
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self.scene];

    lightBulb.position = touchLocation;
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self.scene];

    lightBulb.position = touchLocation;
}

-(void)update:(CFTimeInterval)currentTime {
    //
}

@end
2个回答

10

我刚刚收到了来自苹果开发技术支持的回复,确认这是SpriteKit (SKLightNode)中存在的一个错误。目前他们还不知道解决此问题的方法,但如果找到解决方案,他们会通知我。

根据他们的要求,我已经提交了一个错误报告。

更新于2015年4月22日

SK工程师确认SpriteKit不支持在同一对象上进行阴影投射和阴影处理。目前没有解决方法。这个问题将在某个时候得到解决。

更新于2015年12月15日

收到了来自苹果公司关于此问题的新回复。

苹果开发者关系部门 2015年12月14日 下午1:35

暂无计划解决此问题。

我们现在将关闭此报告。


1
我使用Xcode 8.3.2进行了测试,似乎已经修复了。我将您的代码放入一个示例项目中,从墙上投射出的阴影将蓝色框隐藏,正如预期的那样。当未被墙阴影覆盖时,蓝色框仍会投射自己的阴影。也许这在最近的SK更新中已经修复了,或者我误解了您的问题。 - BlueBear

-1

我找到了一些解决方法(不确定是否适用于所有情况,但在某些情况下可以): 您可以创建两个(或多个 - 最多32个,据我们所知)不同的光源,并逐个(或按组)为它们分配精灵。然后,阴影将按我们需要的方式组合 - 正确地。

SKLightNode* light1 = [SKLightNode new];
SKLightNode* light2 = [SKLightNode new];

... // init them equally

light1.categoryBitMask = 1;
light2.categoryBitMask = 2;
...

SKSpriteNode* sprite1 = ...
SKSpriteNode* sprite2 = ...

sp1.shadowCastBitMask = 1;
sp1.shadowedBitMask = 1;
sp2.shadowCastBitMask = 2;
sp2.shadowedBitMask = 2;

那不是一个解决方案。问题是一个节点投射阴影时,不能同时被遮挡。创建两个节点并不能解决问题,因为投射阴影的节点不会消失到阴影中。 - sangony
@sangony 我认为解决方法是复制你的灯光和精灵。因此,一个灯光将使精灵投射阴影,另一个灯光将使用相同的纹理对第二个精灵进行阴影处理 - 它们会重叠在一起。因此,其中一个精灵投射的阴影不可见,因为它位于第二个精灵下面 - 而第二个精灵确实投射了阴影。 - Seivan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接