SKMutableTexture 中的透明像素
Transparent pixel in SKMutableTexture
我正在使用 SKMutableTexture 在游戏中渲染可破坏的地面。出于所有意图和目的,这很好用,除非我想将透明像素渲染到 MutableTexture 中已经存在非透明像素的位置。
我已经为 RGBAColor 创建了一个结构,如下所示:
struct RGBAColor {
var r: UInt8
var g: UInt8
var b: UInt8
var a: UInt8
static var clear = RGBAColor(r: 0, g: 0, b: 0, a: 0)
}
然后我像这样修改 SKMutableTexture:
self.texture.modifyPixelData({ (voidptr, len) in
let bytes = voidptr!.assumingMemoryBound(to: RGBAColor.self)
for (index, color) in self.modifiedPixels {
bytes[index] = color
self.pixels[index] = color
}
})
.. 其中 "modifiedPixels" 是像 [Int : RGBAColor] 这样的字典(为了不更新纹理中的所有像素 - 仅更新修改后的像素。
当颜色的 alpha (a) > 0 时它会按我的预期工作..但当它为 0 时则不会(这就像像素是在现有纹理的顶部渲染的..而不是像你那样修改实际像素数据)。
我是不是做错了什么?或者这是预期的行为?
来自 SKMutableTexture
文档,
The color components you provide should have already been multiplied
by the alpha value.
通常,如果您想要 alpha 为 0.5 的红色,您会使用 RGBA 组件
(red:1.0, green:0.0, blue:0.0, alpha:0.5)
预乘 alpha 颜色的等价物是
(red:0.5, green:0.0, blue:0.0, alpha:0.5)
其中 RGB 分量已乘以 alpha 值。
对于您的特定情况,您可以向 Color
结构添加一个初始化程序来执行乘法。这是一种实现方式...
首先,定义一个扩展,将 UInt8
缩放 Float
值
extension UInt8 {
func scaled(by value:Float) -> UInt8 {
var scale = UInt(round(Float(self) * value))
scale = Swift.min(scale, UInt(UInt8.max))
return UInt8(scale)
}
}
然后添加一个自动将组件乘以 alpha 值的初始化程序
struct Color {
var red:UInt8
var green:UInt8
var blue:UInt8
var alpha:UInt8
init(red:UInt8,green:UInt8,blue:UInt8,alpha:UInt8) {
let alphaScale = Float(alpha) / Float(UInt8.max)
self.red = red.scaled(by: alphaScale)
self.blue = blue.scaled(by: alphaScale)
self.green = green.scaled(by: alphaScale)
self.alpha = alpha
}
}
然后您可以通过
创建 alpha = 0.5 的红色颜色
let color = Color(red:255, green:0, blue:0, alpha:127)
和完全透明的颜色
let color = Color(red:255, green:0, blue:0, alpha:0)
我正在使用 SKMutableTexture 在游戏中渲染可破坏的地面。出于所有意图和目的,这很好用,除非我想将透明像素渲染到 MutableTexture 中已经存在非透明像素的位置。
我已经为 RGBAColor 创建了一个结构,如下所示:
struct RGBAColor {
var r: UInt8
var g: UInt8
var b: UInt8
var a: UInt8
static var clear = RGBAColor(r: 0, g: 0, b: 0, a: 0)
}
然后我像这样修改 SKMutableTexture:
self.texture.modifyPixelData({ (voidptr, len) in
let bytes = voidptr!.assumingMemoryBound(to: RGBAColor.self)
for (index, color) in self.modifiedPixels {
bytes[index] = color
self.pixels[index] = color
}
})
.. 其中 "modifiedPixels" 是像 [Int : RGBAColor] 这样的字典(为了不更新纹理中的所有像素 - 仅更新修改后的像素。
当颜色的 alpha (a) > 0 时它会按我的预期工作..但当它为 0 时则不会(这就像像素是在现有纹理的顶部渲染的..而不是像你那样修改实际像素数据)。
我是不是做错了什么?或者这是预期的行为?
来自 SKMutableTexture
文档,
The color components you provide should have already been multiplied by the alpha value.
通常,如果您想要 alpha 为 0.5 的红色,您会使用 RGBA 组件
(red:1.0, green:0.0, blue:0.0, alpha:0.5)
预乘 alpha 颜色的等价物是
(red:0.5, green:0.0, blue:0.0, alpha:0.5)
其中 RGB 分量已乘以 alpha 值。
对于您的特定情况,您可以向 Color
结构添加一个初始化程序来执行乘法。这是一种实现方式...
首先,定义一个扩展,将 UInt8
缩放 Float
值
extension UInt8 {
func scaled(by value:Float) -> UInt8 {
var scale = UInt(round(Float(self) * value))
scale = Swift.min(scale, UInt(UInt8.max))
return UInt8(scale)
}
}
然后添加一个自动将组件乘以 alpha 值的初始化程序
struct Color {
var red:UInt8
var green:UInt8
var blue:UInt8
var alpha:UInt8
init(red:UInt8,green:UInt8,blue:UInt8,alpha:UInt8) {
let alphaScale = Float(alpha) / Float(UInt8.max)
self.red = red.scaled(by: alphaScale)
self.blue = blue.scaled(by: alphaScale)
self.green = green.scaled(by: alphaScale)
self.alpha = alpha
}
}
然后您可以通过
创建 alpha = 0.5 的红色颜色let color = Color(red:255, green:0, blue:0, alpha:127)
和完全透明的颜色
let color = Color(red:255, green:0, blue:0, alpha:0)