【问题标题】:How to set a CVPixelBuffer as an input for a vertex shader?如何将 CVPixelBuffer 设置为顶点着色器的输入?
【发布时间】:2014-10-25 23:46:45
【问题描述】:

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

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

【问题讨论】:

  • 顶点缓冲区通常包含 3D 对象的 X、Y、Z 坐标,而不是像素的 RGB 值。也许您想改为创建纹理?

标签: ios rendering metal


【解决方案1】:

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

#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。如果您需要这方面的帮助,请在 cmets 中告诉我。

【讨论】:

  • 嘿哈瓦!我想从您的代码中理解几件事:如果您将像素格式设置为 MTLPixelFormatBGRA8Unorm,这意味着您更改了视频设置以发送带有 BGRA 像素的缓冲区,对吧?
  • 我目前正在将此功能与深度图一起使用,我认为它很可能会失去很多精度 - 应用某些过滤器时,您可以在深度图中看到明确的“步骤”。
  • 我用这种方式将CVPixelBuffer转换为MTLTexture,但是XCode GPU Capture Profile告诉我有一个见解:“CoreVideo Missing Usage Flags”,我认为这意味着通过这种方式创建的MTLTexture没有'没有使用标志,那么有谁知道如何在通过这种方式创建时添加标志?
【解决方案2】:

类似这样的:

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

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

记住:

  • 像素缓冲区可能会将大小填充到最接近的 4 或 8。
  • 纹理使用从 0.0 到 1.0 的标准化坐标进行采样。不是像素坐标。

【讨论】:

  • 感谢@karsten 解决了一些问题,但由于某种原因被拒绝了。我对答案做了同样的修改。
猜你喜欢
  • 1970-01-01
  • 2013-11-23
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 2012-02-10
相关资源
最近更新 更多