Рендеринг текстуры OpenGL как черный

Я использую инфраструктуру Siphon, чтобы попытаться передать кадры видео с сервера в клиентское приложение.

Сифон требует от вас использовать текстуры 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);

Код рендеринга находится в другом классе, но контекст должен быть передан и тот же.

Я попробовал совет почти во всех других случаях этой проблемы, но безрезультатно.

2 ответа

Решение

Второй в последнем параметре в glTexImage2D является:

тип
Определяет тип данных данных пикселей. Следующие символические значения принимаются: 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, а также GL_UNSIGNED_INT_2_10_10_10_REV,

GL_TEXTURE_2D не имеет смысла, это должно быть независимо от типа данных элементов imageData является.

Вы также должны проверять свои ошибки OpenGL с glGetError или же ARB_debug_output, Вам бы сразу показали, что не так

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, на самом деле нет необходимости использовать EXT Форма точек входа FBO. Это стандартная функциональность в OpenGL 3.x. EXT Форма, вероятно, будет работать до тех пор, пока вы используете ее последовательно, но вы рискуете получить неприятные сюрпризы, если смешаете ее со стандартными точками входа.
Другие вопросы по тегам