Создать прозрачную текстуру в 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 * высота
Другие вопросы по тегам