создать прозрачную текстуру в Swift - PullRequest
0 голосов
/ 04 сентября 2018

Мне просто нужно создать прозрачную текстуру. (Пиксели с альфа 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 с помощью предварительного просмотра, он кажется черным. Что здесь не хватает?

UPDATE

Я только что попытался создать текстуру, используя прозрачное изображение. Код.

 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 Ответ

0 голосов
/ 07 сентября 2018

Предварительное редактирование: когда вы быстро просматриваете прозрачную текстуру, она выглядит черной. Я просто дважды проверил код, который у меня стабильно работает, - это ожидаемый результат.

Постредактирование: Вы правы, вам не следует копировать данные 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 - это как можно быстрее перевести ваши изображения в GPU-совместимое представление.
  • Когда вы находитесь за пределами земли UIImage, всегда узнавайте свой порядок каналов (RGBA, BGRA). В любой точке кода, который вы редактируете, вы должны иметь мысленную модель того, какой формат пикселя имеет каждая CVPixelBuffer / MTLTexture.
  • Читайте заранее умноженную против неумноженной альфа, вы можете не столкнуться с проблемами с этим, но это неоднократно отталкивало меня, когда я впервые учился.
  • общий размер в байтах растрового изображения / пиксельного буфера = bytesPerRow * высота
...