2

尝试在 SCNRender 对象的每个调用渲染上从 MTLTexture 创建 CVPixelBufferRef:

  CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        let bytesPerRow = 4 * Int(textureSizeX)
        let region = MTLRegionMake2D(0, 0, Int(textureSizeX), Int(textureSizeY))

    var tmpBuffer = CVPixelBufferGetBaseAddress(pixelBuffer!);

    offscreenTexture.getBytes(tmpBuffer!, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)

    CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))

然后转换为 UIImage 显示在屏幕上

    let ciImage = CIImage.init(cvPixelBuffer: pixelBuffer!)
    let temporaryContext = CIContext(options: nil)
    let tempImage = temporaryContext.createCGImage(ciImage, from: CGRect(x: 0, y: 0, width: textureSizeX, height: textureSizeY))
    let uiImage = UIImage.init(cgImage: tempImage!)

但图像不显示

4

2 回答 2

7

我遇到了同样的问题并找到了以下解决方案。它就像一个魅力:)

func image(from texture: MTLTexture) -> UIImage? {
    let bytesPerPixel = 4

    // The total number of bytes of the texture
    let imageByteCount = texture.width * texture.height * bytesPerPixel

    // The number of bytes for each image row
    let bytesPerRow = texture.width * bytesPerPixel

    // An empty buffer that will contain the image
    var src = [UInt8](repeating: 0, count: Int(imageByteCount))

    // Gets the bytes from the texture
    let region = MTLRegionMake2D(0, 0, texture.width, texture.height)
    texture.getBytes(&src, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)

    // Creates an image context
    let bitmapInfo = CGBitmapInfo(rawValue: (CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue))
    let bitsPerComponent = 8
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let context = CGContext(data: &src, width: texture.width, height: texture.height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

    // Creates the image from the graphics context
    guard let dstImage = context?.makeImage() else { return nil }

    // Creates the final UIImage
    return UIImage(cgImage: dstImage, scale: 0.0, orientation: .up)
}

来源:https ://www.invasivecode.com/weblog/metal-image-processing 您可能还感兴趣:https ://github.com/hollance/CoreMLHelpers/tree/master/CoreMLHelpers

于 2018-06-28T16:06:44.103 回答
3

您应该反过来考虑,创建一个使用 CoreVideo 缓冲区作为后备缓冲区的金属纹理对象,然后以正常方式渲染到纹理中。

- (id<MTLTexture>) makeBGRACoreVideoTexture:(CGSize)size
                        cvPixelBufferRefPtr:(CVPixelBufferRef*)cvPixelBufferRefPtr
{
  int width = (int) size.width;
  int height = (int) size.height;

  // CoreVideo pixel buffer backing the indexes texture

  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithBool:YES], kCVPixelBufferMetalCompatibilityKey,
                           [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                           [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                           nil];

  CVPixelBufferRef pxbuffer = NULL;

  CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                        width,
                                        height,
                                        kCVPixelFormatType_32BGRA,
                                        (__bridge CFDictionaryRef) options,
                                        &pxbuffer);

  NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);

  *cvPixelBufferRefPtr = pxbuffer;

  CVMetalTextureRef cvTexture = NULL;

  CVReturn ret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                           _textureCache,
                                                           pxbuffer,
                                                           nil,
                                                           MTLPixelFormatBGRA8Unorm,
                                                           CVPixelBufferGetWidth(pxbuffer),
                                                           CVPixelBufferGetHeight(pxbuffer),
                                                           0,
                                                           &cvTexture);

  NSParameterAssert(ret == kCVReturnSuccess && cvTexture != NULL);

  id<MTLTexture> metalTexture = CVMetalTextureGetTexture(cvTexture);

  CFRelease(cvTexture);

  return metalTexture;
}
于 2018-06-22T17:17:09.807 回答