OpenGL руководство по проектированию ES

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

Как визуализировать OpenGL ES

В этом разделе описываются две перспективы для визуализации проекта OpenGL ES: как клиент-серверная архитектура и как конвейер. Обе перспективы могут быть полезными в планировании и оценке архитектуры Вашего приложения.

OpenGL ES как клиент-серверная архитектура

Рисунок 6-1 визуализирует OpenGL ES как клиент-серверная архитектура. Ваше приложение передает изменения состояния, текстуру и данные вершины и команды рендеринга к OpenGL клиент ES. Клиент переводит эти данные в формат, который аппаратное обеспечение машинной графики понимает, и вперед их к GPU. Эти процессы добавляют наверху к производительности при обработке графики Вашего приложения.

Рисунок 6-1  OpenGL клиент-серверная архитектура ES

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

OpenGL ES как графический конвейер

Рисунок 6-2 визуализирует OpenGL ES как графический конвейер. Ваше приложение конфигурирует графический конвейер, и затем выполняет команды рисования, чтобы отправить данным вершины вниз конвейер. Последовательные этапы конвейера выполняют вершинный шейдер, чтобы обработать данные вершины, собрать вершины в примитивы, растеризировать примитивы во фрагменты, выполнить программу построения теней фрагмента для вычислений цвета и значений глубины для каждого фрагмента и фрагментов смешения в кадровый буфер для дисплея.

Рисунок 6-2  OpenGL конвейер графики ES
OpenGL performs complex operations as data flows through a program

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

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

OpenGL версии ES и архитектура средства рендеринга

iOS поддерживает три версии OpenGL ES. Более новые версии обеспечивают больше гибкости, позволяя Вам реализовать алгоритмы рендеринга, включающие высококачественные визуальные эффекты, не ставя под угрозу производительность..

 OpenGL ES 3.0

 OpenGL ES 3.0 является новым в iOS 7. Ваше приложение может использовать функции, представленные в OpenGL ES 3.0 для реализации усовершенствованных методов программирования графики — ранее доступный только на аппаратных средствах настольного класса и игровых приставках — для более быстрой производительности при обработке графики и принуждения визуальных эффектов.

Некоторые главные особенности OpenGL ES 3.0 выделяются ниже. Для полного обзора посмотрите  спецификацию OpenGL ES 3.0 в OpenGL ES Реестр API.

OpenGL ES, заштриховывающий версию языка 3.0

GLSL ES 3.0 добавляет новые опции, такие как универсальные блоки, 32-разрядные целые числа и дополнительные целочисленные операции, для выполнения большего количества вычислительных задач общего назначения в вершине и программах программы построения теней фрагмента. Для использования нового языка в программе программы построения теней исходный код шейдера должен начаться #version 330 es директива. Контексты OpenGL ES 3.0 остаются совместимыми с программами построения теней, записанными для OpenGL ES 2.0.

Для получения дополнительной информации посмотрите Принятие OpenGL ES, Заштриховывающий Версию языка 3.0 и OpenGL Язык Штриховки ES 3.0 Спецификации в OpenGL ES Реестр API.

Многократные цели рендеринга

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

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

  Пример рисунка 6-3 вывода программы построения теней фрагмента к многократным целям рендеринга

Вы устанавливаете многократные цели рендеринга с дополнением к процессу, описанному в Создании Объекта Кадрового буфера. Вместо того, чтобы создать единственное цветное присоединение для кадрового буфера, Вы создаете несколько. Затем вызовите glDrawBuffers функция для указания, который присоединения кадрового буфера использовать в рендеринге, как показано в Перечислении 6-1.

Перечисление 6-1  , Настраивающее многократные цели рендеринга

// Attach (previously created) textures to the framebuffer.
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _colorTexture, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _positionTexture, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _normalTexture, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
 
// Specify the framebuffer attachments for rendering.
GLenum targets[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(3, targets);

Когда Ваши команды рисования проблем приложения, Ваша программа построения теней фрагмента определяет, какой цвет (или нецветные данные) выводится для каждого пикселя в каждой цели рендеринга. Перечисление 6-2 показывает основную программу построения теней фрагмента, представляющую к многократным целям путем присвоения к выходным переменным фрагмента, расположения которых соответствуют установленных в Перечислении 6-1.

  Программа построения теней Фрагмента перечисления 6-2 с выводом к многократным целям рендеринга

#version 300 es
 
uniform lowp sampler2D myTexture;
in mediump vec2 texCoord;
in mediump vec4 position;
in mediump vec3 normal;
 
layout(location = 0) out lowp vec4 colorData;
layout(location = 1) out mediump vec4 positionData;
layout(location = 2) out mediump vec4 normalData;
 
void main()
{
    colorData = texture(myTexture, texCoord);
    positionData = position;
    normalData = vec4(normalize(normal), 1.0);
}

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

Преобразуйте обратную связь

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

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

  Обзор рисунка 6-4 анимации системы частиц

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

С обратной связью преобразования можно разработать механизм рендеринга для решения этой проблемы более эффективно. Рисунок 6-5 показывает обзор того, как Ваше приложение могло бы сконфигурировать OpenGL конвейер графики ES для реализации анимации системы частиц. Поскольку OpenGL , ES представляет каждую частицу и ее состояние как вершина, этап вершинного шейдера GPU’s, может выполнить моделирование для нескольких частиц сразу. Поскольку буфер вершины, содержащий данные состояния частицы, снова используется между кадрами, дорогой процесс передачи тех данных к памяти GPU только происходит один раз во время инициализации.

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

  2. Реализуйте свое моделирование частицы в программе вершинного шейдера GLSL и выполните его каждый кадр путем рисования содержания буфера вершины, содержащего данные позиции частицы.

    • Для рендеринга с включенной обратной связью преобразования вызовите glBeginTransformFeedback функция. (Вызовите glEndTransformFeedback() прежде, чем возобновить нормальное получение.)

    • Используйте glTransformFeedbackVaryings функция для указания, какие выводы программы построения теней должны быть получены обратной связью преобразования и использованием glBindBufferBase или glBindBufferRange функция и GL_TRANSFORM_FEEDBACK_BUFFER буферизуйте тип для указания буфера, в который они будут получены.

    • Отключите растеризацию (и последующие этапы конвейера) путем вызова glEnable(GL_RASTERIZER_DISCARD).

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

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

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

 OpenGL ES 2.0

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

 OpenGL ES 1.1

 OpenGL ES 1.1 обеспечивает только основной конвейер графики стандартной функции. iOS поддерживает OpenGL ES 1.1 прежде всего для обратной совместимости. Если Вы поддерживаете приложение OpenGL ES 1.1, считаете обновление Вашего кода для более нового OpenGL версиями ES.

Платформа GLKit может помочь Вам в переходе от конвейера стандартных функций OpenGL ES 1.1 до более поздних версий. Для получения дополнительной информации читайте Используя GLKit для Разработки Средства рендеринга.

Разработка высокоэффективного OpenGL приложение ES

Для суммирования хорошо разработанный OpenGL , приложение ES должно:

Рисунок 6-6 предлагает технологический маршрут для приложения, использующего OpenGL ES для выполнения анимации к дисплею.

  Модель Приложения рисунка 6-6 для управления ресурсами

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

Цикл рендеринга обрабатывает все элементы, Вы намереваетесь представить к OpenGL контекст ES, затем представляет результаты дисплею. В анимированной сцене некоторые данные обновляются для каждого кадра. Во внутреннем цикле рендеринга, показанном на рисунке 6-6, приложение чередуется между обновлением ресурсов рендеринга (создающий или изменяющий OpenGL объекты ES в процессе) и представлением команд рисования, использующих те ресурсы. Цель этого внутреннего цикла состоит в том, чтобы сбалансировать рабочую нагрузку так, чтобы CPU и GPU работали параллельно, предотвращая приложение и OpenGL ES от доступа к тем же ресурсам одновременно. Когда модификация не выполняется в запуске или конце кадра, на iOS изменяя OpenGL объект ES может быть дорогим.

Важная цель для этого внутреннего цикла состоит в том, чтобы избежать копировать данные назад с OpenGL ES к приложению. Копирование результатов GPU к CPU может быть очень медленным. Если скопированные данные также используются позже в качестве части процесса рендеринга текущего кадра, как показано в среднем цикле рендеринга, Ваши блоки приложений, пока не завершаются все ранее представленные команды рисования.

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

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

Суммировать важные характеристики этого проекта:

Остальная часть этой главы обеспечивает полезный OpenGL методы программирования ES для реализования опций этого цикла рендеринга. Более поздние главы демонстрируют, как применить эти общие методы к определенным областям OpenGL программирование ES.

Избегите синхронизировать и сбрасывать операции

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

Эти ситуации требуют, чтобы OpenGL ES представил буфер команд аппаратным средствам для выполнения.

Используя glFlush Эффективно

На некоторых настольных реализациях OpenGL может быть полезно периодически вызвать glFlush функционируйте для эффективного балансирования CPU и работы GPU, но дело обстоит не так в iOS. Основанный на мозаике Задержанный алгоритм Рендеринга, реализованный аппаратным обеспечением машинной графики iOS, зависит от буферизации всех данных вершины в сцене сразу, таким образом, это может быть оптимально обработано для удаления невидимой поверхности. Как правило, существует только две ситуации, где OpenGL приложение ES должен вызвать glFlush или glFinish функции.

  • Необходимо сбросить буфер команд, когда приложение перемещается в фон, потому что, выполняя команды OpenGL ES на GPU, в то время как приложение является в фоновом режиме причинами iOS для завершения приложения. (См. Реализацию Многозадачно-осведомленного OpenGL Приложение ES.)

  • Если Ваше приложение совместно использует OpenGL объекты ES (такие как буферы вершины или текстуры) между многократными контекстами, необходимо вызвать glFlush функция для синхронизации доступа к этим ресурсам. Например, необходимо вызвать glFlush функция после загружающихся данных вершины в одном контексте, чтобы гарантировать, что его содержание готово быть полученным другим контекстом. Это уведомление также применяется при совместном использовании OpenGL объекты ES с другим iOS APIs, такие как Базовое Изображение.

Избегите запрашивать OpenGL состояние ES

Вызовы к glGet*(), включая glGetError(), может потребовать, чтобы OpenGL ES выполнил предыдущие команды прежде, чем получить любые переменные состояния. Эта синхронизация вынуждает аппаратное обеспечение машинной графики работать жестко регламентированный с CPU, сокращая возможности для параллелизма. Для предотвращения этого поддержите собственную копию любого состояния, которое необходимо запросить и получить доступ к ней непосредственно, вместо того, чтобы вызвать OpenGL ES.

Когда ошибки происходят, OpenGL , ES устанавливает флаг ошибки. Эти и другие ошибки появляются в OpenGL Отладчик Кадра ES в XCode или OpenGL ES Анализатор в Инструментах. Необходимо использовать те инструменты вместо glGetError функция, ухудшающая производительность, если вызвано часто. Другие запросы такой как glCheckFramebufferStatus(), glGetProgramInfoLog() и glValidateProgram() также обычно только полезны при разработке и отладке. Необходимо опустить вызовы к этим функциям в Сборках конечных версий приложения.

Используйте OpenGL ES для управления ресурсами

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

Используйте двойную буферизацию для предотвращения конфликтов ресурса

Когда Ваше приложение и OpenGL ES получают доступ к OpenGL объект ES одновременно, конфликты ресурса происходят. Когда один участник пытается изменить OpenGL объект ES, используемый другим, они могут блокировать, пока объект больше не используется. Как только они начинают изменять объект, другой участник может не получить доступ к объекту, пока модификации не завершены. Также ES OpenGL может неявно копировать объект так, чтобы оба участника могли продолжать выполнять команды. Любая опция безопасна, но каждый может закончить как узкое место в Вашем приложении. Рисунок 6-7 показывает эту проблему. В этом примере существует единственный объект текстуры, который и OpenGL ES и Ваше приложение хотят использовать. Когда приложение пытается изменить текстуру, оно должно ожидать до ранее представленных завершенных команд рисования — CPU синхронизируется с GPU.

Рисунок 6-7  Однобуферные данные текстуры
Single-buffered vertex array data

Для решения этой проблемы приложение могло выполнить дополнительную работу между изменением объекта и рисованием с ним. Но, если Ваше приложение не имеет дополнительной работы, это может выполнить, это должно явно создать два тождественно размерных объекта; в то время как один участник читает объект, другой участник изменяет другой. Рисунок 6-8 иллюстрирует подход с двойной буферизацией. В то время как GPU воздействует на одну текстуру, CPU изменяет другой. После начального запуска ни один простаивают CPU или GPU. Несмотря на то, что показано для текстур, это решение работает на почти любой тип OpenGL объект ES.

Рисунок 6-8  данные текстуры С двойной буферизацией
Double-buffered vertex array data

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

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

Помните OpenGL состояние ES

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

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

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

Инкапсулируйте состояние с OpenGL объекты ES

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

Организуйте рисуют вызовы для минимизации изменений состояния

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

Реализация iOS OpenGL , ES может кэшировать некоторые данные конфигурации, в которых это нуждается для эффективного переключения между состояниями, но начальная конфигурация для каждого уникального набора состояния занимает больше времени. Для непротиворечивой производительности можно «предварительно воодушевиться», каждое состояние установило Вас, планируют использовать во время подпрограммы установки:

  1. Включите конфигурацию состояния или программу построения теней, которую Вы планируете использовать.

  2. Нарисуйте тривиальное число вершин с помощью той конфигурации состояния.

  3. Сбросьте OpenGL контекст ES так, чтобы рисование во время этой предтеплой фазы не было выведено на экран.