среда, 24 января 2018 г.

Подготовка проекта в AGK для использования постобработки


Запишем размер экрана в константы (или переменные, если размер экрана будет меняться):

#constant width 1280
#constant height 720

Выполняем стандартные команды:

SetWindowSize( width, height, 0 )
SetOrientationAllowed( 1, 1, 1, 1 )
SetSyncRate( 60, 0 )
SetScissor( 0,0,0,0 )

UseNewDefaultFonts( 1 )

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

render_image=CreateRenderImage(width, height, 0, 0 )

Если нужно создать сложный многослойный эффект (например bloom), то таких текстур может понадобиться намного больше.
Следующим шагом будет создание прямоугольника, который будет отображать текстуру на экране:

quad=CreateObjectQuad()

Quad можно представить как большой спрайт, который занимает весь экран.
Дальше загружаем шейдер (GLSL):

shader=LoadFullScreenShader("shaders/color.ps")

Загружаем только пиксельный шейдер. Вертексный шейдер нам не нужен, так как геометрии мы никакой менять не будем.
Последний этап, это разделение стандартного рендера движка на свой.
Вот так выглядит стандартный цикл:

DO
//команды пользователя
Sync()
LOOP

А вот так разделенный на отдельные части:

DO
//команды пользователя
    Update2D(0)
    ClearScreen()
    Render()
    Swap()
LOOP

Немного о командах:
Update2D(0) - обновление положения всех 2D объектов (для 3D есть Update3D(0))
ClearScreen() - очистка прошлого кадра (буфера)
Render() - визуализация всех созданных объектов в буфер (не на экран)
Swap() - замена буферов и вывод всего содержимого на экран
По такому принципу происходит двойная буферизация кадров в играх. Один буфер отображается на экране, а другой тем временем подготавливается. Команда Swap() меняет их местами.

Запишем код, который будет использовать наш шейдер для создания эффекта "Хроматическая аберрация":

DO
   SetRenderToImage(render_image,0)
   ClearScreen()
   Render()

   SetObjectImage( quad, render_image, 0 )
   SetObjectShader( quad, shader)

   SetRenderToScreen()
   ClearScreen() 
   DrawObject(quad)
    
    Swap()
LOOP

Команда SetRenderToImage(render_image,0) перенаправляет визуализацию с экрана в изображение которое мы создали в начале программы.
Обязательно нужно очистить текстуру командой ClearScreen() (хоть команда и переводится как "очистить экран", но рендеринг происходит в текстуру, поэтому будет очищена именно текстура render_image).
Дальше рисуем все объекты командой Render(). И передаем нашу текстуру объекту quad командой  SetObjectImage( quad, render_image, 0 ). Цифра 0 указывает под каким номером будет текстура передана в шейдер. Мы используем только одну текстуру поэтому пишем порядковый номер 0 (для второй текстуры 1 и тд). Собственно подключаем сам шейдер к объекту quad:  SetObjectShader( quad, shader). 
И возвращаем рендеринг обратно на экран SetRenderToScreen(). Естественно очищаем его от предыдущего кадра командой ClearScreen().
Последнее, что нужно сделать - это нарисовать единственный объект quad, который содержит "снимок" всех объектов игры и уже обработан шейдером. Для этого пишем команду DrawObject(quad) и меняем буферы кадров местами Swap().

ЗДЕСЬ СТРУКТУРА ШЕЙДЕРА!

Результат: 



Весь код:

#constant width 1280
#constant height 720

SetWindowSize( width, height, 0 )

SetVirtualResolution( width, height ) 
SetSyncRate( 60, 0 )
SetScissor( 0,0,0,0 )

render_image=CreateRenderImage(width, height, 0, 0 )
quad=CreateObjectQuad()
shader=LoadFullScreenShader("shaders/color.ps")

image=LoadImage("1.jpg")  //любая картинка для теста
sprite=CreateSprite(image)

DO
    
    Update2D(0)
    
    SetRenderToImage(render_image,0)
    ClearScreen()
    Render()

   SetObjectImage( quad, render_image, 0 )
   SetObjectShader( quad, shader)

   SetRenderToScreen()
   ClearScreen() 
   DrawObject(quad )
    
    Swap()
LOOP

Комментариев нет:

Отправить комментарий