问题描述
我有一个 SKSpriteNode
,我想在它的边缘周围发出蓝色光晕以突出显示.我猜我需要让我的精灵成为 SKEffectNode
的孩子,然后创建/应用某种过滤器.
I have a SKSpriteNode
that I'd like to have a blue glow around it's edges for highlighting purposes. I am guessing that I would need to make my sprite a child of a SKEffectNode
and then create/apply a filter of some sort.
更新:我已经用所选答案的方法对此进行了深入调查,发现 SKEffectNode
即使您将其设置为 shouldRasterize
也会对性能产生相当大的影响并定义了无过滤器".我的结论是,如果您的游戏一次需要超过 10 个移动对象,那么即使光栅化,它们也不能涉及 SKEffectNode
.
UPDATE : I have investigated this quite a it with the chosen answer's approach, and discovered that SKEffectNode
has a sizeable hit on performance even if you have it set to shouldRasterize
and 'no filter' defined. My conclusion is that if your game requires more than 10 moving objects at one time, they can't involve a SKEffectNode
even if rasterized.
我的解决方案可能会涉及预渲染的发光图像/动画,因为 SKEffectNode 不会根据我的要求进行裁剪.
My solution will likely involve pre-rendered glow images/animations, as SKEffectNode is not going to cut it for my requirements.
如果有人对我遗漏的任何事情有洞察力,我会很高兴听到你所知道的一切!
If someone has insight as to anything I am missing, I'd appreciate hearing whatever you know!
我接受了一个答案,因为它确实达到了我的要求,但想将这些注释添加给任何想要走这条路的人,这样您就可以了解使用 SKEffectNode
.
I am accepting an answer because it does achieve what I asked for, but wanted to add these notes to anyone looking to go this route, so you can be aware of some of the issues with using SKEffectNode
.
推荐答案
@rickster 的回答很棒.由于我的代表很低,显然不允许我将此代码添加为他的评论.我希望这不会违反 stackoverflow 的适当规则.我不想以任何方式使用他的代表.
@rickster's answer is great. Since I have low rep, I'm apparently not allowed to add this code as a comment to his. I hope this doesn't break stackoverflow rules of propriety. I'm not trying to userp his rep in any way.
这是他在回答中描述的代码:
Here's code that does what he's describing in his answer:
标题:
// 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];
}
}
这篇关于如何通过 SKEffectNode 在精灵周围创建发光的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!