Рисование с OpenGL ES и GLKit

Платформа GLKit обеспечивает классы контроллера представления и представления, устраняющие код установки и обслуживания, который иначе требовался бы для рисования и анимации OpenGL содержание ES. GLKView класс управляет OpenGL инфраструктура ES для обеспечения места для кода для прорисовки, и GLKViewController класс обеспечивает цикл рендеринга для плавной анимации OpenGL содержание ES в представлении GLKit. Эти классы расширяют стандартные шаблоны разработки UIKit для рисования содержания представления и управления представлением представления. В результате можно фокусировать усилия прежде всего на OpenGL код рендеринга ES и разбудить приложение и работающий быстро. Платформа GLKit также обеспечивает другие функции для упрощения OpenGL ES 2.0 и 3,0 разработок.

Представление GLKit рисует OpenGL содержание ES по требованию

GLKView класс обеспечивает OpenGL основанный на ES эквивалент стандарта UIView рисование цикла. A UIView экземпляр автоматически конфигурирует свой графический контекст так, чтобы Ваш drawRect: потребность реализации только выполняет Кварц 2D команды рисования и a GLKView экземпляр автоматически конфигурирует себя так, чтобы Ваш метод рисования должен был только выполнить OpenGL команды рисования ES. GLKView класс обеспечивает эту функциональность путем поддержания объекта кадрового буфера, содержащего результаты OpenGL команды рисования ES, и затем автоматически представляющего их Базовой Анимации, как только возвращается метод рисования.

Как стандартное представление UIKit, представление GLKit представляет свое содержание по требованию. Когда Ваше представление сначала выведено на экран, оно вызывает Ваш метод рисования — Базовая Анимация кэширует представленный вывод и выводит на экран его каждый раз, когда показано Ваше представление. Когда Вы захотите изменить содержание своего представления, вызовите setNeedsDisplay метод и представление снова вызывают Ваш метод рисования, кэшируют получающееся изображение и представляют его на экране. Когда данные раньше представляли изменения образа нечасто или только в ответ на пользовательское действие, этот подход полезен. Путем рендеринга нового содержания представления только, когда Вы должны, Вы сохраняете заряд батареи на устройстве и оставляете больше времени для устройства для выполнения других действий.

Рисунок 3-1  , Представляющий OpenGL содержание ES с представлением GLKit
Three-stage rendering process: GLKView prepares OpenGL ES infrastructure; your code draws into the framebuffer, and GLKView presents the rendered image for display

Создание и конфигурирование представления GLKit

Можно создать и сконфигурировать a GLKView возразите или программно или использующий Интерфейсного Разработчика. Прежде чем можно будет использовать его для рисования, необходимо связать его с EAGLContext объект (см. Конфигурирование OpenGL Контексты ES).

  • При создании представления программно, сначала создайте контекст и затем передайте его представлению initWithFrame:context: метод.

  • После загрузки представления от раскадровки создайте контекст и установите ее как значение представления context свойство.

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

Перечисление 3-1  , Конфигурирующее представление GLKit

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    // Create an OpenGL ES context and assign it to the view loaded from storyboard
    GLKView *view = (GLKView *)self.view;
    view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
 
    // Configure renderbuffers created by the view
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    view.drawableStencilFormat = GLKViewDrawableStencilFormat8;
 
    // Enable multisampling
    view.drawableMultisample = GLKViewDrawableMultisample4X;
}

Можно позволить мультивыбрать для a GLKView экземпляр с помощью drawableMultisample свойство. Мультивыборка является формой сглаживания, сглаживающего зубчатые края, улучшая качество изображения в большинстве 3D приложений за счет использования большего количества памяти и время обработки фрагмента — если Вы позволяете мультивыбрать, всегда тестируете производительность своего приложения, чтобы гарантировать, что это остается приемлемым.

Рисование с представлением GLKit

Рисунок 3-1 обрисовывает в общих чертах три шага для рисования OpenGL содержание ES: подготовка OpenGL инфраструктура ES, выпуск команд рисования и представление представленного содержания к Базовой Анимации для дисплея. GLKView класс реализует первые и третьи шаги. Для второго шага Вы реализуете метод рисования как пример в Перечислении 3-2.

  Метод рисования перечисления 3-2 В качестве примера для представления GLKit

- (void)drawRect:(CGRect)rect
{
    // Clear the framebuffer
    glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    // Draw using previously configured texture, shader, uniforms, and vertex array
    glBindTexture(GL_TEXTURE_2D, _planetTexture);
    glUseProgram(_diffuseShading);
    glUniformMatrix4fv(_uniformModelViewProjectionMatrix, 1, 0, _modelViewProjectionMatrix.m);
    glBindVertexArrayOES(_planetMesh);
    glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT);
}

GLKView класс в состоянии обеспечить простой интерфейс для OpenGL получение ES, потому что это управляет стандартными компонентами OpenGL процесс рендеринга ES:

  • Прежде, чем вызвать Ваш метод рисования, представление:

    • Делает EAGLContext возразите текущему контексту

    • Создает объект кадрового буфера и renderbuffers на основе его текущего размера, масштабного коэффициента и drawable свойств (в случае необходимости)

    • Связывает объект кадрового буфера как текущее место назначения для команд рисования

    • Устанавливает OpenGL область просмотра ES для соответствия размера кадрового буфера

  • После Ваших возвратов метода рисования, представления:

    • Решения, мультивыбирающие буферы (если мультивыборка включена),

    • Отбрасывания renderbuffers, чье содержание больше не необходимо

    • Подарки renderbuffer содержание к Базовой Анимации для кэширования и дисплея

Рендеринг Используя объект делегата

Многие OpenGL код рендеринга реализации приложений ES в пользовательском классе. Преимущество этого подхода состоит в том, что он позволяет Вам легко поддерживать многократные алгоритмы рендеринга путем определения различного класса средства рендеринга для каждого. Рендеринг алгоритмов, совместно использующих общую функциональность, может наследовать ее от суперкласса. Например, Вы могли бы использовать различные классы средства рендеринга для поддержки и OpenGL ES 2.0 и 3.0 (см. Конфигурирование OpenGL Контексты ES). Или Вы могли бы использовать их для настройки рендеринга для лучшего качества изображения на устройствах с более мощными аппаратными средствами.

GLKit хорошо подходит для этого подхода — можно заставить средство рендеринга возразить делегату стандарта GLKView экземпляр. Вместо разделения на подклассы GLKView и реализация drawRect: метод, Ваш класс средства рендеринга принимает GLKViewDelegate протокол и реализации glkView:drawInRect: метод. Перечисление 3-3 демонстрирует выбор класса средства рендеринга на основе аппаратных функций во время запуска приложения.

Перечисление 3-3  Выбирая класс средства рендеринга на основе аппаратных функций

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Create a context so we can test for features
    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    [EAGLContext setCurrentContext:context];
 
    // Choose a rendering class based on device features
    GLint maxTextureSize;
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
    if (maxTextureSize > 2048)
        self.renderer = [[MyBigTextureRenderer alloc] initWithContext:context];
    else
        self.renderer = [[MyRenderer alloc] initWithContext:context];
 
    // Make the renderer the delegate for the view loaded from the main storyboard
    GLKView *view = (GLKView *)self.window.rootViewController.view;
    view.delegate = self.renderer;
 
    // Give the OpenGL ES context to the view so it can draw
    view.context = context;
 
    return YES;
}

Контроллер представления GLKit анимирует OpenGL содержание ES

По умолчанию, a GLKView возразите представляет его содержание по требованию. Однако главное преимущество к рисованию с OpenGL , ES является его возможностью использовать аппаратные средства обработки графики для непрерывной анимации сложных сцен — приложения, такие как игры и моделирования редко, представляет статические изображения. Для этих случаев платформа GLKit обеспечивает класс контроллера представления, поддерживающий цикл анимации для GLKView объект это управляет. Этот цикл следует шаблону разработки, распространенному в играх и моделированиях с двумя фазами: обновление и дисплей. Рисунок 3-2 показывает упрощенный пример цикла анимации.

Рисунок 3-2  цикл анимации
Two-phase animation loop with example code: Update increments an angle variable and uses it to calculate a rotation matrix, Display issues the drawing commands to draw content using that matrix

Понимание цикла анимации

Для фазы обновления контроллер представления вызывает свое собственное update метод (или его делегат glkViewControllerUpdate: метод). В этом методе необходимо подготовиться к рисованию следующего кадра. Например, игра могла бы использовать этот метод для определения позиций проигрывателя и вражеских символов на основе входных событий, полученных начиная с последнего кадра, и аналитическая визуализация могла бы использовать этот метод для выполнения шага его моделирования. При необходимости в информации синхронизации для определения состояния приложения для следующего кадра, используйте одно из свойств синхронизации контроллера представления такой как timeSinceLastUpdate свойство. На рисунке 3-2 фаза обновления постепенно увеличивается angle переменная и использование это для вычисления матрицы преобразования.

Для фазы дисплея контроллер представления вызывает свое представление display метод, поочередно вызывающий Ваш метод рисования. В Вашем методе рисования Вы представляете OpenGL команды рисования ES GPU для рендеринга содержания. Для оптимальной производительности Ваше приложение должно изменить OpenGL объекты ES в начале рендеринга нового кадра и представить команды рисования позже. На рисунке 3-2 фаза дисплея устанавливает универсальную переменную в программе программы построения теней к матрице, вычисленной в фазе обновления, и затем представляет команду рисования для рендеринга нового содержания.

Цикл анимации чередуется между этими двумя фазами на уровне, обозначенном контроллером представления framesPerSecond свойство. Можно использовать preferredFramesPerSecond свойство для установки уровня нужного кадра — для оптимизации производительности для текущих аппаратных средств дисплея контроллер представления автоматически выбирает оптимальную частоту кадров близко к предпочтительному значению.

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

Перечисление 3-4 демонстрирует типичную стратегию рендеринга анимированного OpenGL содержание ES, использующее a GLKViewController подкласс и GLKView экземпляр.

Перечисление 3-4  Используя контроллер представления и представления GLKit, чтобы нарисовать и анимировать OpenGL содержание ES

@implementation PlanetViewController // subclass of GLKViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
 
    // Create an OpenGL ES context and assign it to the view loaded from storyboard
    GLKView *view = (GLKView *)self.view;
    view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
 
    // Set animation frame rate
    self.preferredFramesPerSecond = 60;
 
    // Not shown: load shaders, textures and vertex arrays, set up projection matrix
    [self setupGL];
}
 
- (void)update
{
    _rotation += self.timeSinceLastUpdate * M_PI_2; // one quarter rotation per second
 
    // Set up transform matrices for the rotating planet
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeRotation(_rotation, 0.0f, 1.0f, 0.0f);
    _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
    _modelViewProjectionMatrix = GLKMatrix4Multiply(_projectionMatrix, modelViewMatrix);
}
 
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // Clear the framebuffer
    glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    // Set shader uniforms to values calculated in -update
    glUseProgram(_diffuseShading);
    glUniformMatrix4fv(_uniformModelViewProjectionMatrix, 1, 0, _modelViewProjectionMatrix.m);
    glUniformMatrix3fv(_uniformNormalMatrix, 1, 0, _normalMatrix.m);
 
    // Draw using previously configured texture and vertex array
    glBindTexture(GL_TEXTURE_2D, _planetTexture);
    glBindVertexArrayOES(_planetMesh);
    glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT, 0);
}
 
@end

В этом примере, экземпляре PlanetViewController класс (пользовательское GLKViewController подкласс), загружается из раскадровки, вместе со стандартом GLKView экземпляр и его drawable свойства. viewDidLoad метод создает OpenGL контекст ES и обеспечивает его для представления, и также устанавливает частоту кадров для цикла анимации.

Контроллер представления является автоматически делегатом своего представления, таким образом, он реализует обоих обновление и фазы дисплея цикла анимации. В update метод, это вычисляет, матрицы трансформации должны были вывести на экран вращающуюся планету. В glkView:drawInRect: метод, это обеспечивает те матрицы для программы программы построения теней и представляет команды рисования для рендеринга геометрии планеты.

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

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

Обработка векторной и матричной математики

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

Миграция от конвейера стандартных функций OpenGL ES 1.1

 OpenGL ES 2.0 и позже удаляет всю функциональность, связанную с конвейером графики стандартной функции OpenGL ES 1.1. GLKBaseEffect класс обеспечивает аналог Objective C для трансформации, освещая и заштриховывая этапы конвейера OpenGL ES 1.1, и GLKSkyboxEffect и GLKReflectionMapEffect классы добавляют поддержку общих визуальных эффектов. См. справочную документацию для этих классов для подробных данных.

Загрузка данных текстуры

GLKTextureLoader класс обеспечивает простой способ загрузить данные текстуры из любого формата изображения, поддерживаемого iOS в OpenGL контекст ES, синхронно или асинхронно. (См. Использование Платформа GLKit для Загрузки Данных Текстуры.)