问题描述
我有一个 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在精灵周围创建一个光晕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!