热门标签 | 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要容易得多,后者很可能是您拥有的另一个逻辑选项。


推荐阅读
  • 我在一个UIImageView上附加了一个UILongPressGestureRecognizer,但无论如何配置,它都无法检测到长按手势。然而,当我将其替换为UITapGestureRecognizer时,后者却能正常工作。这究竟是怎么回事? ... [详细]
  • iOS snow animation
    CTSnowAnimationView.hCTMyCtripCreatedbyalexon1614.Copyright©2016年ctrip.Allrightsreserved.# ... [详细]
  • 本文整理了一份基础的嵌入式Linux工程师笔试题,涵盖填空题、编程题和简答题,旨在帮助考生更好地准备考试。 ... [详细]
  • iOS 不定参数 详解 ... [详细]
  • 目录预备知识导包构建数据集神经网络结构训练测试精度可视化计算模型精度损失可视化输出网络结构信息训练神经网络定义参数载入数据载入神经网络结构、损失及优化训练及测试损失、精度可视化qu ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • java解析json转Map前段时间在做json报文处理的时候,写了一个针对不同格式json转map的处理工具方法,总结记录如下:1、单节点单层级、单节点多层级json转mapim ... [详细]
  • vue引入echarts地图的四种方式
    一、vue中引入echart1、安装echarts:npminstallecharts--save2、在main.js文件中引入echarts实例:  Vue.prototype.$echartsecharts3、在需要用到echart图形的vue文件中引入:   importechartsfrom"echarts";4、如果用到map(地图),还 ... [详细]
  • Java 中的等时日期(int,int)方法,示例 ... [详细]
  • 本文介绍了Go语言中正则表达式的基本使用方法,并提供了一些实用的示例代码。 ... [详细]
  • 自然语言处理(NLP)——LDA模型:对电商购物评论进行情感分析
    目录一、2020数学建模美赛C题简介需求评价内容提供数据二、解题思路三、LDA简介四、代码实现1.数据预处理1.1剔除无用信息1.1.1剔除掉不需要的列1.1.2找出无效评论并剔除 ... [详细]
  • Leetcode学习成长记:天池leetcode基础训练营Task01数组
    前言这是本人第一次参加由Datawhale举办的组队学习活动,这个活动每月一次,之前也一直关注,但未亲身参与过,这次看到活动 ... [详细]
  • 本文将深入探讨 iOS 中的 Grand Central Dispatch (GCD),并介绍如何利用 GCD 进行高效多线程编程。如果你对线程的基本概念还不熟悉,建议先阅读相关基础资料。 ... [详细]
  • python模块之正则
    re模块可以读懂你写的正则表达式根据你写的表达式去执行任务用re去操作正则正则表达式使用一些规则来检测一些字符串是否符合个人要求,从一段字符串中找到符合要求的内容。在 ... [详细]
  • 本文介绍了如何使用 Google Colab 的免费 GPU 资源进行深度学习应用开发。Google Colab 是一个无需配置即可使用的云端 Jupyter 笔记本环境,支持多种深度学习框架,并且提供免费的 GPU 计算资源。 ... [详细]
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社区 版权所有