Рендеринг текстуры 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
Форма, вероятно, будет работать до тех пор, пока вы используете ее последовательно, но вы рискуете получить неприятные сюрпризы, если смешаете ее со стандартными точками входа.