Методы наиболее успешной практики для работы с данными текстуры

Текстуры добавляют реализм к объектам OpenGL. Они помогают объектам, определенным данными вершины, берут свойства материала реальных объектов, такие как древесина, кирпич, металл и мех. Данные текстуры могут произойти из многих источников, включая изображения.

Многие из тех же методов Ваше использование приложения на данных вершины могут также использоваться для улучшения производительности текстуры.

  Текстуры рисунка 11-1 добавляют реализм к сцене
Textures add realism to a scene

Текстуры запускаются как пиксельные данные, который течет через программу OpenGL, как показано на рисунке 11-2.

  Канал передачи данных Текстуры рисунка 11-2
Texture data path

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

Используя расширения для улучшения производительности текстуры

Без любой оптимизации текстурируйте потоки данных через программу OpenGL как показано в рисунке 11-3. Данные из Вашего приложения сначала переходят к платформе OpenGL, которая может сделать копию данных прежде, чем вручить его драйверу. Если Ваши данные не находятся в собственном формате для аппаратных средств (см. Оптимальные Форматы данных и Типы), драйвер может также сделать копию данных для преобразования его в специфичный для аппаратных средств формат для загрузки на видеопамять. Видеопамять, в свою очередь, может сохранить копию данных. Теоретически, могло быть четыре копии Ваших данных текстуры по всей системе.

  Данные рисунка 11-3 копируют в программе OpenGL
Data copies in an OpenGL program

Потоки данных на различных уровнях через систему, как показано размером стрелок на рисунке 11-3. Самая быстрая передача данных происходит между VRAM и GPU. Самая медленная передача происходит между драйвером OpenGL и VRAM. Данные перемещаются между приложением и платформой OpenGL, и между платформой и драйвером на том же «среднем» уровне. Устранение любой передачи данных, но самой медленной в частности улучшит производительность приложения.

Существует несколько расширений, которые можно использовать, чтобы устранить одну или более копий данных и управлять, как данные текстуры перемещаются от приложения до GPU:

Вот некоторые рекомендации:

Следующие разделы описывают расширения и показывают, как использовать их.

Пиксельные буферные объекты

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

Используя пиксель буфер возражает для эффективной загрузки текстур

  1. Вызовите функцию glGenBuffers создать новое имя для буферного объекта.

    void glGenBuffers(sizei n, uint *buffers );

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

    buffers указывает указатель на память для хранения буферных имен.

  2. Вызовите функцию glBindBuffer связывать неиспользованное имя к буферному объекту. После этого вызова недавно создаваемый буферный объект инициализируется с буфером памяти нулевого размера и состояния по умолчанию. (Для настройки по умолчанию посмотрите спецификацию OpenGL для ARB_vertex_buffer_object.)

    void glBindBuffer(GLenum target, GLuint buffer);

    target должен быть быть установленным в GL_PIXEL_UNPACK_BUFFER использовать буфер в качестве источника пиксельных данных.

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

  3. Создайте и инициализируйте хранилище данных буферного объекта путем вызывания функции glBufferData. По существу этот вызов загружает Ваши данные на GPU.

    void glBufferData(GLenum target, sizeiptr size,
                const GLvoid *data, GLenum usage);

    target должен быть установлен в GL_PIXEL_UNPACK_BUFFER.

    size указывает размер хранилища данных.

    *data точки к исходным данным. Если это не NULL, исходные данные копируются в хранилище данных буферного объекта. Если NULL, содержание хранилища данных не определено.

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

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

  5. Обновить данные в буферном объекте, Ваших вызовах приложения glMapBuffer. Отображение буфера препятствует тому, чтобы GPU воздействовал на данные и дает Вашему приложению подсказку к памяти, которую это может использовать для обновления буфера.

    void *glMapBuffer(GLenum target, GLenum access);

    target должен быть установлен в PIXEL_UNPACK_BUFFER.

    access указывает операции, которые Вы планируете выполнить на данных. Можно предоставить READ_ONLY, WRITE_ONLY, или READ_WRITE.

  6. Измените данные текстуры с помощью указателя, предоставленного буфером карты.

  7. Когда Вы закончите изменять текстуру, вызовите функцию glUnmapBuffer. Необходимо предоставитьPIXEL_UNPACK_BUFFER. Как только буфер не отображается, Ваше приложение больше не может получать доступ к данным буфера через указатель, и содержание буфера загружается снова на GPU.

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

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

  1. Вызовите функцию glGenBuffers создать новое имя для буферного объекта.

    void glGenBuffers(sizei n, uint *buffers );

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

    buffers указывает указатель на память для хранения буферных имен.

  2. Вызовите функцию glBindBuffer связывать неиспользованное имя к буферному объекту. После этого вызова недавно создаваемый буферный объект инициализируется с буфером памяти нулевого размера и состояния по умолчанию. (Для настройки по умолчанию посмотрите спецификацию OpenGL для ARB_vertex_buffer_object.)

    void glBindBuffer(GLenum target, GLuint buffer);

    target должен быть быть установленным в GL_PIXEL_PACK_BUFFER использовать буфер в качестве места назначения для пиксельных данных.

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

  3. Создайте и инициализируйте хранилище данных буферного объекта путем вызывания функции glBufferData.

    void glBufferData(GLenum target, sizeiptr size,
                const GLvoid *data, GLenum usage);

    target должен быть установлен в GL_PIXEL_PACK_BUFFER.

    size указывает размер хранилища данных.

    *data точки к исходным данным. Если это не NULL, исходные данные копируются в хранилище данных буферного объекта. Если NULL, содержание хранилища данных не определено.

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

  4. Вызвать glReadPixels или подобная функция. Функция вставляет команду для чтения пиксельных данных в связанный пиксельный буферный объект и затем возвращается.

  5. Для использования в своих интересах асинхронных пиксельных чтений приложение должно выполнить другую работу.

  6. Для получения данных в пикселе буферизуют объект, вызовы приложения glMapBuffer. Это блокирует OpenGL до ранее с очередями glReadPixels команда завершает, отображает данные и обеспечивает указатель на Ваше приложение.

    void *glMapBuffer(GLenum target, GLenum access);

    target должен быть установлен в GL_PIXEL_PACK_BUFFER.

    access указывает операции, которые Вы планируете выполнить на данных. Можно предоставить READ_ONLY, WRITE_ONLY, или READ_WRITE.

  7. Запишите данные вершины в указатель, предоставленный буфером карты.

  8. Когда Вы больше не нуждаетесь в данных вершины, вызываете функцию glUnmapBuffer. Необходимо предоставить GL_PIXEL_PACK_BUFFER. Как только буфер не отображается, данные больше не доступны для Вашего приложения.

Используя пиксель буфер возражает для хранения данных по GPU

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

  1. Установите свою первую передачу и представьте Ваши команды рисования.

  2. Свяжите пиксельный буферный объект и вызов glReadPixels выбирать промежуточное звено заканчивается в буфер.

  3. Свяжите тот же буфер как буфер вершины.

  4. Установите вторую передачу своего алгоритма и представьте Ваши команды рисования.

Хранение Ваших промежуточных данных в GPU при выполнении многократных передач может привести к увеличениям высокой эффективности.

Клиентское хранение Apple

Клиентское расширение хранения Apple (APPLE_client_storage) позволяет Вам предоставить OpenGL указатель на память, которую Ваше приложение выделяет и поддерживает. OpenGL сохраняет указатель на Ваши данные, но не копирует данные. Поскольку OpenGL ссылается на Ваши данные, Ваше приложение должно сохранить свою копию данных, пока не удалены все текстуры ссылки. При помощи этого расширения можно устранить копию платформы OpenGL как показано на рисунке 11-4. Обратите внимание на то, что ширина текстуры должна быть кратным числом 32 байтов для OpenGL для обхода работы копии от приложения до платформы OpenGL.

Рисунок 11-4  клиентское расширение хранения устраняет копию данных
The client storage extension eliminates a data copy

Клиентское расширение хранения 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.

Рисунок 11-5  расширение диапазона текстуры устраняет копию данных
The texture range extension eliminates a data copy

Для получения дальнейшей информации на этих расширениях, посмотрите, что спецификация OpenGL для Apple текстурирует расширение диапазона и спецификацию OpenGL для прямоугольного расширения текстуры ARB.

Объединение клиентского хранения с диапазонами текстуры

Можно использовать клиентское расширение хранения Apple вместе с расширением диапазона текстуры Apple для оптимизации канала передачи данных текстуры в приложении. Когда используется вместе, OpenGL перемещает данные текстуры непосредственно в видеопамять, как показано на рисунке 11-6. GPU непосредственно получает доступ к Вашим данным (через DMA). Набор немного отличается для текстур power-two и прямоугольного. Примеры кода в этом разделе загружают текстуры на GPU. Можно также использовать эти расширения, чтобы загрузить текстуры, видеть Данные Текстуры Загрузки.

  Расширения Объединения рисунка 11-6 для устранения копий данных
Combining extensions to eliminate two data copies

Перечисление 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_RGBA и GL_UNSIGNED_BYTE потребности быть swizzled многими картами, когда данные загружаются, таким образом, это не рекомендуется.

Работа с не питание двух текстур

OpenGL часто используется для обработки видео и изображений, обычно имеющих размерности, которые не являются power-two. До OpenGL 2.0, прямоугольное расширение текстуры (ARB_texture_rectangle) предоставленный единственная возможность для прямоугольной цели текстуры. Это расширение, однако, налагает следующие ограничения на прямоугольные текстуры:

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

Рисунок 11-7  Нормализованные и ненормализованные координаты
Normalized and non-normalized coordinates

Если Ваш код работает на системе, не поддерживающей ни одного ARB_texture_rectangle или ARB_texture_non_power_of_two расширения у Вас есть эти опции для работы с с прямоугольными изображениями:

Рисунок 11-8  изображение сегментировался на power-two мозаики
An image segmented into power-of-two tiles

Создание текстур от данных изображения

OpenGL на Macintosh предоставляет несколько возможностей для создания высококачественных текстур от данных изображения. OS X поддерживает пиксельные значения с плавающей точкой, форматы файлов повторного изображения и множество цветовых пространств. Можно импортировать изображение с плавающей точкой в текстуру с плавающей точкой. Рисунок 11-9 показывает, что изображение раньше текстурировало куб.

Рисунок 11-9  Используя изображение как текстура для куба
Using an image as a texture for a cube

Для Какао необходимо обеспечить растровое представление. Можно создать 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
    }
}

Вот то, что делает код:

  1. Выделяет NSBitmapImageRep объект.

  2. Инициализирует NSBitmapImageRep объект с растровыми данными от текущего представления.

  3. Получает число выборок на пиксель.

  4. Устанавливает надлежащую длину строки распаковки для битового массива.

  5. Устанавливает выровненную байтом распаковку, это необходимо для битовых массивов, которые составляют 3 байта на пиксель.

  6. Если объект текстуры не передается в, генерирует новый объект текстуры.

  7. Связывает имя текстуры к цели текстуры.

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

  9. Проверки, чтобы видеть, является ли битовый массив непланарным и является или 24-разрядным битовым массивом RGB или 32-разрядным битовым массивом RGBA. Если так, получает пиксельные данные с помощью bitmapData метод, передавая его вместе с другими надлежащими параметрами к OpenGL функционирует для указания 2D изображения текстуры.

Создание текстуры от кварцевого источника изображения

Кварцевые изображения (CGImageRef тип данных), определяются в Базовой Графической платформе (ApplicationServices/CoreGraphics.framework/CGImage.h) в то время как тип данных источника изображения для чтения данных изображения и создания Кварцевых изображений от источника изображения объявляется в Изображении платформой I/O (ApplicationServices/ImageIO.framework/CGImageSource.h). Кварц обеспечивает подпрограммы, читающие большое разнообразие данных изображения.

Для использования Кварцевого изображения в качестве источника текстуры выполните эти шаги:

  1. Создайте Кварцевый источник изображения путем предоставления a CFURL возразите против функции CGImageSourceCreateWithURL.

  2. Создайте Кварцевое изображение путем извлечения изображения из источника изображения, использования функции CGImageSourceCreateImageAtIndex.

  3. Извлеките размеры изображения с помощью функции CGImageGetWidth и CGImageGetHeight. Вам будут нужны они для вычисления хранения, требуемого для текстуры.

  4. Выделите хранение для текстуры.

  5. Создайте цветовое пространство для данных изображения.

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

  7. Нарисуйте изображение к растровому контексту.

  8. Выпустите растровый контекст.

  9. Установите пиксельный режим хранения путем вызывания функции glPixelStorei.

  10. Создайте и свяжите текстуру.

  11. Установите надлежащие параметры текстуры.

  12. Вызвать glTexImage2D, предоставление данных изображения.

  13. Освободите данные изображения.

Перечисление 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 текстурируйте диапазон и прямоугольные расширения текстуры:

Перечисление 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-10  Однобуферные данные
Single-buffered data

К данным двойного буфера необходимо предоставить два набора данных, чтобы продолжить работать. Отметьте на рисунке 11-11, что, в то время как GPU представляет один кадр данных, CPU обрабатывает следующее. После начального запуска никакой блок обработки не неактивен. Используя glFinishObject функция, предоставленная расширением предела, гарантирует, что синхронизируется буферное обновление.

Рисунок 11-11  данные С двойной буферизацией
Double-buffered data