SKEffectNode для SKTexture?
SKEffectionNodes
иметь переключатель switchRasterise, который запекает их в растровое изображение и не обновляет их до тех пор, пока не будут изменены базовые узлы, на которые воздействует эффект.
Однако я не могу найти способ создать SKTexture
из этого растеризованного "изображения".
Можно ли получить SKTexture
из SKEffectNode
?
2 ответа
Я понял это таким образом, чтобы решить мои проблемы, используя Фабрику.
Узнайте больше о том, как сделать фабрику, от терпеливой и ясной артикуляции Mobile Ben, здесь: Создание фабрики и использование для создания спрайтов и фигур
Существует проблема с размытием SKTexture
или же SKSpriteNode
в этом он будет исчерпывать пространство. Размытие / свечение выходит за рамки спрайта. Чтобы решить эту проблему, ниже вы увидите, что я создал "создатель" объекта. Это просто пустой SKSpriteNode
это вдвое больше, чем размер размытой текстуры. Текстура, которая должна быть размыта, добавляется в качестве дочернего объекта к этому "создателю" объекта.
Это работает, независимо от того, насколько хакерской это;)
Внутри статического файла фабричного класса:
import SpriteKit
class Factory {
private static let view:SKView = SKView() // the magic. This is the rendering space
static func makeShadow(from source: SKTexture, rgb: SKColor, a: CGFloat) -> SKSpriteNode {
let shadowNode = SKSpriteNode(texture: source)
shadowNode.colorBlendFactor = 0.5 // near 1 makes following line more effective
shadowNode.color = SKColor.gray // makes for a darker shadow. White for "glow" shadow
let textureSize = source.size()
let doubleTextureSize = CGSize(width: textureSize.width * 2, height: textureSize.height * 2)
let framer = SKSpriteNode(color: UIColor.clear, size: doubleTextureSize)
framer.addChild(shadowNode)
let blurAmount = 10
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(blurAmount, forKey: kCIInputRadiusKey)
let fxNode = SKEffectNode()
fxNode.filter = filter
fxNode.blendMode = .alpha
fxNode.addChild(framer)
fxNode.shouldRasterize = true
let tex = view.texture(from: fxNode) // ‘view’ refers to the magic first line
let shadow = SKSpriteNode(texture: tex) //WHOOPEE!!! TEXTURE!!!
shadow.colorBlendFactor = 0.5
shadow.color = rgb
shadow.alpha = a
shadow.zPosition = -1
return shadow
}
}
В любом месте вы можете получить доступ к Sprite, для которого хотите создать текстуру тени или свечения:
shadowSprite = Factory.makeShadow(from: button, rgb: myColor, a: 0.33)
shadowSprite.position = CGPoint(x: self.frame.midX, y: self.frame.midY - 5)
addChild(shadowSprite)
-button
текстура кнопки для тени. a:
является альфа-настройкой (фактически уровень прозрачности от 0,0 до 1,0, где 1,0 полностью непрозрачен), чем ниже, тем светлее будет тень.
Позиционирование служит для того, чтобы тень немного опускалась ниже кнопки, поэтому кажется, что свет идет сверху, отбрасывая тени вниз и на фон.
Я думаю, что вы могли бы попробовать такой код (это просто пример):
if let effect = SKEffectNode.init(fileNamed: "myeffect") {
effect.shouldRasterize = true
self.addChild(effect)
...
let texture = SKView().texture(from: self)
}
Обновление:
После того, как вы ответите, надеюсь, я лучше понял, чего вы хотите достичь.
Это моя точка зрения: если вы хотите создать тень от текстуры, вы можете просто создать SKSpriteNode
с этой текстурой:
let shadow = SKSpriteNode.init(texture: <yourTexture>)
shadow.blendMode = SKBlendMode.alpha
shadow.colorBlendFactor = 1
shadow.color = SKColor.black
shadow.alpha = 0.25
То, что я хочу сказать, это то, что вы могли бы действовать шаг за шагом:
- получить вашу текстуру
- проработайте свою текстуру (добавьте фильтры, создайте какой-то другой эффект)
- получить тень
Этот способ работы создает ряд полезных методов, которые вы можете использовать в своем проекте для создания элементов другого типа. Может быть, разделив задачи, вам не нужно использовать texture(from:)