Skip to content

Latest commit

 

History

History
206 lines (132 loc) · 19.4 KB

TASK-RU.md

File metadata and controls

206 lines (132 loc) · 19.4 KB

CG/2   # Задание 2

Вводный курс компьютерной графики
Автор задания: Александр Соболев

title

Сборка подробно описана в файле README.md Вркатце: устанавливаете библиотеки, создаете в корне папку build, заходите в неё, пишите один раз cmake .., затем make. После того как внесли изменения, снова пишите make. Чтобы запустить приложение, пишите ./main. В случае проблем с первоначальной сборкой, проверьте установленные библиотеки. Если ничего не помогает, спросите помощи у сверстников, либо создайте Issue на странице задания на GitHub (об этом ниже).

Управление в шаблоне

Escape - Выход
ПКМ - Захват мыши
Мышь - Вращение камеры
WASD - Перемещение камеры
QZ - Вверх/вниз в мировых координатах
EC - Вверх/вниз в координатах камеры
F - Переключиться на танк и обратно


Базовая часть (15 баллов)

Вам надо в срочном порядке (до засекречено) запустить танк на сверхсекретное задание. Мир надеется на вас, не подведите!

Для начала скомпилируйте и запустите программу. Сейчас она просто показывает пустой экран. Поскольку танки — удовольствие не дешёвое, мы сначала выведем на экран унылый, но зато очень дешёвый треугольник. Вам предстоит дописывать части уже написанной программы.

Задание (1 балл)

Тут вам понадобятся: MyGame.cpp, triangle/fragment.glsl, triangle/vertex.glsl.

Добавьте вызов triangle->Draw() в метод Draw в MyGame.cpp. Обратите внимание, что метод должен находиться в активной зоне шейдера tri_sh (в блоке с ShaderZone(tri_sh))

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

st1

Всё, что делает triangle->Draw() в данном случае это передает координаты точек треугольника и еще некоторую геометрическую информацию) в используемый шейдер. (Вы можете посмотреть, что именно передается в создании примитива треугольника в Primitives.cpp в CreateSimpleTriangleMesh)

Взгляните на координаты вершин на картинке внизу.

st1-comments

Итак, координаты попадают в вершинный шейдер triangle/vertex.glsl. Напомню, что вершинный шейдер, это программа, которая выполняется для каждой вершины геометрического примитива. В нашем случае вершины всего 3: (-1, 1, -0.5), (-1, -1, -0.5), (1, -1, -0.5). (третья координата пока не используется). Вершины попадают в переменную vertex с аттрибутом расположения location=0. (Это происходит потому что для позиций используется glEnableVertexAttribArray(0) в Primitives.cpp) gl_Position - это специальная переменная, куда записываются полученные значения спроецированных вершин. Сейчас туда, как вы видите, записываются координаты без модификации.

gl_Position – ожидает координаты NDC Normalized Device Coordinates) – это координаты, где центр экрана считается 0,0), а углы соответствуют координатам нашего треугольника. Поэтому мы и получили такой результат.

После того, как все вершины будут обработаны вершинным шейдером OpenGL знает где он должен нарисовать каждый треугольник, остается только понять каким цветом его закрасить. Для каждого пикселя, который нам надо закрасить, вызывается фрагментный шейдер файл fragment.glsl) Если вы посмотрите в triangle/fragment.glsl, то увидите, что там есть специальная переменная color, в которую наш код должен записать рассчитанный цвет пиксела. По-умолчанию RGB. Поэтому треугольник фиолетовый = красный + синий.

Задание (2 балла): Поменяйте фрагментный шейдер так, чтобы программа выводила зеленый треугольник цвета 0, 1, 0)

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

Для проецирования вершин на экран используют матричные операции над однородными координатами. Однородные координаты — это 3-ёх мерные координаты, где добавляется четвертая фиктивная. Это позволяет при помощи матричного умножения осуществлять не только масштабирование Scale) и поворот Rotation), но и движение Translation).

Справа на картинке представлена структура произвольного матричного преобразования в однородных координатах. Левая верхняя подматрица представляет собой трехмерную матрицу (Как в курсе линейной алгебры) и позволяет осуществлять повороты и масштабирование вершины на координаты которой мы умножили данную матрицу. Координаты выделенные черным цветом — это координаты переноса. На них умноженная вершина сдвинется после умножения. Нижнюю строку можно на данном этапе считать всегда равной (0, 0, 0, 1)

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

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

Посмотрите на картинку ниже. Там изображена виртуальная камера, которую мы хотим создать. Ее поле зрения — это усеченная пирамида. Значит, чтобы спроецировать трехмерную вершину на экран, нам нужно применить к ней преобразование, которое переводит пирамиду в единичный куб!

Почему единичный куб? Выше мы уже разобрались, что наш экран - это единичный квадрат [-1, 1]x[-1, 1]. Добавляя глубину, с помощью которой мы сортируем пиксели, он превращается в единичный куб.

Более подробно о преобразованиях:
http://www.songho.ca/opengl/gl_transform.html

К счастью такая функция подсчитывающая такую матрицу уже существует.

ProjectionMatrixTransposed(fov, aspect_ratio, near, far)
fov – горизонтальный угол обзора камеры
aspect_ratio – соотношение ширины к высоте окна
near – расстояние до ближней плоскости отсечения
far – расстояние до дальней плоскости отсечения

Задание (3 балла)

Создайте в конструкторе MyGame.cpp матрицу projection с параметрами.
fov = 90 градусов
near = 0.1
far = 1000
Если использовали ProjectionMatrixTransposed, не забудьте оттранспонировать матрицу.

В нашем случае матрица проекции используется во всех шейдерах, поэтому давайте будем её передавать во все шейдеры. Для этого после выставления шейдера (shader->StartUseShader()) в ShaderZone, пропишем выставление матрицы через shader->SetUniform(name, matrix) в качестве имени используем "projection".

Результат выглядит так. Треугольник не влезает в экран! st3

Нам нужно добавить камеру, чтобы отлететь подальше!

Задание (5 баллов): Схожим образом передать матрицу view.

Все подсказки есть в файлах с пометкой [HELP].

st4

Щёлкните правой кнопкой мыши по экрану и обретите контроль! Вы всевластны над этим треугольником и можете рассмотреть его со всех сторон!

Но надо двигаться дальше, генералов не устраивает треугольник, они требуют танк!

Задание (9 баллов) Добавить больше объектов

Можете перестать рисовать треугольник, он нам больше не нужен. Но нам нужны другие объекты!

Добавьте в MyGame.cpp в методе Draw() недостающие методы отрисовки.

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

Давайте сначала раскрасим его, а потом разберемся, почему он застрял в земле.

Задание (10 баллов) Раскрасить танк

Вам понадобится tank/fragment.glsl.

Следуйте подсказкам и вы с легкостью разукрасите танк.

st5

Немного о том, как у нас это получилось: наш танк состоит из кучи треугольников, каждому треугольнику соответствует свой треугольник в текстурных координатах.

texure-exmaple

Каждый пиксель знает свою позицию и позицию трёх вершин, что его окружают и их текстурные координаты. На основе этих данных он вычисляет "среднее" значение текстурной координаты (интерполирует текстурные координаты).

Теперь мы знаем, что проблема застрявшего танка не в текстурах. Так в чём же?

Дело в том, что мы рисуем все части танка в одной точке, в нулевой, поэтому они застревают в земле и друг в друге.

Задание (12 баллов): Добавить модельные преобразования

Вам понадобятся: Шейдер зона tank_s в MyGame.cpp и tank/vertex.glsl. Все подсказки там.

Замечательно! У нас есть танк! st6

Пока генералы в восторге и не заметили, что танк не шевелится, давайте добавим ему вращением башни!

Задание (15 баллов): Добавить вращение башни

Вам понадобятся: Шейдер зона tank_s в MyGame.cpp. Все подсказки там!

Сесть в танк можно на кнопку F.

Результат:


Правила оценки

Задания из базовой части оцениваются только последней сделанной стадией. То есть баллы за промежуточные стадии не суммируются. Другими словами, максимальное количество баллов за базовую часть - 15 баллов.

Оценка осуществляется проверяющим с учётом субъективного восприятия изображения.

Дополнительная часть

Реализация карт теней даёт ещё 10 баллов. Требования к реализации:

  • Объекты должны затенять друг друга (т. е. тени на плоскость не засчитываются).
  • По клавише “2” должна включаться визуализация буфера глубины с позиции источника света. По клавише “1” необходимо вернуться в исходное состояние.

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

Дополнительные баллы при реализации карт теней:

  • PCF : +1 балл
  • VSM (variance shadow map): от + 2 до +4 балов
  • Каскадные тени (Cascaded Shadow Maps): + 5 баллов
  • Irregular Z Buffer Shadow Mapping : + 10 баллов
  • Другие техники карт теней в зависимости от сложности: от + 2 до +10
  • Тени от источника во все стороны (при помощи кубических текстурных карт): +4

Глобальное освещение и прочее:

  • Отражения при помощи кубических текстурных карт либо на плоскости (+2)
  • Reflective Shadow Map: +4
  • SSAO: от +3 до +6 (например HBAO)
  • Bloom (пост обработка, +2)
  • Другие техники глобального освещения: от +3 до +6 в зависимости от результата.
  • Реалистичное движения танка и анимация гусениц: (от 1 до 2 баллов).
  • Реалистичное движения танка по ландшафту (от 1 до 4 баллов).
  • Реализация источника света в виде системы частиц (огонь или искры): +4
  • Не предусмотренный бонус проверяющего: до +4.

Полезные ссылки

P.S. Если у вас ещё нет любимой IDE, советую обратить внимание на VsCode.

Вопросы

В случае, если вы нашли ошибку в коде, опечатку или орфографическую ошибку, вы можете смело создать Issue или Pull requst на гитхабе в репозитории задания.
https://github.com/Tirondzo/CG-2-2019-Task-2
Если есть какие-то невероятные сложности, вы так же можете создать Issue.