Методы наиболее успешной практики для работы с данными текстуры
Текстуры добавляют реализм к объектам OpenGL. Они помогают объектам, определенным данными вершины, берут свойства материала реальных объектов, такие как древесина, кирпич, металл и мех. Данные текстуры могут произойти из многих источников, включая изображения.
Многие из тех же методов Ваше использование приложения на данных вершины могут также использоваться для улучшения производительности текстуры.
Текстуры запускаются как пиксельные данные, который течет через программу OpenGL, как показано на рисунке 11-2.
Точный маршрут, которые текстурируют данные, берет от Вашего приложения до его конечного места назначения, может повлиять на производительность Вашего приложения. Цель этой главы состоит в том, чтобы обеспечить методы, которые можно использовать для обеспечения оптимальной обработки данных текстуры в приложении. Эта глава
показывает, как использовать расширения OpenGL для оптимизации производительности
перечисляет оптимальные форматы данных и типы
предоставляет информацию о работе с текстурами, размерности которых не являются питанием два
описывает текстуры создания от данных изображения
показывает, как загрузить текстуры
обсуждает двойные буферы использования для данных текстуры
Используя расширения для улучшения производительности текстуры
Без любой оптимизации текстурируйте потоки данных через программу OpenGL как показано в рисунке 11-3. Данные из Вашего приложения сначала переходят к платформе OpenGL, которая может сделать копию данных прежде, чем вручить его драйверу. Если Ваши данные не находятся в собственном формате для аппаратных средств (см. Оптимальные Форматы данных и Типы), драйвер может также сделать копию данных для преобразования его в специфичный для аппаратных средств формат для загрузки на видеопамять. Видеопамять, в свою очередь, может сохранить копию данных. Теоретически, могло быть четыре копии Ваших данных текстуры по всей системе.
Потоки данных на различных уровнях через систему, как показано размером стрелок на рисунке 11-3. Самая быстрая передача данных происходит между VRAM и GPU. Самая медленная передача происходит между драйвером OpenGL и VRAM. Данные перемещаются между приложением и платформой OpenGL, и между платформой и драйвером на том же «среднем» уровне. Устранение любой передачи данных, но самой медленной в частности улучшит производительность приложения.
Существует несколько расширений, которые можно использовать, чтобы устранить одну или более копий данных и управлять, как данные текстуры перемещаются от приложения до GPU:
GL_ARB_pixel_buffer_object
позволяет Вашему приложению использовать буферные объекты OpenGL управлять текстурой и данными изображения. Как с вершиной буферизуют объекты, они позволяют Вашему приложению подсказывать, как буфер используется и решить, когда данные копируются в OpenGL.GL_APPLE_client_storage
позволяет Вам препятствовать тому, чтобы OpenGL копировал Ваши данные текстуры в клиент. Вместо этого OpenGL сохраняет указатель памяти, который Вы обеспечили при создании текстуры. Ваше приложение должно сохранить данные текстуры в том расположении до ссылки, текстура OpenGL удалена.GL_APPLE_texture_range
, вместе с подсказкой хранения, такжеGL_STORAGE_CACHED_APPLE
илиGL_STORAGE_SHARED_APPLE
, позволяет Вам указывать единственный блок памяти текстуры и управлять им, как Вы считаете целесообразным.GL_ARB_texture_rectangle
предоставляет поддержку для непитания - две текстуры.
Вот некоторые рекомендации:
Если Ваше приложение требует оптимальной производительности загрузки текстуры, использовать
GL_APPLE_client_storage
иGL_APPLE_texture_range
вместе управлять Вашими текстурами.Если Ваше приложение требует оптимальной производительности загрузки текстуры, используйте пиксельные буферные объекты.
Если Ваше приложение требует межплатформенных методов, используйте пиксельные буферные объекты и для загрузок текстуры и текстурируйте загрузки.
Использовать
GL_ARB_texture_rectangle
когда Ваши исходные изображения не выровненные к power-2 размеру.
Следующие разделы описывают расширения и показывают, как использовать их.
Пиксельные буферные объекты
Пиксельные буферные объекты являются базовой функцией OpenGL 2.1 и также доступный через GL_ARB_pixel_buffer_object
расширение. Процедура для установки пиксельного буферного объекта почти идентична тому из буферных объектов вершины.
Используя пиксель буфер возражает для эффективной загрузки текстур
Вызовите функцию
glGenBuffers
создать новое имя для буферного объекта.void glGenBuffers(sizei n, uint *buffers );
n
число буферов, для которых Вы хотите создать идентификаторы.buffers
указывает указатель на память для хранения буферных имен.Вызовите функцию
glBindBuffer
связывать неиспользованное имя к буферному объекту. После этого вызова недавно создаваемый буферный объект инициализируется с буфером памяти нулевого размера и состояния по умолчанию. (Для настройки по умолчанию посмотрите спецификацию OpenGL для ARB_vertex_buffer_object.)void glBindBuffer(GLenum target, GLuint buffer);
target
должен быть быть установленным вGL_PIXEL_UNPACK_BUFFER
использовать буфер в качестве источника пиксельных данных.buffer
указывает уникальное имя для буферного объекта.Создайте и инициализируйте хранилище данных буферного объекта путем вызывания функции
glBufferData
. По существу этот вызов загружает Ваши данные на GPU.void glBufferData(GLenum target, sizeiptr size,
const GLvoid *data, GLenum usage);
target
должен быть установлен вGL_PIXEL_UNPACK_BUFFER
.size
указывает размер хранилища данных.*data
точки к исходным данным. Если это неNULL
, исходные данные копируются в хранилище данных буферного объекта. ЕслиNULL
, содержание хранилища данных не определено.usage
константа, обеспечивающая подсказку относительно того, как Ваше приложение планирует использовать хранилище данных. Для получения дополнительной информации на буферных подсказках, посмотрите Буферные Подсказки ИспользованияКаждый раз, когда Вы вызываете
glDrawPixels
,glTexSubImage
или подобные функции, читающие пиксельные данные из приложения, те функции, используют данные в связанном пиксельном буферном объекте вместо этого.Обновить данные в буферном объекте, Ваших вызовах приложения
glMapBuffer
. Отображение буфера препятствует тому, чтобы GPU воздействовал на данные и дает Вашему приложению подсказку к памяти, которую это может использовать для обновления буфера.void *glMapBuffer(GLenum target, GLenum access);
target
должен быть установлен вPIXEL_UNPACK_BUFFER
.access
указывает операции, которые Вы планируете выполнить на данных. Можно предоставитьREAD_ONLY
,WRITE_ONLY
, илиREAD_WRITE
.Измените данные текстуры с помощью указателя, предоставленного буфером карты.
Когда Вы закончите изменять текстуру, вызовите функцию
glUnmapBuffer
. Необходимо предоставитьPIXEL_UNPACK_BUFFER
. Как только буфер не отображается, Ваше приложение больше не может получать доступ к данным буфера через указатель, и содержание буфера загружается снова на GPU.
Используя пиксельные буферные объекты для асинхронных пиксельных передач
glReadPixels
обычно блоки до предыдущих команд завершились, который включает медленный процесс копирования пиксельных данных к приложению. Однако, если Вы вызываете glReadPixels
в то время как пиксельный буферный объект связывается, функция сразу возвращается. Это не блокирует, пока Вы фактически не отображаете пиксельный буферный объект считать его содержание.
Вызовите функцию
glGenBuffers
создать новое имя для буферного объекта.void glGenBuffers(sizei n, uint *buffers );
n
число буферов, для которых Вы хотите создать идентификаторы.buffers
указывает указатель на память для хранения буферных имен.Вызовите функцию
glBindBuffer
связывать неиспользованное имя к буферному объекту. После этого вызова недавно создаваемый буферный объект инициализируется с буфером памяти нулевого размера и состояния по умолчанию. (Для настройки по умолчанию посмотрите спецификацию OpenGL для ARB_vertex_buffer_object.)void glBindBuffer(GLenum target, GLuint buffer);
target
должен быть быть установленным вGL_PIXEL_PACK_BUFFER
использовать буфер в качестве места назначения для пиксельных данных.buffer
указывает уникальное имя для буферного объекта.Создайте и инициализируйте хранилище данных буферного объекта путем вызывания функции
glBufferData
.void glBufferData(GLenum target, sizeiptr size,
const GLvoid *data, GLenum usage);
target
должен быть установлен вGL_PIXEL_PACK_BUFFER
.size
указывает размер хранилища данных.*data
точки к исходным данным. Если это неNULL
, исходные данные копируются в хранилище данных буферного объекта. ЕслиNULL
, содержание хранилища данных не определено.usage
константа, обеспечивающая подсказку относительно того, как Ваше приложение планирует использовать хранилище данных. Для получения дополнительной информации на буферных подсказках, посмотрите Буферные Подсказки ИспользованияВызвать
glReadPixels
или подобная функция. Функция вставляет команду для чтения пиксельных данных в связанный пиксельный буферный объект и затем возвращается.Для использования в своих интересах асинхронных пиксельных чтений приложение должно выполнить другую работу.
Для получения данных в пикселе буферизуют объект, вызовы приложения
glMapBuffer
. Это блокирует OpenGL до ранее с очередямиglReadPixels
команда завершает, отображает данные и обеспечивает указатель на Ваше приложение.void *glMapBuffer(GLenum target, GLenum access);
target
должен быть установлен вGL_PIXEL_PACK_BUFFER
.access
указывает операции, которые Вы планируете выполнить на данных. Можно предоставитьREAD_ONLY
,WRITE_ONLY
, илиREAD_WRITE
.Запишите данные вершины в указатель, предоставленный буфером карты.
Когда Вы больше не нуждаетесь в данных вершины, вызываете функцию
glUnmapBuffer
. Необходимо предоставитьGL_PIXEL_PACK_BUFFER
. Как только буфер не отображается, данные больше не доступны для Вашего приложения.
Используя пиксель буфер возражает для хранения данных по GPU
Нет никакого различия между буферным объектом вершины и пиксельным буферным объектом за исключением цели, с которой они связываются. Приложение может взять результаты в одном буфере и использовать их в качестве другого буферного типа. Например, Вы могли использовать пиксельные результаты программы построения теней фрагмента и дать иное толкование им как данным вершины в будущей передаче, никогда не оставляя GPU:
Установите свою первую передачу и представьте Ваши команды рисования.
Свяжите пиксельный буферный объект и вызов
glReadPixels
выбирать промежуточное звено заканчивается в буфер.Свяжите тот же буфер как буфер вершины.
Установите вторую передачу своего алгоритма и представьте Ваши команды рисования.
Хранение Ваших промежуточных данных в GPU при выполнении многократных передач может привести к увеличениям высокой эффективности.
Клиентское хранение Apple
Клиентское расширение хранения Apple (APPLE_client_storage
) позволяет Вам предоставить OpenGL указатель на память, которую Ваше приложение выделяет и поддерживает. OpenGL сохраняет указатель на Ваши данные, но не копирует данные. Поскольку OpenGL ссылается на Ваши данные, Ваше приложение должно сохранить свою копию данных, пока не удалены все текстуры ссылки. При помощи этого расширения можно устранить копию платформы OpenGL как показано на рисунке 11-4. Обратите внимание на то, что ширина текстуры должна быть кратным числом 32 байтов для OpenGL для обхода работы копии от приложения до платформы OpenGL.
Клиентское расширение хранения Apple определяет пиксельный параметр хранения, GL_UNPACK_CLIENT_STORAGE_APPLE
, то, что Вы передаете функции OpenGL glPixelStorei
указать, что Ваше приложение сохраняет хранение для текстур. Следующие кодовые наборы клиентское хранение:
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); |
Для получения дальнейшей информации посмотрите спецификацию OpenGL для клиентского расширения хранения Apple.
Диапазон текстуры Apple и прямоугольная текстура
Расширение диапазона текстуры Apple (APPLE_texture_range
) позволяет Вам определить область памяти, используемой для данных текстуры. Обычно Вы указываете диапазон адресов, охватывающий хранение для ряда текстур. Это позволяет драйверу OpenGL оптимизировать использование памяти путем создания единственной памяти, отображающейся для всех текстур. Можно также обеспечить подсказку относительно того, как должны храниться данные: кэшируемый или совместно использованный. Кэшируемая подсказка указывает для кэширования данных текстуры в видеопамяти. Эта подсказка рекомендуется, когда у Вас есть текстуры, которые Вы планируете использовать многократно или то использование линейная фильтрация. Совместно используемая подсказка указывает, что данные должны быть отображены в область памяти, позволяющей GPU получить доступ к данным текстуры непосредственно (через DMA) без потребности скопировать его. Когда Вы используете большие изображения только один раз, выполняете фильтрацию ближайшего соседа или должны уменьшить масштаб размера изображения, эта подсказка является лучшей.
Расширение диапазона текстуры определяет следующую подпрограмму для того, чтобы сделать единственную память, отображающуюся для всех текстур используемой Вашим приложением:
void glTextureRangeAPPLE(GLenum target, GLsizei length, GLvoid *pointer); |
target
допустимая цель текстуры, такой как GL_TEXTURE_2D
.
length
указывает число байтов в адресном пространстве, именуемом pointer
параметр.
*pointer
точки к адресному пространству, что Ваше приложение предусматривает хранение текстуры.
Вы обеспечиваете параметр подсказки и значение параметра к к функции OpenGL glTexParameteri
. Возможные значения для параметра подсказки хранения (GL_TEXTURE_STORAGE_HINT_APPLE
) GL_STORAGE_CACHED_APPLE
или GL_STORAGE_SHARED_APPLE
.
Некоторые аппаратные средства требуют, чтобы размерности текстуры были power-two, прежде чем аппаратные средства смогут загрузить данные с помощью DMA. Прямоугольное расширение текстуры (ARB_texture_rectangle
) был представлен для разрешения целей текстуры для текстур любых размерностей — т.е. прямоугольные текстуры (GL_TEXTURE_RECTANGLE_ARB
). Необходимо использовать прямоугольное расширение текстуры вместе с расширением диапазона текстуры Apple, чтобы гарантировать, что OpenGL использует DMA для доступа к данным текстуры. Эти расширения позволяют Вам обходить драйвер OpenGL, как показано на рисунке 11-5.
Обратите внимание на то, что OpenGL не использует DMA для цели текстуры power-two (GL_TEXTURE_2D
). Так, в отличие от прямоугольной текстуры, текстура power-two подвергнется одной дополнительной копии, и производительность не будет вполне как быстро. Производительность обычно не является проблемой, потому что игры, которые являются приложениями наиболее вероятно, чтобы использовать текстуры power-two, текстуры загрузки в начале игры или уровня и не загрузить текстуры в режиме реального времени так же часто как приложения, использующие прямоугольные текстуры, обычно играющие видеоизображения или изображения на дисплее.
Следующий раздел имеет примеры кода, использующие диапазон текстуры и прямоугольные текстуры вместе с клиентским расширением хранения Apple.
Для получения дальнейшей информации на этих расширениях, посмотрите, что спецификация OpenGL для Apple текстурирует расширение диапазона и спецификацию OpenGL для прямоугольного расширения текстуры ARB.
Объединение клиентского хранения с диапазонами текстуры
Можно использовать клиентское расширение хранения Apple вместе с расширением диапазона текстуры Apple для оптимизации канала передачи данных текстуры в приложении. Когда используется вместе, OpenGL перемещает данные текстуры непосредственно в видеопамять, как показано на рисунке 11-6. GPU непосредственно получает доступ к Вашим данным (через DMA). Набор немного отличается для текстур power-two и прямоугольного. Примеры кода в этом разделе загружают текстуры на GPU. Можно также использовать эти расширения, чтобы загрузить текстуры, видеть Данные Текстуры Загрузки.
Перечисление 11-1 показывает, как использовать расширения для прямоугольной текстуры. После включения прямоугольного расширения текстуры необходимо связать прямоугольную текстуру с целью. Затем, установите подсказку хранения. Вызвать glPixelStorei
устанавливать клиентское расширение хранения Apple. Наконец, вызовите функцию glTexImage2D
с с прямоугольной целью текстуры и указателем на Ваши данные текстуры.
Перечисление 11-1 Используя расширения текстуры для прямоугольной текстуры
glEnable (GL_TEXTURE_RECTANGLE_ARB); |
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, id); |
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, |
GL_TEXTURE_STORAGE_HINT_APPLE, |
GL_STORAGE_CACHED_APPLE); |
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); |
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, |
0, GL_RGBA, sizex, sizey, 0, GL_BGRA, |
GL_UNSIGNED_INT_8_8_8_8_REV, |
myImagePtr); |
Установка текстуры power-two для использования этих расширений подобна тому, что необходимо для установки прямоугольной текстуры, как Вы видите путем рассмотрения Перечисления 11-2. Различие то, что GL_TEXTURE_2D
текстурируйте целевые замены GL_TEXTURE_RECTANGLE_ARB
цель текстуры.
Перечисление 11-2 Используя расширения текстуры для текстуры power-two
glBindTexture(GL_TEXTURE_2D, myTextureName); |
glTexParameteri(GL_TEXTURE_2D, |
GL_TEXTURE_STORAGE_HINT_APPLE, |
GL_STORAGE_CACHED_APPLE); |
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
sizex, sizey, 0, GL_BGRA, |
GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr); |
Оптимальные форматы данных и типы
Лучший тип формата и комбинации типа данных для использования для данных текстуры:
GL_BGRA
,GL_UNSIGNED_INT_8_8_8_8_REV
GL_BGRA
,GL_UNSIGNED_SHORT_1_5_5_5_REV
)GL_YCBCR_422_APPLE
,GL_UNSIGNED_SHORT_8_8_REV_APPLE
Комбинация GL_RGBA
и GL_UNSIGNED_BYTE
потребности быть swizzled многими картами, когда данные загружаются, таким образом, это не рекомендуется.
Работа с не питание двух текстур
OpenGL часто используется для обработки видео и изображений, обычно имеющих размерности, которые не являются power-two. До OpenGL 2.0, прямоугольное расширение текстуры (ARB_texture_rectangle
) предоставленный единственная возможность для прямоугольной цели текстуры. Это расширение, однако, налагает следующие ограничения на прямоугольные текстуры:
Вы не можете использовать, множественно отображают фильтрацию с ними.
Можно использовать только эти режимы обертки:
GL_CLAMP
,GL_CLAMP_TO_EDGE
, иGL_CLAMP_TO_BORDER
.Текстура не может иметь границы.
Текстура использует ненормализованные координаты текстуры. (См. рисунок 11-7.)
OpenGL 2.0 добавляет другую опцию для прямоугольной цели текстуры через ARB_texture_non_power_of_two
расширение, поддерживающее эти текстуры без ограничений ARB_texture_rectangle
расширение. Перед использованием его необходимо проверить, чтобы удостовериться, что функциональность доступна. Вы также захотите консультироваться со спецификацией OpenGL для не — power-two расширение.
Если Ваш код работает на системе, не поддерживающей ни одного ARB_texture_rectangle
или ARB_texture_non_power_of_two
расширения у Вас есть эти опции для работы с с прямоугольными изображениями:
Используйте функцию OpenGL
gluScaleImage
масштабировать изображение так, чтобы это поместилось в прямоугольник, размерности которого являются питанием два. Изображение отменяет масштабирующийся эффект при рисовании изображения из должным образом размерного прямоугольника назад в многоугольник, имеющий корректное форматное соотношение для изображения.Сегментируйте изображение на power-two прямоугольники, как показано на рисунке 11-8 при помощи одного изображения буферные и различные указатели текстуры. Заметьте, как стороны и углы изображения, показанного на рисунке 11-8, сегментируются на все более и более меньшие прямоугольники, чтобы гарантировать, что каждый прямоугольник имеет размерности, которые являются питанием два. Если текстура масштабируется или поворачивается, специальный уход может быть необходим на границах между каждым сегментом, чтобы избежать фильтровать артефакты.
Создание текстур от данных изображения
OpenGL на Macintosh предоставляет несколько возможностей для создания высококачественных текстур от данных изображения. OS X поддерживает пиксельные значения с плавающей точкой, форматы файлов повторного изображения и множество цветовых пространств. Можно импортировать изображение с плавающей точкой в текстуру с плавающей точкой. Рисунок 11-9 показывает, что изображение раньше текстурировало куб.
Для Какао необходимо обеспечить растровое представление. Можно создать NSBitmapImageRep
объект от содержания NSView
объект. Можно использовать Изображение платформа I/O (см. Ссылку CGImageSource). Эта платформа имеет поддержку многих различных форматов файлов, данных с плавающей точкой и множества цветовых пространств. Кроме того, это просто в использовании. Можно импортировать данные изображения как текстуру просто путем предоставления a CFURL
объект, указывающий расположение текстуры. Нет никакой потребности в Вас преобразовать изображение в промежуточный целочисленный формат RGB.
Создание текстуры от представления какао
Можно использовать NSView
класс или подкласс его для текстурирования в OpenGL. Процесс должен сначала сохранить данные изображения от NSView
объект в NSBitmapImageRep
возразите так, чтобы данные изображения были в формате, который может с готовностью использоваться в качестве данных текстуры OpenGL. Затем после установки цели текстуры Вы снабжаете растровыми данными к функции OpenGL glTexImage2D
. Обратите внимание на то, что у Вас должен быть допустимый, текущий установленный контекст OpenGL.
Перечисление 11-3 показывает подпрограмму, использующую этот процесс для создания текстуры из содержания NSView
объект. Подробное объяснение каждой пронумерованной строки кода появляется после перечисления.
Перечисление 11-3 , Создающее OpenGL, текстурирует от NSView
объект
-(void)myTextureFromView:(NSView*)theView |
textureName:(GLuint*)texName |
{ |
NSBitmapImageRep * bitmap = [theView bitmapImageRepForCachingDisplayInRect: |
[theView visibleRect]]; // 1 |
int samplesPerPixel = 0; |
[theView cacheDisplayInRect:[theView visibleRect] toBitmapImageRep:bitmap]; // 2 |
samplesPerPixel = [bitmap samplesPerPixel]; // 3 |
glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap bytesPerRow]/samplesPerPixel); // 4 |
glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // 5 |
if (*texName == 0) // 6 |
glGenTextures (1, texName); |
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *texName); // 7 |
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, |
GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 8 |
if(![bitmap isPlanar] && |
(samplesPerPixel == 3 || samplesPerPixel == 4)) { // 9 |
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, |
0, |
samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8, |
[bitmap pixelsWide], |
[bitmap pixelsHigh], |
0, |
samplesPerPixel == 4 ? GL_RGBA : GL_RGB, |
GL_UNSIGNED_BYTE, |
[bitmap bitmapData]); |
} else { |
// Your code to report unsupported bitmap data |
} |
} |
Вот то, что делает код:
Выделяет
NSBitmapImageRep
объект.Инициализирует
NSBitmapImageRep
объект с растровыми данными от текущего представления.Получает число выборок на пиксель.
Устанавливает надлежащую длину строки распаковки для битового массива.
Устанавливает выровненную байтом распаковку, это необходимо для битовых массивов, которые составляют 3 байта на пиксель.
Если объект текстуры не передается в, генерирует новый объект текстуры.
Связывает имя текстуры к цели текстуры.
Фильтрация наборов так, чтобы это не использовало множественное отображение, которое было бы избыточно для прямоугольного расширения текстуры.
Проверки, чтобы видеть, является ли битовый массив непланарным и является или 24-разрядным битовым массивом RGB или 32-разрядным битовым массивом RGBA. Если так, получает пиксельные данные с помощью
bitmapData
метод, передавая его вместе с другими надлежащими параметрами к OpenGL функционирует для указания 2D изображения текстуры.
Создание текстуры от кварцевого источника изображения
Кварцевые изображения (CGImageRef
тип данных), определяются в Базовой Графической платформе (ApplicationServices/CoreGraphics.framework/CGImage.h
) в то время как тип данных источника изображения для чтения данных изображения и создания Кварцевых изображений от источника изображения объявляется в Изображении платформой I/O (ApplicationServices/ImageIO.framework/CGImageSource.h
). Кварц обеспечивает подпрограммы, читающие большое разнообразие данных изображения.
Для использования Кварцевого изображения в качестве источника текстуры выполните эти шаги:
Создайте Кварцевый источник изображения путем предоставления a
CFURL
возразите против функцииCGImageSourceCreateWithURL
.Создайте Кварцевое изображение путем извлечения изображения из источника изображения, использования функции
CGImageSourceCreateImageAtIndex
.Извлеките размеры изображения с помощью функции
CGImageGetWidth
иCGImageGetHeight
. Вам будут нужны они для вычисления хранения, требуемого для текстуры.Выделите хранение для текстуры.
Создайте цветовое пространство для данных изображения.
Создайте Кварцевый контекст растрового изображения для рисования. Удостоверьтесь, что установили контекст для предварительно умноженной альфы.
Нарисуйте изображение к растровому контексту.
Выпустите растровый контекст.
Установите пиксельный режим хранения путем вызывания функции
glPixelStorei
.Создайте и свяжите текстуру.
Установите надлежащие параметры текстуры.
Вызвать
glTexImage2D
, предоставление данных изображения.Освободите данные изображения.
Перечисление 11-4 показывает фрагмент кода, выполняющий эти шаги. Обратите внимание на то, что у Вас должен быть допустимый, текущий контекст OpenGL.
Перечисление 11-4 Используя Кварц отображает как источник текстуры
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(url, NULL); |
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL); |
GLint myTextureName; |
size_t width = CGImageGetWidth(myImageRef); |
size_t height = CGImageGetHeight(myImageRef); |
CGRect rect = {{0, 0}, {width, height}}; |
void * myData = calloc(width * 4, height); |
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); |
CGContextRef myBitmapContext = CGBitmapContextCreate (myData, |
width, height, 8, |
width*4, space, |
kCGBitmapByteOrder32Host | |
kCGImageAlphaPremultipliedFirst); |
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy); |
CGContextDrawImage(myBitmapContext, rect, myImageRef); |
CGContextRelease(myBitmapContext); |
glPixelStorei(GL_UNPACK_ROW_LENGTH, width); |
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
glGenTextures(1, &myTextureName); |
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName); |
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, |
GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height, |
0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, myData); |
free(myData); |
Для получения дополнительной информации об использовании Кварца посмотрите Кварц 2D Руководство по программированию, Ссылка CGImage и Ссылка CGImageSource.
Получение распакованных данных необработанного пикселя из исходного изображения
Можно использовать Изображение платформа I/O вместе с Кварцевым провайдером данных для получения распакованных данных необработанного пикселя из исходного изображения, как показано в Перечислении 11-5. Можно тогда использовать пиксельные данные для текстуры OpenGL. Данные имеют тот же формат как исходное изображение, таким образом, необходимо удостовериться, что Вы используете исходное изображение, имеющее расположение, в котором Вы нуждаетесь.
Альфа не предварительно умножается для пиксельных данных, полученных в Перечислении 11-5, но альфа предварительно умножается для пиксельных данных, которые Вы получаете при использовании кода, описанного в Создании Текстуры от Представления Какао и Создания Текстуры от Кварцевого Источника изображения.
Перечисление 11-5 , Получающее пиксельные данные из исходного изображения
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(url, NULL); |
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL); |
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(myImageRef)); |
void *pixelData = CFDataGetBytePtr(data); |
Загрузка данных текстуры
Работа загрузки текстуры использует тот же канал передачи данных в качестве работы загрузки за исключением того, что инвертируется канал передачи данных. Загрузка передач текстурируют данные, использование прямого доступа к памяти (DMA), от VRAM в текстуру, к которой может тогда получить доступ непосредственно Ваше приложение. Можно использовать клиентский диапазон Apple, диапазон текстуры, и текстурировать прямоугольные расширения для загрузки, как Вы были бы для загрузки.
Для загрузки данных текстуры с помощью клиентского хранения Apple текстурируйте диапазон и прямоугольные расширения текстуры:
Свяжите имя текстуры к цели текстуры.
Установите расширения
Вызовите функцию
glCopyTexSubImage2D
скопировать подызображение текстуры с указанных координат окна. Этот вызов инициирует асинхронную передачу DMA в системную память в следующий раз, когда Вы вызываете подпрограмму сброса. CPU не ожидает этого вызова для завершения.Вызовите функцию
glGetTexImage
передать текстуру в системную память. Обратите внимание на то, что параметры должны соответствовать тем, что Вы раньше устанавливали текстуру, когда Вы вызвали функциюglTexImage2D
. Этот вызов является точкой синхронизации; это ожидает, пока передача не закончена.
Перечисление 11-6 показывает фрагмент кода, загружающий прямоугольную текстуру, использующую кэшируемую память. Ваши данные порядка подачи заявки между glCopyTexSubImage2D
и glGetTexImage
вызовы. Сколько обработки? Достаточно так, чтобы Ваше приложение не должно ожидать GPU.
Код перечисления 11-6, загружающий данные текстуры
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName); |
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, |
GL_STORAGE_SHARED_APPLE); |
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); |
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, |
sizex, sizey, 0, GL_BGRA, |
GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr); |
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, |
0, 0, 0, 0, 0, image_width, image_height); |
glFlush(); |
// Do other work processing here, using a double or triple buffer |
glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, |
GL_UNSIGNED_INT_8_8_8_8_REV, pixels); |
Данные текстуры двойной буферизации
Когда Вы используете любой метод, позволяющий GPU получать доступ к Вашим данным текстуры непосредственно, таким как расширение диапазона текстуры, для GPU и CPU возможно получить доступ к данным одновременно. Для предотвращения такой коллизии необходимо синхронизировать GPU и CPU. Самый простой путь показан на рисунке 11-10. Ваши работы приложения над данными, сбросы, это к GPU и ожидает до GPU, закончены прежде, чем работать над данными снова.
Один метод для обеспечения, что GPU закончен, выполнив команды перед Вашим приложением, отправляет, больше данных должно вставить маркер в поток команды и использование, что для определения, когда CPU может коснуться данных снова, как описано в Пределах Использования для Синхронизации с более прекрасными зернами. Рисунок 11-10 использует команду расширения предела glFinishObject
синхронизировать буферные обновления для потока однобуферных данных текстуры. Заметьте, что, когда CPU обрабатывает данные текстуры, GPU неактивен. Точно так же, когда GPU обрабатывает данные текстуры, CPU неактивен. Намного более эффективно для GPU и CPU работать асинхронно, чем работать синхронно. Данные двойной буферизации являются методом, позволяющим Вам обрабатывать данные асинхронно, как показано на рисунке 11-11.
К данным двойного буфера необходимо предоставить два набора данных, чтобы продолжить работать. Отметьте на рисунке 11-11, что, в то время как GPU представляет один кадр данных, CPU обрабатывает следующее. После начального запуска никакой блок обработки не неактивен. Используя glFinishObject
функция, предоставленная расширением предела, гарантирует, что синхронизируется буферное обновление.