SpriteKit:如何使用 blendMode 在图层中打孔
Posted
技术标签:
【中文标题】SpriteKit:如何使用 blendMode 在图层中打孔【英文标题】:SpriteKit: Howto make holes in layer with blendMode 【发布时间】:2016-11-20 02:02:29 【问题描述】:我有一个添加了一些元素的简单场景。
现在我想专注于一个带有蒙版的特定元素,并在与我想要关注的元素相同的位置剪切一个整体。非常类似于我们在某些游戏第一次启动时看到的一些教程。
基本上我正在添加一个带有alpha=0.7
的全屏图层(因此用户仍然可以看到所有内容),然后在特定位置添加一个圆圈作为该图层的子图层并设置blendMode=
。减去它会从这个全屏图层中“切出”一个圆圈,这样在这个圆圈内你就有一个清晰的视图。
将所有元素添加到屏幕上后,我有以下代码。
// before this code i added some basic elements like circles and backgrounds
let mask = SKSpriteNode(color: .blackColor(), size: self._screenSize)
mask.anchorPoint = CGPoint.zero
mask.position = CGPoint.zero
mask.zPosition = 100
mask.alpha = 0.7
let circle = SKShapeNode(circleOfRadius: Constants.Config.playersize*2)
circle.fillColor = .blackColor()
circle.lineWidth = 0
let circle_mask = SKSpriteNode(texture: SKView().textureFromNode(circle, crop: circle.frame))
circle_mask.blendMode = .Subtract
circle_mask.zPosition = 101
// now show the layer with alpha=0.7 and the circle mask being at the same position as my player element i want to focus on
mask.addChild(circle_mask)
circle_mask.position = player.position
self.addChild(mask)
但这只是添加了全屏图层,没有圆孔。看起来它忽略了 circle_mask 节点。我做错了什么?
我的计划也是继续移动圆形蒙版以专注于该场景中的其他元素。我认为。减去它应该只从它的父节点中减去,也就是带有alpa=0.7
的全屏层,对吧?
我刚刚尝试使用 SKCropNode。将全屏图层作为子图层添加到裁剪节点中,然后将圆圈指定为蒙版。但是现在它几乎把所有东西都剪掉了,只显示了我的全屏图层的一个圆圈,我实际上需要这个裁剪节点的反转结果。
blendMode 的问题在于它在最终帧缓冲区上运行,但我需要的是仅在父节点上运行它,因此在使用 .Subtract 时它不会剪切节点后面的所有内容
【问题讨论】:
您永远不会在圆形蒙版中添加圆形,您只是将其制作为纹理,它不会与任何东西混合。使圆形蒙版成为整个黑框。并添加圆圈作为一个孩子。 Alpha 混合将启动并创建孔。蒙版在 alpha 级别也不起作用,它只是打开和关闭,所以你需要添加一个透明纹理作为你的正常纹理,然后你有你的圆形蒙版来打孔 @Knight0fDragon:我不明白。我的代码不是完全按照你的描述做的吗?我的全屏图层已经有 alpha=0.7。现在我将圆形精灵添加为孩子。但是我如何制作你正在写的“阿尔法混合”。显然 blendMode=.Subtract 是错误的。最后,我将我的面具和圆圈孩子添加到场景中。你能提供一些更正的代码吗? 不,不是,现在我在电脑上,我会尝试为你写一个答案 【参考方案1】:下面是一个示例,说明如何创建一个半透明层,并在其中打一个孔:
-(注意:.subtract 混合模式不考虑精灵的 alpha,因此您需要使用裁剪节点)
self.backgroundColor = .red
//Our transparent overlay
let fullScreen = SKSpriteNode(color: .black, size: self.size)
fullScreen.position = CGPoint.zero
fullScreen.zPosition = 100
fullScreen.alpha = 0.7
//let's make a mask to punch circles in our shape
let mask = SKSpriteNode(color: .white, size: self.size)
mask.position = CGPoint.zero
mask.zPosition = 100
mask.alpha = 1
let circle = SKShapeNode(circleOfRadius: 20*2)
circle.fillColor = .white
circle.lineWidth = 0
circle.alpha = 1
//let circle_mask = SKSpriteNode()
circle.blendMode = .subtract
mask.addChild(circle)
//let's create the node to place on screen
let crop = SKCropNode()
crop.maskNode = mask
crop.addChild(fullScreen)
self.addChild(crop)
【讨论】:
非常感谢。效果很好。但是你能解释一下为什么圆必须是 SKShapeNode 吗?我使用 SKSpriteNode 将其转换为带有 textureFromNode 的 SKTexture,使其停止工作。 你没有正确混合,你只能在节点上混合节点 基本上黑色区域的 alpha 不是 0,而是 1。如果你用 alpha 0 伪装纹理,它应该可以工作 @Knight0fDragon:知道cropNode 在ios 10 上是如何工作的吗?尝试使用 blendMode 和遮罩,但仍然无法在 10.x ios 上运行 将洞的 alpha 设置为 0.001,将混合模式设置为 .replace。以上是关于SpriteKit:如何使用 blendMode 在图层中打孔的主要内容,如果未能解决你的问题,请参考以下文章
Jetpack Compose - Canvas之BlendMode
Android UIPaint ComposeShader 组合渲染 ( Shader 叠加模式 | Xfermode | PorterDuff.Mode | BlendMode )