2

我想使用 Apple Metal 渲染路径来处理 CVPixelBuffer。

如何转换 CVPixelBuffer 使其符合顶点着色器的输入?不知道如何从 CVPixelBuffer 中提取颜色/位置值,所以我可以从主机设置它们。

4

2 回答 2

2

这是我用来将 CVPixelBuffer 数据转换为 Metal 纹理的代码。

#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
  CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

  id<MTLTexture> texture = nil;

  {
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);

    MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;

    CVMetalTextureRef metalTextureRef = NULL;
    CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &metalTextureRef);
    if(status == kCVReturnSuccess)
    {
      texture = CVMetalTextureGetTexture(metalTextureRef);
      if (self.delegate){
        [self.delegate textureUpdated:texture];
      }
      CFRelease(metalTextureRef);
    }
  }
}

获得纹理后,只需将其传递给 renderCommandEncoder。如果您需要这方面的帮助,请在评论中告诉我。

于 2014-11-03T11:23:22.730 回答
1

像这样的东西:

  • 创建纹理。
  • 使用replaceRegion将 CVPixelBuffer 复制到纹理中
  • 使用getBaseAddress作为第一个参数。
  • 不要创建顶点缓冲区。你不需要它。
  • 在 Metal 中创建一个顶点着色器。
  • 将 UInt vid [[vertex_id]] 作为顶点着色器函数的输入。
  • 当您调用 drawPrimitives 时,请指定 vertexCount:width*height。

vid 将从 0 变为宽 * 高。然后,您可以根据 vid 的值对纹理进行采样。

记住:

  • 像素缓冲区可能会将大小填充到最接近的 4 或 8。
  • 纹理使用从 0.0 到 1.0 的归一化坐标进行采样。不是像素坐标。
于 2014-10-31T18:55:19.070 回答