金属似乎将 bgra8Unorm 解释为 rgba 颜色
Metal seems to interpret bgra8Unorm as an rgba color
在 Apple Metal 应用程序中,我正在尝试编辑纹理内容。纹理使用 bgra8Unorm 像素格式,创建方式如下:
fileprivate var texture: MTLTexture!
private var buffer: MTLBuffer!
private var width: Int!
private var height: Int!
...
buffer = device.makeBuffer(length: width * height * 4, options: .storageModeManaged)
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .bgra8Unorm, width: width, height: height, mipmapped: false)
texture = buffer.makeTexture(descriptor: textureDescriptor, offset: 0, bytesPerRow: width * 4)
我将像素颜色设置如下:
func setPixel(x: Int, y: Int, color: NSColor) {
let ptr = buffer.contents().bindMemory(to: UInt32.self, capacity: buffer.length / 4)
var b: CGFloat = 0
var g: CGFloat = 0
var r: CGFloat = 0
var a: CGFloat = 0
color.getRed(&r, green: &g, blue: &b, alpha: &a)
let index = y * width + x
ptr[index] = (UInt32(b * 255) << 24) | (UInt32(g * 255) << 16) | (UInt32(r * 255) << 8) | UInt32(a * 255)
buffer.didModifyRange(index..<(index + 1))
}
主像素格式也设置为bgra8Unorm
继承MTKView
:
init() {
super.init(frame: .zero, device: MTLCreateSystemDefaultDevice())
colorPixelFormat = .bgra8Unorm
clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}
片段着色器根本没有做任何有趣的事情:
fragment float4 basic_fragment(
VertexOut inVert [[ stage_in ]],
texture2d<float> tex2D [[ texture(0) ]],
sampler sampler2D [[ sampler(0) ]]
) {
return tex2D.sample(sampler2D, inVert.tex);
}
然而,当我调用所有这些来将像素的颜色设置为 NSColor.orange
时,它似乎是蓝色的。
运行 调试器并捕获 GPU 帧,我可以看到缓冲区中的值为 8388607
,看起来像最大值 Alpha
、Red
和几乎达到最大值 Green
。但不知何故,金属似乎将这种颜色解释为 rgba
格式,尽管我将所有内容都设置为 bgra
我是不是做错了什么?
Am I doing something wrong?
bgra
表示内存中依次出现b
、g
、r
、a
4个分量。
所以,在小端 UInt32
中,b
应该是 LS 字节,a
应该是 MS 字节。
请试试这个:
ptr[index] = (UInt32(a * 255) << 24) | (UInt32(r * 255) << 16) | (UInt32(g * 255) << 8) | UInt32(b * 255)
在 Apple Metal 应用程序中,我正在尝试编辑纹理内容。纹理使用 bgra8Unorm 像素格式,创建方式如下:
fileprivate var texture: MTLTexture!
private var buffer: MTLBuffer!
private var width: Int!
private var height: Int!
...
buffer = device.makeBuffer(length: width * height * 4, options: .storageModeManaged)
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .bgra8Unorm, width: width, height: height, mipmapped: false)
texture = buffer.makeTexture(descriptor: textureDescriptor, offset: 0, bytesPerRow: width * 4)
我将像素颜色设置如下:
func setPixel(x: Int, y: Int, color: NSColor) {
let ptr = buffer.contents().bindMemory(to: UInt32.self, capacity: buffer.length / 4)
var b: CGFloat = 0
var g: CGFloat = 0
var r: CGFloat = 0
var a: CGFloat = 0
color.getRed(&r, green: &g, blue: &b, alpha: &a)
let index = y * width + x
ptr[index] = (UInt32(b * 255) << 24) | (UInt32(g * 255) << 16) | (UInt32(r * 255) << 8) | UInt32(a * 255)
buffer.didModifyRange(index..<(index + 1))
}
主像素格式也设置为bgra8Unorm
继承MTKView
:
init() {
super.init(frame: .zero, device: MTLCreateSystemDefaultDevice())
colorPixelFormat = .bgra8Unorm
clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}
片段着色器根本没有做任何有趣的事情:
fragment float4 basic_fragment(
VertexOut inVert [[ stage_in ]],
texture2d<float> tex2D [[ texture(0) ]],
sampler sampler2D [[ sampler(0) ]]
) {
return tex2D.sample(sampler2D, inVert.tex);
}
然而,当我调用所有这些来将像素的颜色设置为 NSColor.orange
时,它似乎是蓝色的。
运行 调试器并捕获 GPU 帧,我可以看到缓冲区中的值为 8388607
,看起来像最大值 Alpha
、Red
和几乎达到最大值 Green
。但不知何故,金属似乎将这种颜色解释为 rgba
格式,尽管我将所有内容都设置为 bgra
我是不是做错了什么?
Am I doing something wrong?
bgra
表示内存中依次出现b
、g
、r
、a
4个分量。
所以,在小端 UInt32
中,b
应该是 LS 字节,a
应该是 MS 字节。
请试试这个:
ptr[index] = (UInt32(a * 255) << 24) | (UInt32(r * 255) << 16) | (UInt32(g * 255) << 8) | UInt32(b * 255)