Ios 如何将CVPixelBuffer设置为顶点着色器的输入?

Ios 如何将CVPixelBuffer设置为顶点着色器的输入?,ios,rendering,metal,Ios,Rendering,Metal,我想使用Apple Metal渲染路径处理CVPixelBuffer 如何变换CVPixelBuffer,使其符合顶点着色器的输入? 不知道如何从CVPixelBuffer中提取颜色/位置值,以便我能够从主机中设置它们。类似以下内容: 创建一个纹理 使用将CVPixelBuffer复制到纹理中 用作第一个参数 不要创建顶点缓冲区。你不需要它 在金属中创建顶点着色器 将UInt vid[[vertex_id]]作为顶点着色器函数的输入 调用drawPrimitives时,请指定vertexCou

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

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

类似以下内容:

  • 创建一个纹理
  • 使用将CVPixelBuffer复制到纹理中
  • 用作第一个参数
  • 不要创建顶点缓冲区。你不需要它
  • 在金属中创建顶点着色器
  • 将UInt vid[[vertex_id]]作为顶点着色器函数的输入
  • 调用drawPrimitives时,请指定vertexCount:width*height
视频将从0变为宽*高。然后可以基于vid的值对纹理进行采样

请记住:

  • 像素缓冲区的大小可能最接近4或8
  • 使用0.0到1.0的规格化坐标对纹理进行采样。不是像素坐标
以下是我用来将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);
    }
  }
}
#pragma标记-AVCaptureVideoDataOutputSampleBufferDelegate
-(void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)SampleBufferfromConnection:(AVCaptureConnection*)连接
{
CVPixelBufferRef pixelBuffer=CMSampleBufferGetImageBuffer(sampleBuffer);
id纹理=零;
{
size\u t width=CVPixelBufferGetWidth(pixelBuffer);
大小\u t高度=CVPixelBufferGetHeight(pixelBuffer);
MTLPixelFormat pixelFormat=MTLPixelFormatBGRA8Unorm;
CVMetalTextureRef metalTextureRef=NULL;
CVReturn status=CVMetalTextureCacheCreateTextureFromImage(NULL、_textureCache、pixelBuffer、NULL、pixelFormat、宽度、高度、0和metalTextureRef);
如果(状态==kCVReturnSuccess)
{
纹理=CVMetalTextureGetTexture(metalTextureRef);
if(自授权){
[自授权纹理更新:纹理];
}
CFRelease(metalTextureRef);
}
}
}

创建纹理后,只需将其传递给renderCommandEncoder。如果需要帮助,请在评论中告诉我。

顶点缓冲区通常包含3D对象的X、Y、Z坐标,而不是像素的RGB值。也许你想改为创建纹理?感谢@karsten修复了一些东西,但由于某种原因被拒绝了。我对答案做了同样的修改。嘿,哈瓦!我试图从您的代码中理解的两件事:如果您将像素格式设置为MTLPixelFormatBGRA8Unorm,则意味着您更改了视频设置以发送带有BGRA像素的缓冲区,对吗?我目前正在深度贴图中使用此功能,我认为它很可能会失去很多精度-当应用一些过滤器时,您可以在深度贴图中看到明确的“步骤”。我使用这种方法将CVPixelBuffer转换为MTLTexture,但XCode GPU捕获配置文件告诉我有一个洞察:“CoreVideo缺少使用标志”,我认为这意味着通过这种方式创建的MTLTexture没有使用标志,那么有人知道如何在通过这种方式创建时添加标志吗?