У меня есть MTLTexture, сгенерированная из ARMatteGenerator, которую я хотел бы перенести в OpenGL.
Я не очень разбираюсь в Objective- C, поэтому могу допускать очевидные ошибки для других ...
Я видел this , который создает металлическую текстуру из пиксельного буфера, но мне нужно было бы сделать это наоборот: связать PixelBuffer с уже существующей MTLTexture - в объективе C -.
Моя цель - использовать его со слоем OpenGL.
Я нашел метод, который превращает текстуру MTL в NSData *:
- (NSData*) getTextureBytes:(id<MTLTexture>)texture
{
int bytesPerPixel = 4;
int width = (int) texture.width;
int height = (int) texture.height;
NSMutableData *mFramebuffer = [NSMutableData dataWithLength:width*height*bytesPerPixel];
[texture getBytes:(void*)mFramebuffer.mutableBytes
bytesPerRow:width*bytesPerPixel
bytesPerImage:width*height*bytesPerPixel
fromRegion:MTLRegionMake2D(0, 0, width, height)
mipmapLevel:0
slice:0];
return [NSData dataWithData:mFramebuffer];
}
Но тогда я не знаю, как получить ссылку на CVPixelBuffer.
Я немного сбит с толку относительно того, как я должен действовать ...
Лучший ,
P
Как указывает @trojanfoe, дает мне положительный результат, но текстура выглядит черной.
Мой _updateMatteTextures
выглядит следующим образом:
- (void) _updateMatteTextures:(id<MTLCommandBuffer>) commandBuffer {
if(self.currentDrawable && _session.currentFrame.capturedImage){
alphaTexture = [matteDepthTexture generateMatteFromFrame:_session.currentFrame commandBuffer:commandBuffer];
dilatedDepthTexture = [matteDepthTexture generateDilatedDepthFromFrame:_session.currentFrame commandBuffer:commandBuffer];
// ===============================================================
int bytesPerPixel = 4;
int width = (int) alphaTexture.width;
int height = (int) alphaTexture.height;
CVReturn err = noErr;
err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
width,
height,
formatInfo.cvPixelFormat,
alphaTexture,
width * bytesPerPixel,
stillImageDataReleaseCallback,
alphaTexture,
NULL,
&alphaTextureGLES);
if (err != kCVReturnSuccess) {
if(err == kCVReturnInvalidPixelFormat){
NSLog(@"Invalid pixel format");
}
if(err == kCVReturnInvalidPixelBufferAttributes){
NSLog(@"Invalid pixel buffer attributes");
}
if(err == kCVReturnInvalidSize){
NSLog(@"invalid size");
}
if(err == kCVReturnPixelBufferNotOpenGLCompatible){
NSLog(@"not opengl compatible");
}
}else{
NSLog(@"ok CVPixelBufferCreateWithBytes SUCCESS");
}
// correct wrapping and filtering
glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), CVOpenGLESTextureGetName(alphaTextureGLES));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), 0);
}else{
return;
}
Я пытался использовать магазин с результатом CVPixelBufferCreateWithBytes
в CVPixelBufferRef
, с тем же успехом (черная текстура):
if(self.currentDrawable && _session.currentFrame.capturedImage){
alphaTexture = [matteDepthTexture generateMatteFromFrame:_session.currentFrame commandBuffer:commandBuffer];
dilatedDepthTexture = [matteDepthTexture generateDilatedDepthFromFrame:_session.currentFrame commandBuffer:commandBuffer];
// ===============================================================
int bytesPerPixel = 4;
int width = (int) alphaTexture.width;
int height = (int) alphaTexture.height;
CVReturn err = noErr;
err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
width,
height,
formatInfo.cvPixelFormat,
alphaTexture,
width * bytesPerPixel,
stillImageDataReleaseCallback,
alphaTexture,
NULL,
&pixel_bufferAlpha);
if (err != kCVReturnSuccess) {
if(err == kCVReturnInvalidPixelFormat){
NSLog(@"Invalid pixel format");
}
if(err == kCVReturnInvalidPixelBufferAttributes){
NSLog(@"Invalid pixel buffer attributes");
}
if(err == kCVReturnInvalidSize){
NSLog(@"invalid size");
}
if(err == kCVReturnPixelBufferNotOpenGLCompatible){
NSLog(@"not opengl compatible");
}
}else{
NSLog(@"ok CVPixelBufferCreateWithBytes SUCCESS");
}
CVPixelBufferLockBaseAddress(pixel_bufferAlpha, 0);
err = noErr;
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_videoTextureAlphaCache,
pixel_bufferAlpha,
nil,
GL_TEXTURE_2D,
formatInfo.glInternalFormat,
CVPixelBufferGetWidth(pixel_bufferAlpha),
CVPixelBufferGetHeight(pixel_bufferAlpha),
formatInfo.glFormat,
formatInfo.glType,
0,
&alphaTextureGLES);
if (err != kCVReturnSuccess) {
CVBufferRelease(alphaTextureGLES);
if(err == kCVReturnInvalidPixelFormat){
NSLog(@"Invalid pixel format");
}
if(err == kCVReturnInvalidPixelBufferAttributes){
NSLog(@"Invalid pixel buffer attributes");
}
if(err == kCVReturnInvalidSize){
NSLog(@"invalid size");
}
if(err == kCVReturnPixelBufferNotOpenGLCompatible){
NSLog(@"not opengl compatible");
}
}
// clear texture cache
CVOpenGLESTextureCacheFlush(_videoTextureAlphaCache, 0);
// correct wrapping and filtering
glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), CVOpenGLESTextureGetName(alphaTextureGLES));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), 0);
CVPixelBufferUnlockBaseAddress(pixel_bufferAlpha, 0);
}else{
return;
}
С:
CVPixelBufferRef pixel_bufferAlpha;
CVOpenGLESTextureCacheRef _videoTextureAlphaCache;
void stillImageDataReleaseCallback(void *releaseRefCon, const void *baseAddress)
{
free((void *)baseAddress);
}
Не уверен, что я здесь не так делаю.