Как создать треугольник в unity

Процедурная генерация трёхмерных моделей

Как создать треугольник в unity

Процедурная генерация — замечательная штука! Интереснее всего работать именно с графикой, особенно трёхмерной — сразу видно результат. Всего пары инструкций достаточно, чтобы создать облако треугольников как на картинке выше.

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

На примере движка Unity и C# я покажу как можно работать с моделями и превращать текст в графику. Большинство приводимого кода легко портируется на другие фреймфорки и языки.

Видео:[Unity] генерация 3d объектов. Mesh generationСкачать

[Unity] генерация 3d объектов. Mesh generation

Треугольник

Как создать треугольник в unity
Начнём с простейшей формы — треугольника. В Unity и во многих других движках используется популярный способ описания моделей: с помощью массивов вершин, треугольников и нормалей. Дополнительно для текстурирования используются uv-координаты вершин. Для работы с моделями есть класс Mesh, в котором для каждого набора данных имеется отдельный массив. В Mesh.vertices хранятся координаты вершин, в Mesh.triangles — индексы вершин группами по три. А в Mesh.normals и Mesh.uv лежат векторы нормалей и координаты uv-карт, индексы которых должны совпадать с индексами соответствующих вершин, т. е. порядок в массивах должен быть одинаковым. Покажу на примере, чтобы было понятнее.

Сделаем функцию, которая на вход принимает три вершины треугольника, а отдаёт готовую модельку. Начнём с основы.

Упаковываем три вершины в массив и передаём мешу. Треугольник описывается элементарно, но есть нюанс, про который нужно помнить. Если смотреть на модель снаружи, то вершины её треугольников должны располагаться по часовой стрелке. Это сделано для того, чтобы во время отрисовки можно было отсечь треугольники, которые «не смотрят в камеру», и обрабатывать их отдельно. Порядок вершин рассчитывается очень просто, поэтому такой способ фильтрации очень эффективен. Если взять произведение двух векторов, то можно найти третий вектор, перпендикулярный плоскости, образуемой сомножителями. Если пробежаться по треугольнику и посчитать произведения, то можно узнать порядок вершин. Кстати эти перпендикулярные вектора нам тоже нужны для описания моделей — это ведь нормали. Нормаль считается следующим образом:

Сначала сделали из трёх точек два вектора, а потом перемножили. Эта нормаль будет одинаковой на всех вершинах треугольника.

Осталось добавить uv-координаты, для трёх вершин это просто.

Ну и всё, треугольник готов. Теперь его можно использовать.

Видео:Как создать Ragdoll в Unity3D?Скачать

Как создать Ragdoll в Unity3D?

Четырёхугольник

Как создать треугольник в unity
Помимо треугольников есть ещё один популярный примитив для моделирования — четырёхугольник, ну или квад, если вам так больше нравится.

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

Напоминаю, что вершины по-прежнему записываются по часовой стрелке.

Теперь, когда мы имеем два базовых примитива, мы можем собрать любую модель.

Видео:Трюки юнити: Как сделать любой пивот для объекта?Скачать

Трюки юнити: Как сделать любой пивот для объекта?

Плоскость

Как создать треугольник в unity
Поэкспериментируем со сборкой моделей на примере плоскости. Возьмём много квадратов и разложим стык в стык.

Лень — двигатель прогресса, поэтому для сборки квадратов в модель будем использовать Mesh.CombineMeshes. Этот метод принимает на вход структуру CombineInstance, в которой можно указать модельку, её индекс и матрицу трансформирования. Для нас важно только первое, остальное игнорируем.

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

Видео:КАК СДЕЛАТЬ РАЗРУШЕНИЕ ОБЪЕКТОВ В Unity 3D | ЮНИТИ | РАЗРАБОТКА ИГР НА ЮНИТИСкачать

КАК СДЕЛАТЬ РАЗРУШЕНИЕ ОБЪЕКТОВ В Unity 3D | ЮНИТИ | РАЗРАБОТКА ИГР НА ЮНИТИ

Параллелепипед

Как создать треугольник в unity
Раскладывать плитки по плоскости слишком просто, пора перейти к третьему измерению.

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

Нужно всего шесть четырёхугольников. Зная длину, ширину и высоту параллелепипеда, можно рассчитать все его вершины. Удобно сначала найти два противоположных угла параллелепипеда, а потом от них отстраивать всё остальное. Также имеет смысл отцентрировать модель. Как это выглядит на практике можете посмотреть ниже.

Видео:Уроки по Unity3d #17 - работа с мешами(создание простых мешей из кода)Скачать

Уроки по Unity3d #17  - работа с мешами(создание простых мешей из кода)

Октаэдр

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

Как создать треугольник в unity
Хотя есть ещё один момент. До сих пор многие из вершин в наших моделях дублировались, хотя, как вы возможно слышали, при создании моделей наоборот всегда стараются сократить число вершин и треугольников. Почему же с кубом и октаэдром не так? Покажу на примере, вот код сборки октаэдра с минимально необходимым числом вершин:

В конце я применил Mesh.RecalculateNormals, который автоматически считает нормали, так проще.

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

Видео:Создаем землю, ландшафт (terrain) в Unity 3D #3Скачать

Создаем землю, ландшафт (terrain) в Unity 3D #3

Тетраэдр

Как создать треугольник в unity
Теперь можно взяться за фигуры поинтереснее. Расчёт вершин даже для простого тетраэдра требует потребует пятёрки по школьной геометрии, поэтому сразу предупреждаю, если не помните что на что делится в синусе, то лучше сначала заглянуть в учебник, как это пришлось сделать мне.

Освежили память? Продолжим.

Пусть наш тетраэдр стоит на одной из граней, тогда противоположную вершину можно добавить сразу:

Остальные вершины должны образовывать равносторонний треугольник. Их координаты можно найти с помощью синусов и косинусов. В Unity есть функции Mathf.Sin и Mathf.Cos, которые ведут расчёт в радианах. Делим окружность на три части и находим на ней три точки:

Из этих вершин уже можно собрать пирамидку, но это не будет тетраэдром, потому что у настоящего тетраэдра все грани одинаковые. Для настоящего тетраэдра основание пирамиды нужно немного уменьшить и сдвинуть ниже. Тут опять пригодятся синусы и косинусы, но чтобы ими воспользоваться, немного смухлюем и подсмотрим один угол в Википедии. «Edge central angle» это угол между радиусами описанной сферы, пересекающими вершины тетраэдра. Кхм, или что-то в этом роде, я успел запутаться пока формулировал мысль. В общем присовокупив этот угол получаем следующий код:

Не так уж и сложно, надеюсь, что все всё поняли. Вот так выглядит всё в итоге, с добавлением масштабирования:

А вот тот же тетраэдр без математики, с захардкоденными вершинами, почувствуйте разницу:

Видео:Как сделать взрыв в UnityСкачать

Как сделать взрыв в Unity

Икосаэдр

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

На каждой окружности их по пять штук, а значит интервал между ними 72 градуса. Смещение между окружностями — 36 градусов. Для выравнивания вершин нам опять понадобится волшебный угол из Википедии: «If two vertices are taken to be at the north and south poles (latitude ±90°), then the other ten vertices are at latitude ±arctan(1/2) ≈ ±26.57°». В переводе на русский это означает, что волшебный угол — арктангенс одной второй.

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

Видео:Физика в Unity - 1. RigidbodyСкачать

Физика в Unity - 1. Rigidbody

Заключение

Если вы внимательно читали код в статье, то наверняка заметили, что там много ненужных вычислений, тот же Mathf.Cos(magicAngle) из примера выше. При желании его можно посчитать только один раз и занести в переменную, это будет не так наглядно и понятно зато быстрее.

Кроме того в генерируемых моделях не самые удобные uv-карты, было бы неплохо их исправить, но для этого придётся переделывать очень много кода, пока и так сойдёт.

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

Исходники и бинарники для разных платформ можете скачать по ссылкам ниже.

Видео:Unity для новичков за 20 минут | Gamicle #unity #gamedev #gamicleСкачать

Unity для новичков за 20 минут | Gamicle #unity #gamedev #gamicle

Геометрические шейдеры Unity

Как создать треугольник в unity

Ресурсов по шейдерам в Unity вообще достаточно мало. Но есть очень специфичный тип шейдеров, для которых ресурсов мало до странности (по крайней мере, на момент написания) — это геометрические шейдеры.

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

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

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

Видео:Как сделать МЕНЮ в Unity? | Scene Management, UI, TutorialСкачать

Как сделать МЕНЮ в Unity? | Scene Management, UI, Tutorial

Предисловие

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

Как создать треугольник в unity

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

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

Однако самая крутая вещь в геометрических шейдерах, что когда они берут тройки вершин, образующих (например) треугольник, они могут не только определять, что происходит с этим треугольником, но также генерировать новые вершины и новые треугольники. Затем брать всю эту недавно сгенерированную геометрию и разворачивать ее, как делалось бы при смещении вершин в вершинном шейдере. Это позволяет, например, делать частицы из треугольников, как продемонстрировал VFX Mike.

Наконец, хотя их код поначалу может показаться пугающим, как только вы освоите некоторые вещи, использование шейдеров станет интуитивно понятным. И вы сможете лучше понять такие вещи, как UV и координаты пространства объектов. И, если вы чем-то похожи на меня, вы поймаете себя на том, что говорите: «О, чёрт, я не думал, что это сработает!».

Видео:Физика в Unity - 10. JointСкачать

Физика в Unity - 10. Joint

Как писать геометрические шейдеры Unity

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

Давайте посмотрим на код:

ВАЖНО: Чтобы избежать любых неточностей, автор настоятельно рекомендует взять код из github. В частности, его WordPress не хотел правильно печатать « triStream : Если вы не заметили, то геометрический шейдер возвращает «void», поэтому на самом деле ни одного объекта, как это делал бы вершинный шейдер. Геометрический шейдер на самом деле добавляет каждый треугольник в список TriangleStream, который принимает объекты типа «g2f». Если вы хотите вывести линии, вы превратите их в «inout LineStream lineStream», а если вы хотите вывести точки, это будет «inout PointStream pointStream».

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

Сначала в строке 56 мы создаем объект g2f, который будем использовать для постоянного изменения его полей, а затем добавляем объект в поток.

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

Во-первых, в строке 60 я использую прием «UnityObjectToClipPos», чтобы преобразовать позицию входной вершины из объектного пространства в пространство отсечения. Затем макрос «UNITY_TRANSFER_FOG» для передачи всей информации о тумане Unity. В строке 62 я также использую макрос «TRANSFORM_TEX» для изменения UV-координат на основе информации о масштабировании и тайлинге «_MainTex». Все это делается для каждой из трех вершин треугольника так же, как делали бы в вершинном шейдере, если бы у нас не было геометрического.

Наконец, мы добавляем модифицированный объект «g2f» к потоку треугольников, используя «triStream.Append (o);». После цикла в строке 66 также есть прием «RestartStrip». Он должен сообщить потоку, что будет добавлять отдельный треугольник впоследствии. Здесь, поскольку мы не добавляем никаких новых треугольников, это на самом деле не нужно. Я добавил, чтобы вы могли легко скопировать код для последующей доработки.

Фрагментный шейдер в шаблоне

Наконец, в строках 69-76 у нас фрагментный шейдер. Вы можете заметить, что он совершенно не отличается от фрагментного шейдера по умолчанию в новом неосвещенном шейдере, за исключением того, что в качестве параметра он получает «g2f» вместо «v2f».

Видео:Как сделать оптимизацию игры в Unity 3D // Occlusion CullingСкачать

Как сделать оптимизацию игры в Unity 3D // Occlusion Culling

Выдавливание пирамид

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

Наглядный пример того, что мы будем делать с каждым треугольником:

Как создать треугольник в unity

Посмотрим на код:

Перед геометрическим шейдером

Для этого шейдера я добавил новое свойство «_ExtrusionFactor», которое будет определять, насколько выдавленными будут пирамиды. Еще я добавил тег «Cull Off» в строке 11, чтобы избежать выбрасывания части граней из-за того, что некоторые треугольники нарисованы в неправильном порядке. На самом деле лучше было бы правильно нарисовать грани. Но давайте пока оставим так, чтобы легче использовать циклы.

Некоторые изменения были также сделаны в структурах данных. Чтобы получить вектор нормали каждой грани, сначала нужно получить вектор нормали каждой вершины, поэтому нам нужно добавить его как в структуры «appdata» и «v2g». Кроме того, в структуру «g2f» я добавляю поле цвета, которое поможет лучше визуализировать эффект.

Вершинный шейдер почти такой же, как и раньше, я просто передаю вектор нормали в данные «v2g» в качестве дополнительной информации.

Геометрический шейдер

Вот где на этот раз творится волшебство! Во-первых, вы можете заметить, что в строке 12 я упоминаю в качестве максимального количества для вывода в этом шейдере 12 вершин. Однако вы можете подумать, что это неправильно, поскольку мы добавляем только одну дополнительную вершину наверху пирамиды. По крайней мере, меня это изначально смутило. Но дело в том, что раз мы добавляем новые треугольники, нам придется добавлять каждую новую вершину, которая образует новый треугольник. Поэтому, поскольку мы добавим новый треугольник для каждого ребра, у нас будет 3 новых треугольника из 3 вершин в каждом, плюс исходный треугольник сетки с еще 3 вершинами. То есть 3 * 3 + 3 = 12 новых вершин. Видите, как это число может быстро выйти из-под контроля?

Для выдавливания нам понадобится центр каждого треугольника и вектор нормали к нему. Поэтому в строке 65 я вычисляю положение барицентра треугольника, получая среднее положение его точек, а в строке 66 получаю вектор нормали, также усредняя векторы нормалей каждой точки треугольника.

Затем я перехожу к созданию пирамид. Алгоритм выглядит так:

Для каждой из точек треугольника

  • Получить индекс следующей точки
  • Добавить вершину на месте текущей точки
  • Добавить вершину в барицентре треугольника и вытянуть ее вдоль вектора нормали грани на величину, равную «_ExtrusionFactor»
  • Добавить вершину на месте следующей точки

Именно это происходит в первом цикле for. В строке 69 я получаю индекс следующей точки, увеличивая i на единицу и используя модуль 3, чтобы не выходить за пределы диапазона массива. Затем в строках 71-75 я добавляю новую вершину точно так же, как в примере выше, только в этот раз я еще установил для нее значение цвета черным (в строке 74).

В строках 77-81 я делаю то же самое для точки пирамиды, но для ее положения я использую вычисленный барицентр, к которому добавляю вектор нормали, умноженный на «_ExtrusionAmount», чтобы переместить его вверх. Для кончика треугольника я использую белый цвет, так что выдавливание будет более очевидным.

Затем в строках 83-87 я делаю то же самое для следующей точки, также окрашивая ее в черный цвет.

Так как здесь мы фактически добавляем новый треугольник в каждый цикл, я добавил triStream.RestartStrip (); в конце цикла.

Наконец, после цикла в строках 92-99 я добавляю вершины исходного треугольника, также окрашивая его в черный цвет. И все готово:

Как создать треугольник в unity

Фрагментный шейдер

Фрагментный шейдер остается тем же самым, однако я умножаю цвет на «i.color», чтобы назначенные нами цвета вершин были видны.

Видео:Unity terrain. Как создавать ландшафт в unity3d.Скачать

Unity terrain. Как создавать ландшафт в unity3d.

Заключение

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

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

Видео:Очень просто! Создание 3д персонажа для игры #shorts #short #gamedev #unity3dСкачать

Очень просто! Создание 3д персонажа для игры #shorts #short #gamedev #unity3d

Как создать треугольник в unity

Для представления плоских поверхностей в Unity есть примитивы Plane и Quad (подробнее см. Примитивы. Однако полезно изучить то, как может быть построен минимальный меш плоскости, т.к. это, возможно, самой простой пример, с четырьмя вершинами для углов и двумя треугольниками.

В первую очередь, следует задать массив вершин. Предположим, что плоскость лежит на осях X и Y и путь её ширина и высота контролируются переменными-свойствами. Расположим вершины в таком порядке: нижняя-левая, нижняя-правая, верхняя-левая, верхняя-правая.

Как создать треугольник в unity

Т.к. свойства данных меша исполняют код “за кулисами”, будет куда более эффективно задать данные в собственном массиве, и затем назначить свойству, нежели получать доступ к свойству-массиву поэлементно.

Затем идут треугольники. Т.к. нам требуется 2 треугольника, каждый из которых определён тремя целыми числами, массив треугольников в общем счёте будет иметь 6 элементов. Помня о правиле упорядочивания углов по часовой стрелке, левый нижний треугольник будет использовать 0, 2, 1 в качестве индексов угла, в то время как другой (верхний правый) будет использовать 2, 3, 1.

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

Наконец, добавление текстурных координат в меш позволит ему правильно отображать материал. Предполагая, что мы хотим увидеть всё изображение на плоскости, все значения UV будут равны 0 или 1, в соответствии с углами текстуры.

Завершенный скрипт может выглядеть как-то так:-

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

💥 Видео

Как создать Terrain в Unity?Скачать

Как создать Terrain в Unity?
Поделиться или сохранить к себе: