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:)

Другие вопросы по тегам