Создать прозрачную текстуру в Swift
Мне просто нужно создать прозрачную текстуру.(Пикселей с альфа 0).
func layerTexture()-> MTLTexture {
let width = Int(self.drawableSize.width )
let height = Int(self.drawableSize.height )
let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .bgra8Unorm, width: width , height: height, mipmapped: false)
let temparyTexture = self.device?.makeTexture(descriptor: texDescriptor)
return temparyTexture!
}
когда я открываю temparyTexture с помощью предварительного просмотра, он кажется черным. Что здесь не хватает?
ОБНОВИТЬ
Я просто попытался создать текстуру, используя прозрачное изображение. код.
func layerTexture(imageData:Data)-> MTLTexture {
let width = Int(self.drawableSize.width )
let height = Int(self.drawableSize.height )
let bytesPerRow = width * 4
let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm, width: width , height: height, mipmapped: false)
let temparyTexture = self.device?.makeTexture(descriptor: texDescriptor)
let region = MTLRegionMake2D(0, 0, width, height)
imageData.withUnsafeBytes { (u8Ptr: UnsafePointer<UInt8>) in
let rawPtr = UnsafeRawPointer(u8Ptr)
temparyTexture?.replace(region: region, mipmapLevel: 0, withBytes: rawPtr, bytesPerRow: bytesPerRow)
}
return temparyTexture!
}
метод вызывается следующим образом
let image = UIImage(named: "layer1.png")!
let imageData = UIImagePNGRepresentation(image)
self.layerTexture(imageData: imageData!)
где layer1.png - прозрачный png. Но даже при сбое с сообщением "Поток 1: EXC_BAD_ACCESS (code=1, address=0x107e8c000) " в момент, когда я пытаюсь заменить текстуру. Я считаю, что это потому, что данные изображений сжаты, а rawpointer должен указывать на несжатые данные. Как я могу решить это?
Я на правильном пути или совершенно не в том направлении? Есть ли другие альтернативы. Мне просто нужно создать прозрачную текстуру.
1 ответ
Предварительное редактирование: когда вы быстро просматриваете прозрачную текстуру, она выглядит черной. Я просто дважды проверил код, который у меня стабильно работает, - это ожидаемый результат.
Постредактирование: Вы правы, вы не должны копировать данные PNG или JPEG непосредственно в содержимое MTLTexture. Я бы порекомендовал сделать что-то вроде этого:
var pixelBuffer: CVPixelBuffer?
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue]
var status = CVPixelBufferCreate(nil, Int(image.size.width), Int(image.size.width),
kCVPixelFormatType_32BGRA, attrs as CFDictionary,
&pixelBuffer)
assert(status == noErr)
let coreImage = CIImage(image: image)!
let context = CIContext(mtlDevice: MTLCreateSystemDefaultDevice()!)
context.render(coreImage, to: pixelBuffer!)
var textureWrapper: CVMetalTexture?
status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
GPUManager.shared.textureCache, pixelBuffer!, nil, .bgra8Unorm,
CVPixelBufferGetWidth(pixelBuffer!), CVPixelBufferGetHeight(pixelBuffer!), 0, &textureWrapper)
let texture = CVMetalTextureGetTexture(textureWrapper!)!
// use texture now for your Metal texture. the texture is now map-bound to the CVPixelBuffer's underlying memory.
Проблема, с которой вы сталкиваетесь, заключается в том, что на самом деле довольно сложно полностью понять, как работают растровые изображения и как их можно по-разному выложить. Графика - это очень замкнутое поле с большим количеством эзотерической терминологии, некоторые из которых относятся к вещам, которые постигают годы, некоторые из которых относятся к вещам, которые тривиальны, но люди просто выбрали странное слово, чтобы назвать их. Мои главные указатели:
- Выйдите из земли UIImage как можно раньше в вашем коде. Лучший способ избежать накладных расходов и задержек при переходе в Metal land - это как можно быстрее получить изображения в совместимом с графическим процессором представлении.
- Когда вы находитесь за пределами земли UIImage, всегда узнавайте свой порядок каналов (RGBA, BGRA). В любой точке кода, который вы редактируете, у вас должна быть ментальная модель того, какой формат пикселя имеет каждая CVPixelBuffer / MTLTexture.
- Читайте заранее умноженную против неумноженной альфа, вы можете не столкнуться с проблемами с этим, но это неоднократно меня отталкивало, когда я впервые учился.
- общий размер байта растрового изображения / пикселя в буфере = bytesPerRow * высота