首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将自定义SKShader应用于SKScene,用Swift对iOS 8 SpriteKit中的整个渲染场景进行像素化

将自定义SKShader应用于SKScene,用Swift对iOS 8 SpriteKit中的整个渲染场景进行像素化
EN

Stack Overflow用户
提问于 2014-09-27 07:07:03
回答 3查看 3.3K关注 0票数 3

我试图在SKScene上创建一个全屏像素效果。我了解到应该有两种选择来做到这一点:

  • 使用GLES 2.0使用自定义SKShader
  • 使用核心图像过滤器。

我尝试添加一个自定义SKShader,它应该通过像素化来修改整个屏幕。我不确定这是否可能,但是来自SKScene的文档(它是SKEffectNode的子类)表明了这一点:

SKEffectNode对象将其子对象呈现到缓冲区中,并可对此呈现的输出应用核心图像筛选器。

可以将SKShader分配给SKScene,就像在GameScene : SKScene中一样

代码语言:javascript
复制
override func didMoveToView(view: SKView) {
    let shader = SKShader(fileNamed: "pixelation.fsh")
    self.shader = shader
    self.shouldEnableEffects = true
}

..。但是,呈现的缓冲区似乎没有作为u_texture传递给GLES:

代码语言:javascript
复制
void main()
{
    vec2 coord = v_tex_coord;
    coord.x = floor(coord.x * 10.0) / 10.0;
    coord.y = floor(coord.y * 10.0) / 10.0;
    vec4 texture = texture2D(u_texture, coord);
    gl_FragColor = texture;
}

..。所以以前的着色器不工作了。

如果我将该着色器分配给基于纹理的SKSpriteNode,它就能工作。

那么,在所有节点被呈现之后,是否可以修改整个帧缓冲区(例如,像素化它)作为后处理措施?

编辑:我找到了一种在OS (如何将CIPixellate核心图像过滤器添加到雪碧套件场景中?)中使用copying进行像素化的方法,但是复制该实现不会在iOS上产生任何结果。根据文档CIPixellate应该是Available in OS X v10.4 and later and in iOS 6.0 and later.

EN

回答 3

Stack Overflow用户

发布于 2014-10-02 16:19:22

为了让.shaderSKScene上运行,需要在场景中将shouldEnableEffects设置为true (SKEffectNode也是如此)。

虽然从技术上讲,这“工作”(着色器是应用),有一个缺陷,在渲染后的场景,得到轻微调整。

因此,到目前为止,使用CoreImage过滤器是最好的方法。

票数 3
EN

Stack Overflow用户

发布于 2014-09-27 15:06:54

我设法使它工作使用核心图像过滤器CIPixellate。我使用is作为SKEffectNode的过滤器来产生像素化效果。有几件事要注意:

  • SKSceneSKEffectNode的一个子类,但是将过滤器应用于SKScene并不有效。它会弄乱背景,不做任何像素。
  • 您需要创建一个SKEffectNode并添加要在其下像素化的节点。

下面是基于选择Game类型项目和Swift时生成的代码的解决方案

代码语言:javascript
复制
import SpriteKit

class GameScene: SKScene {
    var effectNode : SKEffectNode = SKEffectNode.node()

    override func didMoveToView(view: SKView) {
        let filter = CIFilter(name: "CIPixellate")
        filter.setDefaults()
        filter.setValue(5.0, forKey: "inputScale")

        self.effectNode.filter = filter
        self.effectNode.shouldEnableEffects = true
        self.addChild(effectNode)
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            let sprite = SKSpriteNode(imageNamed:"Spaceship")

            sprite.xScale = 0.5
            sprite.yScale = 0.5
            sprite.position = location

            let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)

            sprite.runAction(SKAction.repeatActionForever(action))

            self.effectNode.addChild(sprite)
        }
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}
票数 2
EN

Stack Overflow用户

发布于 2016-04-01 03:31:05

实际上,对于最近的一个项目,我不得不做同样的事情,作为一种在级别之间进行转换的方法,并最终为它做了一项工作。基本上,我在代码中获取了屏幕的屏幕截图,然后在加载下一个级别时,我调用了以前保存的屏幕截图,说明加载时该级别的外观。我添加了以前的水平屏幕截图作为一个SKSpriteNode,然后运行了许多次的着色器,直到它是难以置信的像素。然后,我对那个级别的截图做了同样的处理,并替换了两个,然后我对第二个屏幕截图进行了像素化,所以它看起来就像当这个级别被击败时,所有东西都被像素化了,然后非像素化了自己,从而揭示了一个新的层次。

代码语言:javascript
复制
          UIGraphicsBeginImageContextWithOptions(UIScreen.mainScreen().bounds.size, false, 0);
            self.view!.drawViewHierarchyInRect(view!.bounds, afterScreenUpdates: true)
            let image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            //UIGraphicsEndImageContext()

            protoImage = SKSpriteNode(texture: SKTexture(CGImage: image.CGImage!))
            protoImage.size = CGSizeMake(self.frame.size.width, self.frame.size.height)
            node.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2)
            protoImage.zPosition = 9000

第二场景

代码语言:javascript
复制
           let shader: SKShader = SKShader(fileNamed: "RWTGradient2.fsh")
           let ratioX: Float = divisor/Float(protoImage.frame.size.width)
           let ratioY: Float = divisor/Float(protoImage.frame.size.height)
           shader.uniforms = [

                SKUniform(name: "ratioX", float: ratioX),
                SKUniform(name: "ratioY", float: ratioY),

           ]
           protoImage.shader = shader;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26072230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档