这是一个使用着色器为您生成 maskNode 的方法:
func generateMaskNode(from mask:SKNode) -> SKNode
{
var returningNode : SKNode!
autoreleasepool
{
let view = SKView()
//First let's flatten the node
let texture = view.texture(from: mask)
let node = SKSpriteNode(texture:texture)
//Next apply the shader to the flattened node to allow for color swapping
node.shader = SKShader(fileNamed: "shader.fsh")
let texture2 = view.texture(from: node)
returningNode = SKSpriteNode(texture:texture2)
}
return returningNode
}
它需要您创建一个名为 shader.fsh 的文件,里面的代码如下所示:
void main() {
// Find the pixel at the coordinate of the actual texture
vec4 val = texture2D(u_texture, v_tex_coord);
// If the color value of that pixel is 0,0,0
if (val.r == 0.0 && val.g == 0.0 && val.b == 0.0) {
// Turn the pixel off
gl_FragColor = vec4(0.0,0.0,0.0,0.0);
}
else {
// Otherwise, keep the original color
gl_FragColor = val;
}
}
要使用它,它要求您使用黑色像素而不是 alpha 作为确定裁剪内容的方法,因此您的代码现在应该如下所示:
var cropNode = SKCropNode()
var shape = SKShapeNode(rectOf: CGSize(width:100,height:100))
shape.fillColor = SKColor.orange
var shape2 = SKShapeNode(rectOf: CGSize(width:25,height:25))
shape2.fillColor = SKColor.orange
shape2.blendMode = .subtract
shape.addChild(shape2)
let mask = generateMaskNode(from:shape)
cropNode.addChild(shape)
cropNode.position = CGPoint(x:150,y:170)
cropNode.maskNode=mask
container.addChild(cropNode)
减法在模拟器而不是设备上起作用的原因是因为模拟器减去了 alpha 通道,而设备却没有。该设备实际上表现正确,因为不假设要减去 alpha,所以应该忽略它。
请注意,您不必选择黑色作为裁剪颜色,您可以更改着色器以允许您选择任何颜色,只需更改行:
if (val.r == 0.0 && val.g == 0.0 && val.b == 0.0)
到你想要的颜色。(就像你的情况一样。你可以说 r = 0 g = 1 b = 0 只在绿色上裁剪)
以上代码在设备上的结果
编辑:我想指出减去混合不是必需的,这也可以:
var cropNode = SKCropNode()
var shape = SKShapeNode(rectOf: CGSize(width:100,height:100))
shape.fillColor = SKColor.orange
var shape2 = SKShapeNode(rectOf: CGSize(width:25,height:25))
shape2.fillColor = SKColor.black
shape2.blendMode = .replace
shape.addChild(shape2)
let mask = generateMaskNode(from:shape)
cropNode.addChild(shape)
cropNode.position = CGPoint(x:150,y:170)
cropNode.maskNode=mask
container.addChild(cropNode)
现在我无法测试,这引出了一个问题,甚至需要我的功能。下面的代码理论上应该可以工作,因为它正在用上面的像素替换底层像素,所以理论上 alpha 应该转移过来。如果有人可以对此进行测试,请告诉我它是否有效。
var cropNode = SKCropNode()
var shape = SKShapeNode(rectOf: CGSize(width:100,height:100))
shape.fillColor = SKColor.orange
var shape2 = SKShapeNode(rectOf: CGSize(width:25,height:25))
shape2.fillColor = SKColor(red:0,green:0,blue:0,alpha:0)
shape2.blendMode = .replace
shape.addChild(shape2)
cropNode.addChild(shape)
cropNode.position = CGPoint(x:150,y:170)
cropNode.maskNode= shape.copy() as! SKNode
container.addChild(cropNode)
替换只替换颜色而不是 alpha