Получение вне экрана

Приложения OpenGL могут хотеть использовать OpenGL для рендеринга изображений, фактически не выводя на экран их пользователю. Например, приложение для обработки изображений могло бы представить изображение, затем скопировать то изображение назад в приложение и сохранить его на диск. Другая полезная стратегия состоит в том, чтобы создать промежуточные изображения, использующиеся позже для рендеринга дополнительного содержания. Например, Ваше приложение могло бы хотеть представить изображение и использовать его в качестве текстуры в будущей передаче рендеринга. Для лучшей производительности внеэкранными целями должен управлять OpenGL. Наличие OpenGL управляет, внеэкранные цели позволяет Вам избегать копировать пиксельные данные назад в Ваше приложение, кроме тех случаев, когда это абсолютно необходимо.

OS X предлагает две полезных опции для создания внеэкранных целей рендеринга:

Рендеринг к объекту кадрового буфера

Расширение кадрового буфера OpenGL (GL_EXT_framebuffer_object) позволяет приложениям создавать вне экрана представляющие цели из OpenGL. OpenGL управляет памятью для этих кадровых буферов.

Объект кадрового буфера (FBO) подобен drawable объекту, кроме drawable объекта определенный для оконной системы объект, тогда как объект кадрового буфера является агностическим окном объектом, это определяется в стандарте OpenGL. После рисования к объекту кадрового буфера это прямо, чтобы считать пиксельные данные в приложение или использовать его в качестве исходных данных для других команд OpenGL.

Объекты кадрового буфера предлагают много преимуществ:

Полнота является ключевым понятием к пониманию объектов кадрового буфера. Полнота является состоянием, указывающим, удовлетворяет ли объект кадрового буфера все требования для рисования. Вы тестируете на это состояние после выполнения всей необходимой работы установки. Если объект кадрового буфера не завершен, он не может использоваться в качестве места назначения для рендеринга операций и как источник для операций чтения.

Полнота зависит от многих факторов, которые не возможно уплотнить в один или два оператора, но эти факторы полностью определяются в спецификации OpenGL для расширения объекта кадрового буфера. Спецификация описывает требования для внутренних форматов изображений, присоединенных к кадровому буферу, как определить, является ли формат цветом - глубина - и шаблон-renderable, а также другие требования.

До использования объектов кадрового буфера считайте спецификацию OpenGL, не только определяющую объект кадрового буфера API, но и обеспечивающую подробные определения всех условий, необходимых для понимания их использования, и показывающую несколько примеров кода.

Остаток от этого раздела обеспечивает обзор того, как использовать кадровый буфер или в качестве текстуры или в качестве изображения. Функции раньше устанавливали текстуры, и изображения немного отличаются. API для изображений использует renderbuffer терминологию, определенную в спецификации OpenGL. Изображение renderbuffer является просто 2D пиксельным изображением. API для текстур использует терминологию текстуры, как Вы могли бы ожидать. Например, одно из требований установки объекта кадрового буфера для текстуры glFramebufferTexture2DEXT, тогда как требование установки объекта кадрового буфера для изображения glFramebufferRenderbufferEXT. Вы будете видеть, как установить простой объект кадрового буфера для каждого типа получения, запустившись сначала с текстур.

Используя объект кадрового буфера как текстура

Это основные шаги, должен был установить объект кадрового буфера для рисования текстуры вне экрана:

  1. Удостоверьтесь расширение кадрового буфера (GL_EXT_framebuffer_object) поддерживается в системе, на которой работает Ваш код. Посмотрите Определение Возможностей OpenGL, Поддерживаемых Средством рендеринга.

  2. Проверьте пределы средства рендеринга. Например, Вы могли бы хотеть вызвать функцию OpenGL glGetIntegerv проверять максимальный размер текстуры (GL_MAX_TEXTURE_SIZE) или узнайте максимальное количество цветных буферов, которые можно присоединить к объекту кадрового буфера (GL_MAX_COLOR_ATTACHMENTS_EXT).

  3. Генерируйте имя объекта кадрового буфера путем вызывания следующей функции:

    void glGenFramebuffersEXT (GLsizei n, GLuint *ids);

    n число имен объектов кадрового буфера, которые Вы хотите создать.

    По возврату, *ids точки к сгенерированным именам.

  4. Свяжите имя объекта кадрового буфера с целью кадрового буфера путем вызывания следующей функции:

    void glBindFramebufferEXT(GLenum target, GLuint framebuffer);

    target должна быть константа GL_FRAMEBUFFER_EXT.

    framebuffer установлен в неиспользованное имя объекта кадрового буфера.

    По возврату объект кадрового буфера инициализируется к значениям состояния, описанным в спецификации OpenGL для расширения объекта кадрового буфера. Каждая точка подключения кадрового буфера инициализируется к значениям состояния точки подключения, описанным в спецификации. Число точек подключения равно GL_MAX_COLOR_ATTACHMENTS_EXT плюс 2 (для глубины и точек подключения шаблона).

    Каждый раз, когда объект кадрового буфера связывается, команды рисования направлены к нему вместо того, чтобы быть направленными к drawable, связанному с контекстом рендеринга.

  5. Генерируйте имя текстуры.

    void glGenTextures(GLsizei n, GLuint *textures);

    n число имен объектов текстуры, которые Вы хотите создать.

    По возврату, *textures точки к сгенерированным именам.

  6. Свяжите имя текстуры к цели текстуры.

    void glBindTexture(GLenum target, GLuint texture);

    target тип текстуры для привязки.

    texture имя текстуры, которое Вы просто создали.

  7. Установите среду текстуры и параметры.

  8. Определите текстуру путем вызывания надлежащей функции OpenGL, чтобы указать цель, уровень детализации, внутренний формат, размерности, границу, формат пиксельных данных, и текстурировать хранение данных.

  9. Присоедините текстуру к кадровому буферу путем вызывания следующей функции:

    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 уровень множественного отображения изображения текстуры для присоединения к кадровому буферу.

  10. Проверьте, чтобы удостовериться, что кадровый буфер завершен путем вызывания следующей функции:

    GLenum glCheckFramebufferStatusEXT(GLenum target);

    target должна быть константа GL_FRAMEBUFFER_EXT.

    Эта функция возвращает постоянное состояние. Необходимо протестировать, чтобы удостовериться, что константа GL_FRAMEBUFFER_COMPLETE_EXT. Если это не, посмотрите, что спецификация OpenGL для кадрового буфера возражает расширению для описания других констант в перечислении состояния.

  11. Содержание рендеринга к текстуре. Необходимо удостовериться, что связали различную текстуру с кадровым буфером, возражают или отключают текстурирование перед рендерингом содержания. Если Вы представляете к присоединению текстуры объекта кадрового буфера с той же самой текстурой, в настоящее время связываемой и включенной, результат не определен.

  12. Для рисования содержания текстуры к окну сделайте окно целью всех команд рендеринга путем вызывания функции glBindFramebufferEXT и передача константы GL_FRAMEBUFFER_EXT и 0. Окно всегда указывается как 0.

  13. Используйте присоединение текстуры в качестве нормальной текстуры путем привязки его, включения текстурирования и получения.

  14. Удалите текстуру.

  15. Удалите объект кадрового буфера путем вызывания следующей функции:

    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) вне экрана:

  1. Удостоверьтесь расширение кадрового буфера (EXT_framebuffer_object) поддерживается на средстве рендеринга, на котором работает Ваш код.

  2. Проверьте пределы средства рендеринга. Например, Вы могли бы хотеть вызвать функцию OpenGL glGetIntegerv узнать максимальное количество цветных буферов (GL_MAX_COLOR_ATTACHMENTS_EXT).

  3. Генерируйте имя объекта кадрового буфера путем вызывания функции glGenFramebuffersEXT.

  4. Свяжите имя объекта кадрового буфера с целью кадрового буфера путем вызывания функции glBindFramebufferEXT.

  5. Генерируйте renderbuffer имя объекта путем вызывания следующей функции:

    void  glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers );

    n число renderbuffer имен объектов для создания.

    *renderbuffers точки к хранению для сгенерированных имен.

  6. Свяжите renderbuffer имя объекта с целью renderbuffer путем вызывания следующей функции:

    void glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);

    target должна быть константа GL_RENDERBUFFER_EXT.

    renderbuffer renderbuffer имя объекта, сгенерированное ранее.

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

  8. Присоедините 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, что Вы хотите присоединить к кадровому буферу.

  9. Проверьте, чтобы удостовериться, что кадровый буфер завершен путем вызывания следующей функции:

    enum  glCheckFramebufferStatusEXT(GLenum target);

    target должна быть константа GL_FRAMEBUFFER_EXT.

    Эта функция возвращает постоянное состояние. Необходимо протестировать, чтобы удостовериться, что константа GL_FRAMEBUFFER_COMPLETE_EXT. Если это не, посмотрите, что спецификация OpenGL для кадрового буфера возражает расширению для описания других констант в перечислении состояния.

  10. Содержание рендеринга к renderbuffer.

  11. Для доступа к содержанию объекта renderbuffer свяжите объект кадрового буфера и затем используйте функции OpenGL такой как glReadPixels или glCopyTexImage2D.

  12. Удалите объект кадрового буфера с его 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 каждый обеспечивает подпрограмму с этой целью:

Каждая из этих подпрограмм требует, чтобы Вы обеспечили цель текстуры, внутренний формат, максимальный уровень множественного отображения, и ширину и высоту текстуры.

Цель текстуры должна быть одной из этих констант текстуры OpenGL: GL_TEXTURE_2D для 2D текстуры, GL_TEXTURE_RECTANGLE_ARB для прямоугольного (не power-two) текстура, или GL_TEXTURE_CUBE_MAP поскольку куб отображает текстуру.

Внутренний формат указывает, как интерпретировать данные для текстурирования операций. Можно предоставить любую из этих опций: GL_RGB (каждый пиксель является трехкомпонентной группой), GL_RGBA (каждый пиксель является четырехкомпонентной группой), или GL_DEPTH_COMPONENT (каждый пиксель является единственным компонентом глубины).

Максимальный уровень множественного отображения должен быть 0 для пиксельного буфера, не имеющего множественного отображения. Значение, которое Вы предоставляете, не должно превышать фактическое максимальное количество уровней множественного отображения, которые могут быть представлены с данной шириной и высотой.

Обратите внимание на то, что ни одна из подпрограмм, создающих пиксельный буфер, не выделяет необходимое хранение. Хранение выделяется системой в то время, когда Вы присоединяете пиксельный буфер к контексту рендеринга.

Установка пиксельного буфера для внеэкранного получения

После создания пиксельного буфера общая процедура для использования пиксельного буфера для рисования подобна способу, которым Вы устанавливаете окна и представления для рисования:

  1. Укажите средство рендеринга и буферизуйте атрибуты.

  2. Получите объект формата пикселя.

  3. Создайте контекст рендеринга и сделайте его текущим.

  4. Присоедините пиксельный буфер к контексту с помощью соответствующего Apple присоединяемая функция OpenGL:

    • setPixelBuffer:cubeMapFace:mipMapLevel:currentVirtualScreen: метод NSOpenGLContext класс дает получателю команду представлять в пиксельном буфере.

    • Функция CGL CGLSetPBuffer присоединяет CGL рендеринг контекста к пиксельному буферу.

  5. Нарисуйте, как Вы обычно были бы, с помощью OpenGL.

Используя пиксельный буфер как источник текстуры

Пиксельные буферы позволяют Вам выполнить прямое текстурирование, не подвергаясь стоимости дополнительных копий. После рисования к пиксельному буферу можно создать текстуру путем выполнения этих шагов:

  1. Генерируйте имя текстуры путем вызывания функции OpenGL glGenTextures.

  2. Свяжите именованную текстуру с целью путем вызывания функции OpenGL glBindTexture.

  3. Установите параметры текстуры путем вызывания функции OpenGL glTexEnvParameter.

  4. Установите пиксельный буфер как источник для текстуры путем вызова одного из следующего 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.

  5. Нарисуйте примитивы с помощью надлежащих координат текстуры. (См. «Красную книгу» — Руководство по программированию OpenGL — для подробных данных.)

  6. Вызвать glFlush заставить все команды рисования выполняться.

  7. Когда Вы больше не нуждаетесь в объекте текстуры, вызываете функцию OpenGL glDeleteTextures.

  8. Установите текущий контекст в NULL использование одного из Apple подпрограммы OpenGL:

  9. Уничтожьте пиксельный буфер путем вызова CGLDestroyPBuffer.

  10. Уничтожьте контекст путем вызова CGLDestroyContext.

  11. Уничтожьте формат пикселя путем вызова CGLDestroyPixelFormat.

Вы могли бы счесть эти инструкции полезными при использовании пиксельных буферов для текстурирования:

  • Вы не можете выполнить вызовы текстурирования OpenGL, изменяющие пиксельное содержимое буфера (такой как glTexSubImage2D или glCopyTexImage2D) с пикселем буферизуют как место назначения. Можно использовать команды текстурирования для чтения данных из пиксельного буфера, такой как glCopyTexImage2D, с пикселем буферизуют текстуру как источник. Можно также использовать функции OpenGL такой как glReadPixels для чтения содержания пикселя буферизуют непосредственно от пиксельного буферного контекста.

  • Текстурирование может не привести к намеченным результатам, не сообщая об ошибке. Необходимо удостовериться, что Вы включаете надлежащую цель текстуры, устанавливаете совместимый режим фильтра и придерживаетесь других требований, описанных в спецификации OpenGL.

  • Когда Вы текстурируете от пиксельного буфера, Вы не обязаны устанавливать совместное использование контекста. Вы можете иметь различные объекты формата пикселя и контексты рендеринга и для пиксельного буфера и для целевого drawable объекта, не совместно используя ресурсы, и все еще текстурировать использование пиксельного буфера в целевом контексте.

Рендеринг к пиксельному буферу в удаленной системе

Выполните эти шаги для рендеринга к пиксельному буферу в удаленной системе. Удаленной системе не должны были присоединять дисплей к нему.

  1. Когда Вы устанавливаете средство рендеринга и буферизуете атрибуты, включаете удаленный пиксельный буферный атрибут kCGLPFARemotePBuffer.

  2. Войдите в систему удаленной машины с помощью ssh команда для обеспечения безопасности.

  3. Запустите приложение в целевой системе.

  4. Получите содержание.