SKSpriteNode, созданный из SKTexture(данные: размер:), проблемы с альфа (непрозрачность)

У меня возникла проблема при создании SKSpriteNode из pixelData.

Ниже мой код.

var pixelData: [UInt32] = [UInt32](count: 256, repeatedValue: 0xff0000ff)
pixelData.appendContentsOf([UInt32](count: 256, repeatedValue: 0xff00ff00))
pixelData.appendContentsOf([UInt32](count: 256, repeatedValue: 0xffff0000))
pixelData.appendContentsOf([UInt32](count: 256, repeatedValue: 0x000000ff))

let data = NSData(bytes: pixelData, length: pixelData.count * sizeof(UInt32))

let texture = SKTexture(data: data, size: CGSize(width: 32, height: 32))

let node = SKSpriteNode(texture: texture, size: CGSize(width: 32, height: 32))
node.position.x = self.frame.midX
node.position.y = self.frame.midY

self.addChild(node)

Это пошло так, как я хочу для трех нижних строк (это первые 3 части в массиве pixelData, 0xff0000ff, 0xff00ff00, 0xffff0000: Красный, зеленый и синий).

Однако я ожидал, что верхняя строка будет полностью прозрачной: 0x000000ff, что должно означать rgba(1, 0, 0, 0). Но это выглядело так:

Я не знаю, почему это произошло. Мое понимание pixelData неверно? Или это ошибка или что-то в SpriteKit?

Большое спасибо за Вашу помощь!

1 ответ

Решение

Из документации для удобства метод для преобразования данных пикселей в SKTexture,

Компоненты цвета уже должны быть умножены на альфа-значение.

Следовательно, значение 0x000000ff не определено, так как красный компонент не может быть 0xff если значение альфа равно 0. Кроме того, несколько не интуитивно понятно представлять цвет пикселя шестнадцатеричным значением, особенно когда компоненты расположены в обратном порядке.

Кроме того, вы можете определить структуру данных для представления цвета, а затем предварительно умножить каждый компонент цвета на альфа-значение во время инициализации:

struct Color {
    var red:UInt8
    var green:UInt8
    var blue:UInt8
    var alpha:UInt8

    // You can omit the parameters that have default values.
    init(red:UInt8=0, green:UInt8=0, blue:UInt8=0, alpha:UInt8=UInt8.max) {
        let alphaValue:Float = Float(alpha) / 255
        self.red = UInt8(round(Float(red) * alphaValue))
        self.green = UInt8(round(Float(blue) * alphaValue))
        self.blue = UInt8(round(Float(green) * alphaValue))
        self.alpha = alpha
    }
}

Затем вы можете определить и инициализировать pixelData массив с теми же значениями, что и ваш код

    var pixelData:[Color] = [Color](count: 256, repeatedValue: Color(red: UInt8.max))
    pixelData += [Color](count:256, repeatedValue: Color(green: UInt8.max))
    pixelData += [Color](count:256, repeatedValue: Color(blue: UInt8.max))
    pixelData += [Color](count:256, repeatedValue: Color(red: UInt8.max, alpha: 0))

и создать NSData объект с

    let data = NSData(bytes: pixelData, length: pixelData.count * sizeof(Color))
Другие вопросы по тегам