Используем SetTextureOffset для анимации глаз
Если еще какую-то Face-morph вершинную анимацию сделать - будет очень живенько и мультяшно.
Если еще какую-то Face-morph вершинную анимацию сделать - будет очень живенько и мультяшно.
Я тут публиковал раньше постик о своей игре, физической симуляции, вычисляемой на видеокарте. Люди спрашивали, как это сделано. Но та игра была слишком громоздкой, чтобы по ней что-то объяснять. Поэтому, я сделал небольшой проектик, чтобы по нему всё объяснить. Это двумерная модель волос, вот гифка:
https://i.imgur.com/pxfW7cC.gifv
И для неё я написал подробный туториал:
https://habrahabr.ru/post/346268/
Там есть ссылка на сам проект с моделью волос. И там же есть есть ещё ссылка на более простой туториал, посвящённый тоже вычислениям на видеокарте.
Прошу всех изучить материал и больше не делать игр без восхитительной физики, без лагов вычисляемой на видеокарте.
Если кто хочет научиться в юнити вычислять на видеокарте, то вот здесь я опубликовал руководство с примером.
https://habrahabr.ru/post/346260/
Программа рисует фрактал мандельброта с помощью компьют шейдера.
Это пока простой туториал, скоро напишу более сложный, посвящённый физическому моделированию на GPU, в котором в качестве примера будет вот это
Наконец-то я доделал игру, которая работает на видеокарте. Она несколько месяцев повисела в раннем доступе на стиме, и теперь я её окончательно выпустил.
Основная особенность игры в том, что она представляет собой физическую симуляцию, которая выполняется на графическом процессоре. Основной код игры - это огромный compute shader, 6 тысяч строк на HLSL. Десятки тысяч взаимодействующих частиц обрабатываются параллельно, и выходит довольно быстро. Всё в игре сделано из этих частиц. Вот видосик с геймплеем:
Хочется просуммировать опыт разработки такого рода игры. Какие достоинства и недостатки у вычислений на видеокарте.
Достоинства:
1. Производительности GPU в 10-100 раз выше, чем у процессора, когда дело касается параллельных вычислений. Это очен много, так что на видеокарте можно делать принципиально другие игры, чем на процессоре. Моя игра просто не работала бы на CPU (то есть, была бы слишком медленной).
Недостатки:
1. Мало туториалов. Я потратил довольно много времени, чтобы всё изучить. И ещё больше - чтобы решить возникавшие проблемы.
2. Это в принципе сложнее, программировать для графиеского ядра. Привычные для процессорного вычисления вещи могут не работать. Например, вместо трёхмерного цикла на трёхмерном массиве я должен был делать трёхмерное пространство потоков, одновременно обрабатывающих одномерный массив (в который пришлось разложить исходный трёхмерный). Кроме того, надо заботиться, чтобы параллельные потоки работали с общими данными в защищённом режиме. В целом всё это решаемо, но требует больше времени.
3. Проблемы возникли и при чтении данных из видеопамяти. Это приходилось делать на каждом цикле, но работало оно слишком медленно. Потоу что в юнити не было асинхронного чтения в удобное для графического конвейра время, и он постоянно блокировался при чтении данных. В итоге fps падал вдвое. Пришлось использовать нативный плагин для асинхронного чтения из видеопамяти средствами directX, но во-первых, это не работало вне windows, а во-вторых, по неизвестным причинам это не работало на некоторых видеокартах, игроки жаловались.
4. Не у всех есть достаточно современные видеокарты, поддерживающие шейдеры и обладающие достаточной производительностью. Это ограничивало круг игроков, способных поиграть в мою игру.
5. Графические API на разных платформах немного отличаются друг от друга. В простых случаях они совместимы со стандартом directX, но у меня - не простой случай. У Metal одно небольшое ограничение, на андроиде - другое, на Vulkan - третье. В итоге, моя игра работает только на Windows.
6. Не удалось сделать вычисления детерминированными, так что пришлось обойтись без мультиплеера.
Но по итогам, я всё-таки доволен, что сделал что хотел. Очень интересно было посмотреть, каково играть в полностью физической, разрушаемой среде. Было бы неплохо, если б все графические API были совместимы, надеюсь, в будущем это всё устаканится. Потому что технология очень полезная из-за гигантского выигрыша в производительности. Вовсе не обязательно делать целую игру, можно перенести некоторые части игры на обработку в видеопроцессор. Например, поиск пути в стратегиях. А сейчас не любой разработчик будет готов писать compute shader, если всё равно его придётся дублировать, на случай, если игра запущена на платформе, не поддерживающей вычисление на видеокарте.
Ну и если кто-то вдруг захочет попробовать свои силы в этой области, то вот парочка туториалов:
http://kylehalladay.com/blog/tutorial/2014/06/27/Compute-Sha...
http://www.emersonshaffer.com/blog/2016/5/11/unity3d-compute...
Пока пишу основную статью по текстурированию/развертке/атласу для модульных (и не очень) построек - решил поделиться простеньким шейдером, что написал для себя. (Не шейдерфордж/амплифай).
конечный вид модели (3 текстуры 512*512) MRAO-Shader
Конечный вид модели (5 текстур 512*512) Standart (Rough)-Shader
Как работает?
Очень просто. У нас есть 3 текстуры Normal/Diffuse(albedo)/MRAO (или MGAO).
Объединяете их в Photoshop/Substance Painter/etc по каналам.
В MRAO (MetallicRoughnessAmbientOcclusion) подключается текстура, в которой
R канал - Металик.
G канал - рофнесс или Глосс. (Контролируется через toggle)
B канал - AO
Зачем так?
Для экономии места (веса проекта).
Ссылка для скачивание шейдера:
https://drive.google.com/open?id=0ByYwq4jRlilBY3FQazNRQm5tbn...
Привет, давайте поговорим о чем-нибудь симпатичном.
Предисловие.
В процессе разработки даже маленьких и простых игр посреди рутинных работ иногда появляются моменты, которые вызывают детский восторг. Собственно, такие моменты и отличают любимое дело (или хобби) от всех остальных.
У меня чаще всего такое происходит, когда понимаешь, как сотворить что-то новое, страшное и до этого момента непонятное. Сразу хочется об этом рассказать всем, кто все еще готов тебя слушать и поделиться, как делятся вкусным куском пиццы.
Поехали.
Мне понадобился индикатор загрузки для длинного подгружаемого списка (список друзей). Уже привычным и естественным жестом для пользователей мобильных является комбинация 1) потянуть резиновый список 2) поглядеть на спиннер 3) в списке появляется новое содержимое.
Индикатор нужен, чтобы пользователь понимал, что что-то происходит и это не конец списка.
В предыдущей игре я использовал простую вращающуюся картинку, но захотелось чего-то интереснее и технологичнее.
Сделаем простой индикатор при помощи шейдеров. Делать будем в Unity, конечно.
Процесс.
Идея простая. Нам нужна прямоугольная прозрачная картинка, на которой появится вращающееся кольцо, у которого начало будет непрозрачным, а конец полностью прозрачным. Примерно такая:
Я взял за основу стандартный шейдер (взять можно здесь: https://unity3d.com/ru/get-unity/download/archive). Выберите в выпадающем меню пункт "Встроенные шейдеры".
Создадим материал, укажем в нем наш новый шейдер и применим его к картинке. (в моем случае, для UI).
Удалил из него все лишнее и оставил только общую структуру.
Над вершинами мы издеваться не будем, только над текстурной частью.
По сути, мы должны описать, каким цветом нужно закрасить каждую точку нашей картинки. В данном случае, нам нужно получить окрашенное кольцо, все остальные точки оставив прозрачными. Напишем что-то такое:
И получим кривое колечко.
Обратите внимание на конструкцию lerp(a, b, step (c, X)). Она часто встречается в шейдерах и является заменой условного выражения. Читается как: “Если X >= с, тогда b, иначе a”.
Можете почитать о ней подробнее тут (https://shadowmint.gitbooks.io/unity-material-shaders/conten...).
Теперь сосредоточимся на получении нужного нам эффекта вращения.
Будем изменять значение полупрозрачности в зависимости от угла:
И получим что-то такое:
Отмечу, что функция frac() возвращает часть числа после запятой. С отрицательными значениями может работать странно, кажется, у меня была такая проблема.
А еще мы определили число Пи.
Ну и под конец - немного магии. Добавим прямо в шейдер влияние времени:
Про _Time в шейдерах можете почитать в мануалах (https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html). Отмечу только, что я использовал _Time.y - это время в масштабе 1:1, прошедшее с запуска игры.
Для финализации результата я еще немного сгладил края и... “голову” кольца.
Ссылка на полный код в конце.
В игре получилось так (там добавлено немного свечения):
Заключение.
Ребятам, кто начинает - экспериментируйте.
Ребятам, кто разбирается - поправляйте!
Всем спасибо. Делайте хорошие игры.
P.S.
Конечный результат (немного сбилась табуляция, ну да ладно) - (https://github.com/imetelyov/unity-loading-ring-shader/blob/...)
Мои скромные поделки можете глянуть тут: https://vk.com/quasar.games
На самом деле, писал новый шейдер для персонажей и случайно получился такой эффект.
По традиции, в динамике.
Если будут интересующиеся (надеюсь такие есть, все таки за 1к подписчиков перевалил, кто вы, люди:), могу разложить из каких составляющих собрана данная текстура и какие были сложности при ее создании.