热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何通过SKEffectNode在精灵周围创建一个辉光-HowcanyoucreateaglowaroundaspriteviaSKEffectNode

IhaveaSKSpriteNodethatIdliketohaveablueglowarounditsedgesforhighlightingpurposes.

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.

我有一个SKSpriteNode我想要在它的边缘周围有一个蓝色的光圈,以突出显示。我猜想,我需要把我的sprite变成一个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.

更新:我用所选答案的方法研究了相当多的it,发现SKEffectNode在性能上受到了很大的影响,即使您将它设置为shouldRasterize和'no filter'。我的结论是,如果你的游戏一次需要10个以上的移动对象,即使是光栅化的,也不能涉及到SKEffectNode。

My solution will likely involve pre-rendered glow images/animations, as SKEffectNode is not going to cut it for my requirements.

我的解决方案可能会涉及预渲染的辉光图像/动画,因为SKEffectNode不会按照我的要求裁剪它。

If someone has insight as to anything I am missing, I'd appreciate hearing whatever you know!

如果有人能洞悉我所错过的一切,我将感激你所知道的一切!

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.

我正在接受一个答案,因为它确实实现了我所要求的,但是想要将这些注释添加到任何想要走这条路线的人,这样您就可以知道使用SKEffectNode的一些问题。

3 个解决方案

#1


27  

@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.

@rickster的回答是伟大的。由于我有一个低代表,我显然不允许添加这段代码作为他的评论。我希望这不会违反stackoverflow的礼节规则。我不会试图以任何方式利用他的代表。

Here's code that does what he's describing in his answer:

这是他在回答中所描述的代码

Header:

标题:

//  ENHGlowFilter.h
#import 

@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

Implementation:

实现:

#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

In use:

在使用:

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

#2


22  

You can create a glow effect in Core Image by creating a CIFilter subclass that composes multiple built-in filters. Such a filter would involve steps like these:

通过创建一个包含多个内置过滤器的CIFilter子类,您可以在核心映像中创建一个辉光效果。这样的过滤器将包括以下步骤:

  1. Create an image to be used as the blue glow. There's probably a few decent ways to do this; one is to use CIColorMatrix to create a monochrome version of the input image.
  2. 创建一个用作蓝色辉光的图像。可能有一些不错的方法;一种是使用CIColorMatrix创建输入图像的单色版本。
  3. Scale up and blur the glow image (CIAffineTransform + CIGaussianBlur).
  4. 放大和模糊辉光图像(CIAffineTransform + CIGaussianBlur)。
  5. Composite the original input image over the glow image (CISourceOverCompositing).
  6. 在辉光图像上组合原始输入图像(CISourceOverCompositing)。

Once you have a CIFilter subclass that does all that, you can use it with a SKEffectNode to get a realtime glow around the effect node's children. Here it is running in the "Sprite Kit Game" Xcode template on an iPad 4:

一旦您有了一个CIFilter子类来完成所有这些工作,您就可以将它与一个SKEffectNode一起使用,从而在effect节点的子节点周围获得实时的辉光。它在ipad4的“Sprite Kit Game”Xcode模板中运行:

Glowing spaceship in Sprite Kit

I got this up and running in a few minutes by cribbing the custom filter class used for a similar effect in the Scene Kit presentation from WWDC 2013 -- grab it from the WWDC Sample Code package at developer.apple.com/downloads, and look for the ASCGlowFilter class. (If you want to use that code on iOS, you'll need to change the NSAffineTransform part to use CGAffineTransform instead. I also replaced the centerX and centerY properties with an inputCenter parameter of type CIVector so Sprite Kit can automatically center the effect on the sprite.)

我在WWDC 2013年的场景工具包演示中使用了定制过滤器类,并在几分钟内运行了它——从developer.apple.com/downloads的WWDC示例代码包中获取它,然后查找ASCGlowFilter类。(如果您想在iOS中使用该代码,则需要更改NSAffineTransform部分以使用CGAffineTransform。我还用CIVector类型的inputCenter参数替换了centerX和centerY属性,这样Sprite Kit就可以自动将效果居中。)

Did I say "realtime" glow? Yup! That's short for "really eats CPU time". Notice in the screenshot it's no longer pegged at 60 fps, even with only one spaceship -- and with the software OpenGL ES renderer on the iOS Simulator, it runs at slideshow speed. If you're on the Mac, you probably have silicon to spare... but if you want to do this in your game, keep some things in mind:

我说过"实时"辉光吗?是的!这是“真的吃了CPU时间”的缩写。请注意,在截图中,即使只有一艘宇宙飞船,它也不再以60帧每秒的速度被锁定——而iOS模拟器上的OpenGL ES渲染器软件,它的运行速度也是以幻灯片的速度。如果你在Mac电脑上,你可能有多余的硅……但如果你想在游戏中做到这一点,记住以下几点:

  • There are probably some ways to get better performance out of the filter itself. Play with different CI filters and you might see some improvement (there are several blur filters in Core Image, some of which will certainly be faster than Gaussian). Also note blur effects tend to be fragment-shader bound, so the smaller the image and the smaller the glow radius the better.
  • 可能有一些方法可以从过滤器本身获得更好的性能。使用不同的CI过滤器,您可能会看到一些改进(Core Image中有几个模糊过滤器,其中一些肯定比高斯的要快)。另外,注意模糊效果往往是碎片着色的边界,所以图像越小,辉光半径越小越好。
  • If you want to have multiple glows in a scene, consider making all the glowing sprites children of the same effect node -- that'll render them all into one image, then apply the filter once.
  • 如果你想在一个场景中有多个发光点,可以考虑把所有发光的精灵都放在同一个效果节点上——这样可以把它们全部渲染成一个图像,然后再应用一次滤镜。
  • If the sprites to be glowed don't change much (e.g. if our spaceship wasn't rotating), setting shouldRasterize to YES on the effect node should help a lot. (Actually, in this case, you might get some improvement by rotating the effect node instead of the sprite within it.)
  • 如果要发光的精灵变化不大(例如,如果我们的飞船没有旋转),那么在效果节点上设置shouldRasterize为YES应该会有很大的帮助(实际上,在这种情况下,您可以通过旋转效果节点而不是其中的精灵来获得一些改进)。
  • Do you really need realtime glow? As with many spiffy graphical effects in games, you'll get much better performance if you fake it. Make a blurry, bluey spaceship in your favorite graphics editor and put it in the scene as another sprite.
  • 你真的需要实时发光吗?就像游戏中许多华丽的图形效果一样,如果你假装它,你会得到更好的性能。在你最喜欢的图形编辑器中做一个模糊的,蓝色的宇宙飞船,把它作为另一个精灵。

#3


3  

You could use a SKShapeNode behind the sprite and define a glow using it's glowWidth and strokeColor properties. If you size and position it right, this should give you the appearance of a glow. This doesn't give you many options for customization, but I imagine it's much easier than using a CIFilter with an SKEffectNode which is likely the other logical option you have for this.

您可以使用精灵后面的SKShapeNode并使用它的glowWidth和strokeColor属性定义辉光。如果你的尺寸和位置正确,这应该会让你看起来容光焕发。这并没有为您提供许多定制选项,但我认为这比使用带有SKEffectNode的CIFilter要容易得多,后者很可能是您拥有的另一个逻辑选项。


推荐阅读
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 本文介绍了Python函数的定义与调用的方法,以及函数的作用,包括增强代码的可读性和重用性。文章详细解释了函数的定义与调用的语法和规则,以及函数的参数和返回值的用法。同时,还介绍了函数返回值的多种情况和多个值的返回方式。通过学习本文,读者可以更好地理解和使用Python函数,提高代码的可读性和重用性。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
author-avatar
赵娜supergirl
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有