Часть №9: Постобработка в игре «Breakout» на C++/OpenGL

  Дмитрий Бушуев  | 

  Обновл. 20 Дек 2020  | 

 1773

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

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

На уроке о фреймбуферах мы продемонстрировали, как можно применять постобработку для достижения интересных эффектов при помощи всего одной текстуры. Мы собираемся сделать нечто подобное и в игре «Breakout»: создать фреймбуфер с прикрепленным к нему мультисэмплированным рендербуфером. Весь код рендеринга игры должен рендерить сцену в данный мультисэмплированный фреймбуфер, который, затем, копирует свое содержимое в другой фреймбуфер с прикрепленной к нему текстурой. Данная текстура — это сглаженное изображение игры, которое мы будем рендерить на экранный 2D-прямоугольник с применением (или без) эффектов постобработки.

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

   Шаг №1: Привязать мультисэмплированный фреймбуфер.

   Шаг №2: Выполнить обычный рендеринг игры.

   Шаг №3: Скопировать мультисэмплированный фреймбуфер в обычный фреймбуфер с прикрепленной текстурой.

   Шаг №4: Отвязать фреймбуфер (использовать заданный по умолчанию фреймбуфер).

   Шаг №5: В шейдере постобработки использовать текстуру цветового буфера из обычного фреймбуфера.

   Шаг №6: Выполнить рендеринг выходного изображения шейдера постобработки.

Шейдер постобработки позволяет активировать три типа эффектов: Shake, Confuse и Chaos.

   Shake (Встряска) — слегка встряхивает и кратковременно немного размывает сцену.

   Confuse (Дезориентация) — инвертирует цвета сцены, а также оси x и y.

   Chaos (Хаос) — использует ядро обнаружения граней для создания интересных визуальных эффектов, а также перемещает текстурированное изображение по кругу для получения забавного эффекта «Хаоса».

Ниже приведен краткий обзор того, как будут выглядеть данные эффекты:

Вершинный шейдер:

Активируемый тип эффекта выбирается на основе того, значение какой uniform-переменной установлено в true. Если значение true задано для параметра chaos или confuse, то вершинный шейдер будет манипулировать текстурными координатами, заставляя сцену вращаться (либо перемещать текстурные координаты по кругу, либо инвертировать их). Поскольку мы установили режим наложения текстур в GL_REPEAT, то эффект «Хаоса» заставит сцену повторяться в различных частях экранного прямоугольника. Если же переменная shake установлена в true, то позиции вершин будут перемещаться на некоторую небольшую величину, создавая эффект дрожания экрана. Обратите внимание, что chaos и confuse не должны принимать значения true одновременно, в то время как эффект «Встряски» (shake) способен работать с любыми другими эффектами.

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

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

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

#Класс PostProcessor

Заголовочный файл — post_processor.h:

Файл реализации — post_processor.cpp:

Что стоит здесь отметить, так это наличие функций BeginRender() и EndRender(). Поскольку мы должны визуализировать всю игровую сцену во фреймбуфер, то вызовы BeginRender() и EndRender() производятся соответственно до и после кода рендеринга сцены. В результате этого класс берет на себя управление и обработку «внутренними» операциями фреймбуфера. Использование класса PostProcessor внутри функции рендеринга игры будет выглядеть следующим образом:

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

Shake it

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

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

Затем в функции Game::Update() мы уменьшаем значение переменной ShakeTime до 0.0f, тем самым отключая эффект:

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

  GitHub / Часть №9: Постобработка в игре «Breakout» на C++/OpenGL — Исходный код


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (5 оценок, среднее: 5,00 из 5)
Загрузка...

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *