我试图在SKScene上创建一个全屏像素效果。我了解到应该有两种选择来做到这一点:
SKShader。我尝试添加一个自定义SKShader,它应该通过像素化来修改整个屏幕。我不确定这是否可能,但是来自SKScene的文档(它是SKEffectNode的子类)表明了这一点:
SKEffectNode对象将其子对象呈现到缓冲区中,并可对此呈现的输出应用核心图像筛选器。
可以将SKShader分配给SKScene,就像在GameScene : SKScene中一样
override func didMoveToView(view: SKView) {
let shader = SKShader(fileNamed: "pixelation.fsh")
self.shader = shader
self.shouldEnableEffects = true
}..。但是,呈现的缓冲区似乎没有作为u_texture传递给GLES:
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.。
发布于 2014-10-02 16:19:22
为了让.shader在SKScene上运行,需要在场景中将shouldEnableEffects设置为true (SKEffectNode也是如此)。
虽然从技术上讲,这“工作”(着色器是应用),有一个缺陷,在渲染后的场景,得到轻微调整。
因此,到目前为止,使用CoreImage过滤器是最好的方法。
发布于 2014-09-27 15:06:54
我设法使它工作使用核心图像过滤器CIPixellate。我使用is作为SKEffectNode的过滤器来产生像素化效果。有几件事要注意:
SKScene是SKEffectNode的一个子类,但是将过滤器应用于SKScene并不有效。它会弄乱背景,不做任何像素。SKEffectNode并添加要在其下像素化的节点。下面是基于选择Game类型项目和Swift时生成的代码的解决方案
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 */
}
}发布于 2016-04-01 03:31:05
实际上,对于最近的一个项目,我不得不做同样的事情,作为一种在级别之间进行转换的方法,并最终为它做了一项工作。基本上,我在代码中获取了屏幕的屏幕截图,然后在加载下一个级别时,我调用了以前保存的屏幕截图,说明加载时该级别的外观。我添加了以前的水平屏幕截图作为一个SKSpriteNode,然后运行了许多次的着色器,直到它是难以置信的像素。然后,我对那个级别的截图做了同样的处理,并替换了两个,然后我对第二个屏幕截图进行了像素化,所以它看起来就像当这个级别被击败时,所有东西都被像素化了,然后非像素化了自己,从而揭示了一个新的层次。
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第二场景
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;https://stackoverflow.com/questions/26072230
复制相似问题