我有一个SKSpriteNode,我希望在它的边缘有一个蓝色的光晕,以便突出显示。我猜我需要让我的sprite成为SKEffectNode的子级,然后创建/应用某种过滤器。
更新:我已经用选择答案的方法对此进行了相当多的研究,发现即使您将其设置为shouldRasterize并且定义了'no filter‘,SKEffectNode在性能上也有相当大的影响。我的结论是,如果你的游戏一次需要10个以上的移动对象,即使光栅化了,它们也不会涉及SKEffectNode。
我的解决方案可能会涉及预先渲染的发光图像/动画,因为SKEffectNode不会根据我的要求对其进行裁剪。
如果有人能洞察到我遗漏的任何东西,我将不胜感激!
我接受一个答案,因为它确实实现了我所要求的,但我想将这些注释添加到任何想要走这条路的人,这样你就可以意识到使用SKEffectNode的一些问题。
发布于 2014-02-06 03:16:39
@rickster的答案很棒。由于我的代表性很低,我显然不允许将这段代码作为注释添加到他的代码中。我希望这不会违反stackoverflow规则。我不想以任何方式使用他的代表。
以下是他在回答中所描述的代码:
标题:
// ENHGlowFilter.h
#import <CoreImage/CoreImage.h>
@interface ENHGlowFilter : CIFilter
@property (strong, nonatomic) UIColor *glowColor;
@property (strong, nonatomic) CIImage *inputImage;
@property (strong, nonatomic) NSNumber *inputRadius;
@property (strong, nonatomic) CIVector *inputCenter;
@end
//Based on ASCGLowFilter from Apple实施:
#import "ENHGlowFilter.h"
@implementation ENHGlowFilter
-(id)init
{
self = [super init];
if (self)
{
_glowColor = [UIColor whiteColor];
}
return self;
}
- (NSArray *)attributeKeys {
return @[@"inputRadius", @"inputCenter"];
}
- (CIImage *)outputImage {
CIImage *inputImage = [self valueForKey:@"inputImage"];
if (!inputImage)
return nil;
// Monochrome
CIFilter *monochromeFilter = [CIFilter filterWithName:@"CIColorMatrix"];
CGFloat red = 0.0;
CGFloat green = 0.0;
CGFloat blue = 0.0;
CGFloat alpha = 0.0;
[self.glowColor getRed:&red green:&green blue:&blue alpha:&alpha];
[monochromeFilter setDefaults];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:red] forKey:@"inputRVector"];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:green] forKey:@"inputGVector"];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:blue] forKey:@"inputBVector"];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:alpha] forKey:@"inputAVector"];
[monochromeFilter setValue:inputImage forKey:@"inputImage"];
CIImage *glowImage = [monochromeFilter valueForKey:@"outputImage"];
// Scale
float centerX = [self.inputCenter X];
float centerY = [self.inputCenter Y];
if (centerX > 0) {
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, centerX, centerY);
transform = CGAffineTransformScale(transform, 1.2, 1.2);
transform = CGAffineTransformTranslate(transform, -centerX, -centerY);
CIFilter *affineTransformFilter = [CIFilter filterWithName:@"CIAffineTransform"];
[affineTransformFilter setDefaults];
[affineTransformFilter setValue:[NSValue valueWithCGAffineTransform:transform] forKey:@"inputTransform"];
[affineTransformFilter setValue:glowImage forKey:@"inputImage"];
glowImage = [affineTransformFilter valueForKey:@"outputImage"];
}
// Blur
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[gaussianBlurFilter setDefaults];
[gaussianBlurFilter setValue:glowImage forKey:@"inputImage"];
[gaussianBlurFilter setValue:self.inputRadius ?: @10.0 forKey:@"inputRadius"];
glowImage = [gaussianBlurFilter valueForKey:@"outputImage"];
// Blend
CIFilter *blendFilter = [CIFilter filterWithName:@"CISourceOverCompositing"];
[blendFilter setDefaults];
[blendFilter setValue:glowImage forKey:@"inputBackgroundImage"];
[blendFilter setValue:inputImage forKey:@"inputImage"];
glowImage = [blendFilter valueForKey:@"outputImage"];
return glowImage;
}
@end使用中:
@implementation ENHMyScene //SKScene subclass
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
[self setAnchorPoint:(CGPoint){0.5, 0.5}];
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
SKEffectNode *effectNode = [[SKEffectNode alloc] init];
ENHGlowFilter *glowFilter = [[ENHGlowFilter alloc] init];
[glowFilter setGlowColor:[[UIColor redColor] colorWithAlphaComponent:0.5]];
[effectNode setShouldRasterize:YES];
[effectNode setFilter:glowFilter];
[self addChild:effectNode];
_effectNode = effectNode;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
sprite.position = location;
[self.effectNode addChild:sprite];
}
}发布于 2013-10-08 08:58:27
通过创建由多个内置滤镜组成的CIFilter子类,可以在核心图像中创建发光效果。这样的筛选器将涉及如下步骤:
CIColorMatrix来创建输入图像的单色版本。在发光图像(CISourceOverCompositing).上按CIAffineTransform+ CIGaussianBlur).
一旦拥有了完成所有这些任务的CIFilter子类,您就可以将其与SKEffectNode一起使用,以在效果节点的子节点周围获得实时光晕。它在iPad 4上的“雪碧包游戏”Xcode模板中运行:

我从WWDC2013的Scene Kit演示文稿中抄袭了用于类似效果的自定义过滤器类,并在几分钟内将其启动并运行--从developer.apple.com/downloads的WWDC示例代码包中获取它,并查找ASCGlowFilter类。(如果您希望在iOS上使用该代码,则需要将NSAffineTransform部件更改为使用CGAffineTransform。我还用CIVector类型的inputCenter参数替换了centerX和centerY属性,这样Sprite Kit就可以自动将效果居中放置在sprite上。)
我说过“实时”发光了吗?是啊!这是“真正消耗CPU时间”的缩写。请注意,在屏幕截图中,即使只有一艘宇宙飞船,它也不再固定在60fps --并且使用iOS模拟器上的OpenGL ES渲染器,它以幻灯片的速度运行。如果你用的是Mac,你可能有多余的芯片...但如果你想在游戏中做到这一点,请记住以下几点:
shouldRasterize设置为YES应该会有很大帮助。(实际上,在这种情况下,您可能会通过旋转效果节点而不是其中的精灵来获得一些改进。)发布于 2013-10-07 20:34:40
您可以在sprite后面使用SKShapeNode,并使用它的glowWidth和strokeColor属性定义光晕。如果大小和位置正确,这应该会给你一个光晕的外观。这并没有为您提供太多的自定义选项,但我认为这比使用带有SKEffectNode的CIFilter要容易得多,这可能是您在这方面的另一个合理选择。
https://stackoverflow.com/questions/19214040
复制相似问题