Objective c OpenGL纹理渲染为黑色

Objective c OpenGL纹理渲染为黑色,objective-c,opengl,quartz-2d,syphon,Objective C,Opengl,Quartz 2d,Syphon,我正在使用Syphon框架尝试将视频帧从服务器推送到客户端应用程序 Syphon要求您使用OpenGL纹理而不是普通图像 因此,我尝试将CGImageRef渲染为纹理,并将其发送到发布 我正在创建CGL上下文,如下所示: CGLPixelFormatAttribute attribs[13] = { kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, // This sets the conte

我正在使用Syphon框架尝试将视频帧从服务器推送到客户端应用程序

Syphon要求您使用OpenGL纹理而不是普通图像

因此,我尝试将CGImageRef渲染为纹理,并将其发送到发布

我正在创建CGL上下文,如下所示:

CGLPixelFormatAttribute attribs[13] = {
    kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, // This sets the context to 3.2
    kCGLPFAColorSize,     (CGLPixelFormatAttribute)24,
    kCGLPFAAlphaSize,     (CGLPixelFormatAttribute)8,
    kCGLPFAAccelerated,
    kCGLPFADoubleBuffer,
    kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1,
    kCGLPFASamples,       (CGLPixelFormatAttribute)4,
    (CGLPixelFormatAttribute)0
};

CGLPixelFormatObj pix;
GLint npix;
CGLChoosePixelFormat(attribs, &pix, &npix);

CGLCreateContext(pix, 0, &_ctx);
我已经有了一个CGImageRef,我知道它可以正确地渲染为NSImage

我正在渲染纹理,如下所示:

CGLLockContext(cgl_ctx);

if (_texture) {
    glDeleteTextures(1, &_texture);
}

int width = 1920;
int height = 1080;

GLubyte* imageData = malloc(width * height * 4);
CGContextRef imageContext = CGBitmapContextCreate(imageData, width, height, 8, width * 4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, width, height), image);
CGContextRelease(imageContext);

GLuint frameBuffer;
GLenum status;

glGenFramebuffersEXT(1, &frameBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer);
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_TEXTURE_2D, imageData);

status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
    NSLog(@"OpenGL Error");
}

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

CGLUnlockContext(cgl_ctx);
呈现代码位于不同的类中,但上下文应该经过传递,并且是相同的


我几乎在这个问题的每一个实例中都尝试过这个建议,但都没有效果

glTexImage2D中倒数第二个参数是:

类型
指定像素数据的数据类型。接受以下符号值: “代码>glu无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的短的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的无符号的短的无6_5_版本,“代码>代码>GL>GL>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu>glu无符号签名的无符号的无符号的无符号的无符号的无符号的无符号的四四个四个城市的无符号的无符号的无符号的四个四个四个四个城市的四个城市的四个城市的四个城市的四个城市的四个城市的四个城市的四个城市的四个城市的四个地区的四个地区的四个地区的四个地区的四个地区的四个地区的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本的版本,版本的10_10_10_2和
GL_UNSIGNED_INT_2_10_10_10_10_REV

GL\u TEXTURE\u 2D
在这里没有意义,它应该是
imageData
元素的任何数据类型

您还应该使用
glGetError
ARB\u debug\u输出检查OpenGL错误。您会立即看到问题所在:

Source:OpenGL   Type:Error  ID:5    Severity:High   Message:GL_INVALID_ENUM in glTexImage2D(incompatible format = GL_RGBA, type = GL_TEXTURE_2D)

这段代码中有一些问题。以下是使事情正常运行的关键:

  • 正如@orost在前面的回答中指出的,
    glTexImage2D()
    调用的类型参数无效。应该是:

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    
  • 纹理永远不会作为FBO目标附着。在设置FBO时,您需要:

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, _texture, 0);
    
还有几个项目可能不会阻止您运行它,但我建议您无论如何都要更改它们:

  • 如果要通过渲染创建内容,则不需要为纹理指定数据。您传递给
    glTexImage2D()
    的数据无论如何都是未初始化的,因此这没有多大用处。传递
    NULL
    作为数据参数要干净得多,正如我在上面显示的调用中所做的那样
  • 因为您使用的是OpenGL 3.2,所以实际上不需要使用FBO入口点的
    EXT
    形式。这是OpenGL 3.x中的标准功能。只要你一直使用
    EXT
    表单,它可能会正常工作,但是如果你把它与标准入口点混合使用,你可能会有令人难堪的惊喜

鉴于我的imageContext,您对该类型有何建议?我会使用GL_UNSIGNED_BYTE吗?@JamEngulfer221我不熟悉您使用的框架。但是图像数据通常是浮点或无符号整数。看看代码,图像数据的元素肯定是
GLubyte
,或者是无符号字节?@JamEngulfer221如果它们是无符号字节,那么
glubunsigned\u BYTE
就是你想要的类型,是的。另外,我怎么能得到你发布的错误报告呢?我似乎找不到关于使用您提到的东西的好文档。查看我的代码,我认为imageData会被初始化,因为我认为我将图像绘制到某种使用imageData的上下文中。在指定数据的主题上,我想呈现的是该数据。如果我不包括它,实际上就没有什么可渲染的,因为在渲染代码中没有提到图像数据。我想我理解你的意图,但它不是这样工作的。当您将数据指针传递到
glTexImage2D()
时,它仅在调用期间用于用数据填充纹理。指针不会与纹理永久关联。如果渲染到纹理,并且需要结果图像的CPU副本,则需要使用
glReadPixels()
将其读回。我刚刚阅读了
glTexImage2D()
的文档,它似乎不同意您的观点。它说:
如果目标是GL_纹理_2D。。。数据以有符号或无符号字节序列的形式从数据中读取…
@JamEngulfer221是的,这与我说的有什么不同?
glTexImage2D()
调用读取调用期间传入的数据。在呼叫返回后,它不会以任何方式使用它。