Получение вне экрана
Приложения OpenGL могут хотеть использовать OpenGL для рендеринга изображений, фактически не выводя на экран их пользователю. Например, приложение для обработки изображений могло бы представить изображение, затем скопировать то изображение назад в приложение и сохранить его на диск. Другая полезная стратегия состоит в том, чтобы создать промежуточные изображения, использующиеся позже для рендеринга дополнительного содержания. Например, Ваше приложение могло бы хотеть представить изображение и использовать его в качестве текстуры в будущей передаче рендеринга. Для лучшей производительности внеэкранными целями должен управлять OpenGL. Наличие OpenGL управляет, внеэкранные цели позволяет Вам избегать копировать пиксельные данные назад в Ваше приложение, кроме тех случаев, когда это абсолютно необходимо.
OS X предлагает две полезных опции для создания внеэкранных целей рендеринга:
Объекты кадрового буфера. Расширение кадрового буфера OpenGL позволяет Вашему приложению создавать полностью поддерживаемые внеэкранные кадровые буферы OpenGL. Объекты кадрового буфера полностью поддерживаются как межплатформенное расширение, таким образом, они - предпочтительный способ создать вне экрана представляющие цели. Посмотрите Рендеринг к Объекту Кадрового буфера.
Пиксельный буфер drawable объекты. Пиксельный буфер drawable объекты является специфичной для Apple технологией для создания внеэкранной цели. Каждый специфичный для Apple OpenGL APIs обеспечивает подпрограммы для создания внеэкранного аппаратно ускоренного пиксельного буфера. Пиксельные буферы рекомендуются для использования только, когда объекты кадрового буфера не доступны. Посмотрите Рендеринг к Пиксельному Буферу.
Рендеринг к объекту кадрового буфера
Расширение кадрового буфера OpenGL (GL_EXT_framebuffer_object
) позволяет приложениям создавать вне экрана представляющие цели из OpenGL. OpenGL управляет памятью для этих кадровых буферов.
Объект кадрового буфера (FBO) подобен drawable объекту, кроме drawable объекта определенный для оконной системы объект, тогда как объект кадрового буфера является агностическим окном объектом, это определяется в стандарте OpenGL. После рисования к объекту кадрового буфера это прямо, чтобы считать пиксельные данные в приложение или использовать его в качестве исходных данных для других команд OpenGL.
Объекты кадрового буфера предлагают много преимуществ:
Они - независимая оконная система, который делает код портирования проще.
Их просто установить и сохранить память. Нет никакой потребности установить атрибуты и получить объект формата пикселя.
Они связаны с единственным контекстом OpenGL, тогда как каждый пиксельный буфер должен быть связан с контекстом.
Можно переключиться между ними быстрее, так как нет никакого контекстного переключения как с пиксельными буферами. Поскольку все команды представляются единственным контекстом, никакая дополнительная сериализация не требуется.
Они могут совместно использовать буферы глубины; пиксельные буферы не могут.
Можно использовать их для 2D пиксельных изображений и текстурировать изображения.
Полнота является ключевым понятием к пониманию объектов кадрового буфера. Полнота является состоянием, указывающим, удовлетворяет ли объект кадрового буфера все требования для рисования. Вы тестируете на это состояние после выполнения всей необходимой работы установки. Если объект кадрового буфера не завершен, он не может использоваться в качестве места назначения для рендеринга операций и как источник для операций чтения.
Полнота зависит от многих факторов, которые не возможно уплотнить в один или два оператора, но эти факторы полностью определяются в спецификации OpenGL для расширения объекта кадрового буфера. Спецификация описывает требования для внутренних форматов изображений, присоединенных к кадровому буферу, как определить, является ли формат цветом - глубина - и шаблон-renderable, а также другие требования.
До использования объектов кадрового буфера считайте спецификацию OpenGL, не только определяющую объект кадрового буфера API, но и обеспечивающую подробные определения всех условий, необходимых для понимания их использования, и показывающую несколько примеров кода.
Остаток от этого раздела обеспечивает обзор того, как использовать кадровый буфер или в качестве текстуры или в качестве изображения. Функции раньше устанавливали текстуры, и изображения немного отличаются. API для изображений использует renderbuffer терминологию, определенную в спецификации OpenGL. Изображение renderbuffer является просто 2D пиксельным изображением. API для текстур использует терминологию текстуры, как Вы могли бы ожидать. Например, одно из требований установки объекта кадрового буфера для текстуры glFramebufferTexture2DEXT
, тогда как требование установки объекта кадрового буфера для изображения glFramebufferRenderbufferEXT
. Вы будете видеть, как установить простой объект кадрового буфера для каждого типа получения, запустившись сначала с текстур.
Используя объект кадрового буфера как текстура
Это основные шаги, должен был установить объект кадрового буфера для рисования текстуры вне экрана:
Удостоверьтесь расширение кадрового буфера (
GL_EXT_framebuffer_object
) поддерживается в системе, на которой работает Ваш код. Посмотрите Определение Возможностей OpenGL, Поддерживаемых Средством рендеринга.Проверьте пределы средства рендеринга. Например, Вы могли бы хотеть вызвать функцию OpenGL
glGetIntegerv
проверять максимальный размер текстуры (GL_MAX_TEXTURE_SIZE
) или узнайте максимальное количество цветных буферов, которые можно присоединить к объекту кадрового буфера (GL_MAX_COLOR_ATTACHMENTS_EXT
).Генерируйте имя объекта кадрового буфера путем вызывания следующей функции:
void glGenFramebuffersEXT (GLsizei n, GLuint *ids);
n
число имен объектов кадрового буфера, которые Вы хотите создать.По возврату,
*ids
точки к сгенерированным именам.Свяжите имя объекта кадрового буфера с целью кадрового буфера путем вызывания следующей функции:
void glBindFramebufferEXT(GLenum target, GLuint framebuffer);
target
должна быть константаGL_FRAMEBUFFER_EXT
.framebuffer
установлен в неиспользованное имя объекта кадрового буфера.По возврату объект кадрового буфера инициализируется к значениям состояния, описанным в спецификации OpenGL для расширения объекта кадрового буфера. Каждая точка подключения кадрового буфера инициализируется к значениям состояния точки подключения, описанным в спецификации. Число точек подключения равно
GL_MAX_COLOR_ATTACHMENTS_EXT
плюс 2 (для глубины и точек подключения шаблона).Каждый раз, когда объект кадрового буфера связывается, команды рисования направлены к нему вместо того, чтобы быть направленными к drawable, связанному с контекстом рендеринга.
Генерируйте имя текстуры.
void glGenTextures(GLsizei n, GLuint *textures);
n
число имен объектов текстуры, которые Вы хотите создать.По возврату,
*textures
точки к сгенерированным именам.Свяжите имя текстуры к цели текстуры.
void glBindTexture(GLenum target, GLuint texture);
target
тип текстуры для привязки.texture
имя текстуры, которое Вы просто создали.Установите среду текстуры и параметры.
Определите текстуру путем вызывания надлежащей функции OpenGL, чтобы указать цель, уровень детализации, внутренний формат, размерности, границу, формат пиксельных данных, и текстурировать хранение данных.
Присоедините текстуру к кадровому буферу путем вызывания следующей функции:
void glFramebufferTexture2DEXT (GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level);
target
должен бытьGL_FRAMEBUFFER_EXT
.attachment
должна быть одна из точек подключения кадрового буфера:GL_STENCIL_ATTACHMENT_EXT
,GL_DEPTH_ATTACHMENT_EXT
, илиGL_COLOR_ATTACHMENTn_EXT
, гдеn
число от0
кGL_MAX_COLOR_ATTACHMENTS_EXT-1
.textarget
цель текстуры.texture
существующий объект текстуры.level
уровень множественного отображения изображения текстуры для присоединения к кадровому буферу.Проверьте, чтобы удостовериться, что кадровый буфер завершен путем вызывания следующей функции:
GLenum glCheckFramebufferStatusEXT(GLenum target);
target
должна быть константаGL_FRAMEBUFFER_EXT
.Эта функция возвращает постоянное состояние. Необходимо протестировать, чтобы удостовериться, что константа
GL_FRAMEBUFFER_COMPLETE_EXT
. Если это не, посмотрите, что спецификация OpenGL для кадрового буфера возражает расширению для описания других констант в перечислении состояния.Содержание рендеринга к текстуре. Необходимо удостовериться, что связали различную текстуру с кадровым буфером, возражают или отключают текстурирование перед рендерингом содержания. Если Вы представляете к присоединению текстуры объекта кадрового буфера с той же самой текстурой, в настоящее время связываемой и включенной, результат не определен.
Для рисования содержания текстуры к окну сделайте окно целью всех команд рендеринга путем вызывания функции
glBindFramebufferEXT
и передача константыGL_FRAMEBUFFER_EXT
и0
. Окно всегда указывается как0
.Используйте присоединение текстуры в качестве нормальной текстуры путем привязки его, включения текстурирования и получения.
Удалите текстуру.
Удалите объект кадрового буфера путем вызывания следующей функции:
void glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers);
n
число объектов кадрового буфера удалить.*framebuffers
точки к массиву, содержащему имена объектов кадрового буфера.
Перечисление 5-1 показывает код, выполняющий эти задачи. Этот пример создает и рисует к единственному объекту кадрового буфера.
Перечисление 5-1 , Настраивающее кадровый буфер для текстурирования
GLuint framebuffer, texture; |
GLenum status; |
glGenFramebuffersEXT(1, &framebuffer); |
// Set up the FBO with one texture attachment |
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, TEXWIDE, TEXHIGH, 0, |
GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
GL_TEXTURE_2D, texture, 0); |
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) |
// Handle error here |
// Your code to draw content to the FBO |
// ... |
// Make the window the target |
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
//Your code to use the contents of the FBO |
// ... |
//Tear down the FBO and texture attachment |
glDeleteTextures(1, &texture); |
glDeleteFramebuffersEXT(1, &framebuffer); |
Используя объект кадрового буфера как изображение
Существует большое подобие между установкой объекта кадрового буфера для составления изображений и установкой той для рисования текстур. Это основные шаги, должен был установить объект кадрового буфера для рисования 2D пиксельного изображения (изображение renderbuffer) вне экрана:
Удостоверьтесь расширение кадрового буфера (
EXT_framebuffer_object
) поддерживается на средстве рендеринга, на котором работает Ваш код.Проверьте пределы средства рендеринга. Например, Вы могли бы хотеть вызвать функцию OpenGL
glGetIntegerv
узнать максимальное количество цветных буферов (GL_MAX_COLOR_ATTACHMENTS_EXT
).Генерируйте имя объекта кадрового буфера путем вызывания функции
glGenFramebuffersEXT
.Свяжите имя объекта кадрового буфера с целью кадрового буфера путем вызывания функции
glBindFramebufferEXT
.Генерируйте renderbuffer имя объекта путем вызывания следующей функции:
void glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers );
n
число renderbuffer имен объектов для создания.*renderbuffers
точки к хранению для сгенерированных имен.Свяжите renderbuffer имя объекта с целью renderbuffer путем вызывания следующей функции:
void glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);
target
должна быть константаGL_RENDERBUFFER_EXT
.renderbuffer
renderbuffer имя объекта, сгенерированное ранее.Создайте хранение данных и установите формат пикселя и размерности изображения renderbuffer путем вызывания следующей функции:
void glRenderbufferStorageEXT (GLenum target, GLenum internalformat,
GLsizei width, GLsizei height);
target
должна быть константаGL_RENDERBUFFER_EXT
.internalformat
формат пикселя изображения. Значение должно бытьRGB
,RGBA
,DEPTH_COMPONENT
,STENCIL_INDEX
, или один из других форматов перечислен в спецификации OpenGL.width
ширина изображения, в пикселях.height
высота изображения, в пикселях.Присоедините renderbuffer к цели кадрового буфера путем вызывания функции
glFramebufferRenderbufferEXT
.void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment,
GLenum renderbuffertarget, GLuint renderbuffer);
target
должна быть константаGL_FRAMEBUFFER_EXT
.attachment
должна быть одна из точек подключения кадрового буфера:GL_STENCIL_ATTACHMENT_EXT
,GL_DEPTH_ATTACHMENT_EXT
, или GL_COLOR_ATTACHMENTn_EXT
, откуда n является числом0
кGL_MAX_COLOR_ATTACHMENTS_EXT–1
.renderbuffertarget
должна быть константаGL_RENDERBUFFER_EXT
.renderbuffer
должен быть установлен в имя объекта renderbuffer, что Вы хотите присоединить к кадровому буферу.Проверьте, чтобы удостовериться, что кадровый буфер завершен путем вызывания следующей функции:
enum glCheckFramebufferStatusEXT(GLenum target);
target
должна быть константаGL_FRAMEBUFFER_EXT
.Эта функция возвращает постоянное состояние. Необходимо протестировать, чтобы удостовериться, что константа
GL_FRAMEBUFFER_COMPLETE_EXT
. Если это не, посмотрите, что спецификация OpenGL для кадрового буфера возражает расширению для описания других констант в перечислении состояния.Содержание рендеринга к renderbuffer.
Для доступа к содержанию объекта renderbuffer свяжите объект кадрового буфера и затем используйте функции OpenGL такой как
glReadPixels
илиglCopyTexImage2D
.Удалите объект кадрового буфера с его renderbuffer присоединением.
Перечисление 5-2 показывает код, устанавливающий и рисующий к единственному объекту renderbuffer. Ваше приложение может установить больше чем один объект renderbuffer, если это требует их.
Перечисление 5-2 , Настраивающее renderbuffer для рисования изображений
GLuint framebuffer, renderbuffer; |
GLenum status; |
// Set the width and height appropriately for your image |
GLuint imageWidth = 1024, |
imageHeight = 1024; |
//Set up a FBO with one renderbuffer attachment |
glGenFramebuffersEXT(1, &framebuffer); |
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); |
glGenRenderbuffersEXT(1, &renderbuffer); |
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer); |
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, imageWidth, imageHeight); |
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
GL_RENDERBUFFER_EXT, renderbuffer); |
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) |
// Handle errors |
//Your code to draw content to the renderbuffer |
// ... |
//Your code to use the contents |
// ... |
// Make the window the target |
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
// Delete the renderbuffer attachment |
glDeleteRenderbuffersEXT(1, &renderbuffer); |
Рендеринг к пиксельному буферу
Строка расширения OpenGL GL_APPLE_pixel_buffer
обеспечивает аппаратно ускоренный вне экрана рендеринг для пиксельного буфера. Пиксельный буфер обычно используется в качестве источника текстуры. Это может также использоваться для удаленного рендеринга.
Необходимо создать контекст рендеринга для каждого пиксельного буфера. Например, если Вы хотите использовать пиксельный буфер в качестве источника текстуры, Вы создаете один контекст рендеринга, присоединенный к пиксельному буферу и второму контексту, присоединенному к окну или представлению.
Первый шаг в использовании пиксельного буфера должен создать его. Специфичный для Apple OpenGL APIs каждый обеспечивает подпрограмму с этой целью:
NSOpenGLPixelBuffer
методinitWithTextureTarget:textureInternalFormat:textureMaxMipMapLevel:pixelsWide:pixelsHigh:
Функция CGL
CGLCreatePBuffer
Каждая из этих подпрограмм требует, чтобы Вы обеспечили цель текстуры, внутренний формат, максимальный уровень множественного отображения, и ширину и высоту текстуры.
Цель текстуры должна быть одной из этих констант текстуры OpenGL: GL_TEXTURE_2D
для 2D текстуры, GL_TEXTURE_RECTANGLE_ARB
для прямоугольного (не power-two) текстура, или GL_TEXTURE_CUBE_MAP
поскольку куб отображает текстуру.
Внутренний формат указывает, как интерпретировать данные для текстурирования операций. Можно предоставить любую из этих опций: GL_RGB
(каждый пиксель является трехкомпонентной группой), GL_RGBA
(каждый пиксель является четырехкомпонентной группой), или GL_DEPTH_COMPONENT
(каждый пиксель является единственным компонентом глубины).
Максимальный уровень множественного отображения должен быть 0
для пиксельного буфера, не имеющего множественного отображения. Значение, которое Вы предоставляете, не должно превышать фактическое максимальное количество уровней множественного отображения, которые могут быть представлены с данной шириной и высотой.
Обратите внимание на то, что ни одна из подпрограмм, создающих пиксельный буфер, не выделяет необходимое хранение. Хранение выделяется системой в то время, когда Вы присоединяете пиксельный буфер к контексту рендеринга.
Установка пиксельного буфера для внеэкранного получения
После создания пиксельного буфера общая процедура для использования пиксельного буфера для рисования подобна способу, которым Вы устанавливаете окна и представления для рисования:
Укажите средство рендеринга и буферизуйте атрибуты.
Получите объект формата пикселя.
Создайте контекст рендеринга и сделайте его текущим.
Присоедините пиксельный буфер к контексту с помощью соответствующего Apple присоединяемая функция OpenGL:
setPixelBuffer:cubeMapFace:mipMapLevel:currentVirtualScreen:
методNSOpenGLContext
класс дает получателю команду представлять в пиксельном буфере.Функция CGL
CGLSetPBuffer
присоединяет CGL рендеринг контекста к пиксельному буферу.
Нарисуйте, как Вы обычно были бы, с помощью OpenGL.
Используя пиксельный буфер как источник текстуры
Пиксельные буферы позволяют Вам выполнить прямое текстурирование, не подвергаясь стоимости дополнительных копий. После рисования к пиксельному буферу можно создать текстуру путем выполнения этих шагов:
Генерируйте имя текстуры путем вызывания функции OpenGL
glGenTextures
.Свяжите именованную текстуру с целью путем вызывания функции OpenGL
glBindTexture
.Установите параметры текстуры путем вызывания функции OpenGL
glTexEnvParameter
.Установите пиксельный буфер как источник для текстуры путем вызова одного из следующего Apple функции OpenGL:
setTextureImageToPixelBuffer:colorBuffer:
методNSOpenGLContext
класс присоединяет данные изображения в пиксельном буфере к объекту текстуры, в настоящее время связываемому получателем.Функция CGL
CGLTexImagePBuffer
связывает содержание пиксельного буфера CGL как источник данных для объекта текстуры.
Контекст, который Вы присоединяете к пиксельному буферу, является целевым контекстом рендеринга: контекст, использующий пиксельный буфер в качестве источника данных текстуры. Каждая из этих подпрограмм требует a
source
параметр, который является OpenGL, постоянным, который указывает исходный буфер для текстурирования от. Исходный параметр должен быть допустимым буфером OpenGL, такой какGL_FRONT
,GL_BACK
, илиGL_AUX0
, и должно быть совместимо с буферными атрибутами, используемыми для создания контекста OpenGL, связанного с пиксельным буфером. Это означает, что пиксельный буфер должен обладать рассматриваемым буфером для текстурирования для следования. Например, если буферный атрибут, используемый с пиксельным буфером, только единственный буферизованный, то текстурирование отGL_BACK
буфер перестанет работать.Если Вы изменяете содержание какого-либо пиксельного буфера, содержащего, множественно отображают уровни, необходимо вызвать соответствующий Apple функция OpenGL снова (
setTextureImageToPixelBuffer:colorBuffer:
илиCGLTexImagePBuffer
) прежде, чем нарисовать с пикселем буферизуют, чтобы гарантировать, что содержание синхронизируется с OpenGL. Для синхронизации содержания пиксельных буферов без множественных отображений просто снова переплетите к использованию объекта текстурыglBind
.Нарисуйте примитивы с помощью надлежащих координат текстуры. (См. «Красную книгу» — Руководство по программированию OpenGL — для подробных данных.)
Вызвать
glFlush
заставить все команды рисования выполняться.Когда Вы больше не нуждаетесь в объекте текстуры, вызываете функцию OpenGL
glDeleteTextures
.Установите текущий контекст в
NULL
использование одного из Apple подпрограммы OpenGL:makeCurrentContext
методNSOpenGLContext
классФункция CGL
CGLSetCurrentContext
Уничтожьте пиксельный буфер путем вызова
CGLDestroyPBuffer
.Уничтожьте контекст путем вызова
CGLDestroyContext
.Уничтожьте формат пикселя путем вызова
CGLDestroyPixelFormat
.
Вы могли бы счесть эти инструкции полезными при использовании пиксельных буферов для текстурирования:
Вы не можете выполнить вызовы текстурирования OpenGL, изменяющие пиксельное содержимое буфера (такой как
glTexSubImage2D
илиglCopyTexImage2D
) с пикселем буферизуют как место назначения. Можно использовать команды текстурирования для чтения данных из пиксельного буфера, такой какglCopyTexImage2D
, с пикселем буферизуют текстуру как источник. Можно также использовать функции OpenGL такой какglReadPixels
для чтения содержания пикселя буферизуют непосредственно от пиксельного буферного контекста.Текстурирование может не привести к намеченным результатам, не сообщая об ошибке. Необходимо удостовериться, что Вы включаете надлежащую цель текстуры, устанавливаете совместимый режим фильтра и придерживаетесь других требований, описанных в спецификации OpenGL.
Когда Вы текстурируете от пиксельного буфера, Вы не обязаны устанавливать совместное использование контекста. Вы можете иметь различные объекты формата пикселя и контексты рендеринга и для пиксельного буфера и для целевого drawable объекта, не совместно используя ресурсы, и все еще текстурировать использование пиксельного буфера в целевом контексте.
Рендеринг к пиксельному буферу в удаленной системе
Выполните эти шаги для рендеринга к пиксельному буферу в удаленной системе. Удаленной системе не должны были присоединять дисплей к нему.
Когда Вы устанавливаете средство рендеринга и буферизуете атрибуты, включаете удаленный пиксельный буферный атрибут
kCGLPFARemotePBuffer
.Войдите в систему удаленной машины с помощью
ssh
команда для обеспечения безопасности.Запустите приложение в целевой системе.
Получите содержание.