OpenGL Texture rendering as black

921 views Asked by At

I'm using the Syphon framework to try and push frames of video from a server to a client application.

Syphon requires you to use OpenGL textures instead of normal images.

Because of this, I'm trying to render a CGImageRef as a texture and send it on to be published.

I'm creating my CGL context as so:

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);

I already have a CGImageRef that I know can be rendered properly as an NSImage.

I'm rendering the texture as so:

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);

The rendering code is in a different class, but the context should be passed through and is the same.

I've tried the advice in pretty much every other instance of this problem to no avail.

2

There are 2 answers

8
AudioBubble On BEST ANSWER

The second-to-last parameter in glTexImage2D is:

type
Specifies the data type of the pixel data. The following symbolic values are accepted: GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV.

GL_TEXTURE_2D doesn't make sense there, it should be whatever the data type of elements of imageData is.

You should also be checking your OpenGL errors with glGetError or ARB_debug_output. You would have immediately be shown what's wrong:

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

There are a few problems in this code. The following are critical to get things working:

  • As also pointed out in an earlier answer by @orost, the type parameter for the glTexImage2D() call is invalid. It should be:

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    
  • The texture is never attached as an FBO target. While you set up the FBO, you need:

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, _texture, 0);
    

There are a couple more items that probably won't keep you from getting it running, but I would recommend to change them anyway:

  • You don't need to specify data for the texture if you're going to create the content by rendering to it. The data you pass to glTexImage2D() is uninitialized anyway, so that can't do much good. It's much cleaner to pass NULL as the data argument, as I already did in the call shown above.
  • Since you're using OpenGL 3.2, there's really no need to use the EXT form of the FBO entry points. This is standard functionality in OpenGL 3.x. The EXT form will probably work as long as you use it consistently, but you risk ugly surprises if you mix it with standard entry points.