2015-06-09 2 views
1

Я использую фреймворк Siphon, чтобы попытаться направить кадры видео с сервера на клиентское приложение.OpenGL Texture render as black

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

Рандеринга в другом классе, но контекст должен быть пропущен через и то же.

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

ответ

1

Второй до последнего параметра является 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) 
+0

Учитывая мой imageContext, что бы вы предложили для типа? Использую ли я GL_UNSIGNED_BYTE? – JamEngulfer

+0

@ JamEngulfer221 Я не знаком с каркасом, который вы используете. Но данные изображения обычно представляют собой float или unsigned int. – orost

+0

Глядя на код, наверняка, элементами imageData будут 'GLubyte' или unsigned bytes? – JamEngulfer

1

В этом коде есть несколько проблем. Ниже критичны, чтобы все заработало:

  • Как также отмечалось в более раннем ответе по @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, вероятно, будет работать до тех пор, пока вы будете ее использовать последовательно, но вы рискуете уродливыми сюрпризами, если будете смешивать ее со стандартными точками входа.
+0

Глядя на мой код, я думал, что imageData будет инициализирован, потому что мне показалось, что я обратил изображение в контекст, который каким-то образом использовал imageData. – JamEngulfer

+0

На тему указания данных эти данные - это то, что я хочу сделать. Если я не включу его, буквально ничего не сделать, потому что данные изображения больше нигде не упоминаются в коде рендеринга. – JamEngulfer

+0

Я думаю, что понимаю ваши намерения, но это не так, как это работает. Когда вы передаете указатель данных на 'glTexImage2D()', он используется только во время вызова для заполнения текстуры данными. Указатель не постоянно связан с текстурой. Если вы визуализируете текстуру и хотите получить копию ЦП результирующего изображения, вам нужно будет прочитать ее с помощью 'glReadPixels()'. –