Разнообразие вендоров железа "обогатило" в прекрасном смысле этого слова рендеринг в текстуру. Какая только экзотика не была ( p-buffer ). На данный момент есть вменяемый вариант RTT через расширение EXT_framebuffer_object. Вся идея данного расширения сводится к добавлению нового объекта FBO ( frame buffer object ). К этому объекту можно сделать привязку различных объектов, будь то буфер цвета, глубины, трафарет или RBO (renderbuffer object).
Приступим к написанию кода
Для начала проверяем поддержку данного расширения
- - (BOOL) initFBO
- {
- // check extension
- const GLubyte* extensions = glGetString ( GL_EXTENSIONS );
- if ( extensions )
- {
- if(gluCheckExtension((GLubyte*)("GL_EXT_framebuffer_object"), extensions))
- return YES;
- }
- return NO;
- }
Создаем текстуру в которую будем рендерить
- GLuint textureId
- glGenTextures ( 1, &textureId );
- glBindTexture ( GL_TEXTURE_2D, textureId );
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexImage2D ( GL_TEXTURE_2D, 0, 4, TextureWidth, TextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
Создаем FBO объект
- GLuint frameBufferId;
- glGenFramebuffersEXT ( 1, &frameBufferId ); // 0 - это главный буфер, очевидно что id > 0
- glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, frameBufferId );
- glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, textureId, 0 ); //привязываем тексту к фрэймбуфер
- // проверяем буфер ( код ниже )
- // ...
- glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ); // восстанавливаем главный буфер
Проверка буфера
- GLenum status = glCheckFramebufferStatusEXT ( GL_FRAMEBUFFER_EXT );
- if ( status != GL_FRAMEBUFFER_COMPLETE_EXT )
- {
- switch ( status )
- {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- NSLog(@"FBO GL_FRAMEBUFFER_UNSUPPORTED_EXT");
- break;
- default:
- NSLog(@"FBO Unknown error");
- break;
- }
- return NO;
- }
Разумеется можно еще добавить создание буфера глубины или трафарета, сделать привязку к данному FBO. Если все успешно создалось то можно рендерить в текстуру.
- glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, frameBufferId ); // выставляем нужный нам буфер
- glClearColor ( 0.0f, 0.0f, 1.0f, 1.0f );
- glClear ( GL_COLOR_BUFFER_BIT );
- // что-то рисуем в текстуру ( корректируем все матрицы )
- // ...
- glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ); // восстанавливаем буфера окна
Теперь у нас в текстуре которая была привязана к данному framebuffer объекту находится то что нам нужно. Можем с ней работать как с обычной текстурой. Отрисовать всю сцену в текстуру и применить эфффект блюра. И конечно не забывайте удалять текстуры и буфера ;-)
Example OpenGL FBO (github) готовый пример показывает наглядно как с этим работать
1 комментарий:
Спасибо! А можно ли рендерить из текстуры в текстуру, не выводя на экран?
Отправить комментарий