Pull to refresh
85
2
Григорий Дядиченко @DyadichenkoGA

Master of Unity3D

Send message
Отдельные меши тоже надо заранее генерировать. Обычно на уровне нет задачи ретоп делать прям по ходу дела. Либо на загрузке, либо просто вообще заранее
Хотя туплю, нормали можно в нормали и записать, тангенты использовать для чего-то ещё или не использовать вообще. Меш мы не генерируем с нуля. Просто есть базовый, и мы делаем его автоматическую ретопологию с учётом полюсов и геометрии луж. С помощью triangle.Net не так сложно такое сделать. По сути самый сложный алгоритм связанный с ретопологией — это получить контуры для мешей из текстуры шума. Но можно с каким-то шагом разбить текстуру на точки, отсечь по какому-то значению, а дальше алгоритмом распаковки подарка с ограничениями собрать контуры из получившегося облака точек. Если делать это не в реальном времени, а заранее, подобный алгоритм займёт адекватное время. Для произвольной модели единственное с чем по идее могут возникнуть проблемы — это uv маппинг, если он сложный.
Если делать эффект правильно, чтобы получилось красиво, можно пойти несколькими путями. Если дальний ракурс, то как говорили выше лучше не заморачиваться и пользоваться партиклами. Если же вблизи и нужно на какой-то меш наложить лужи с рябью, какие тут возникнут проблемы по ходу.

Разберём немного способы:

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

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

О чём я думал, не назову это способом, просто что мне приходило в голову. Тут суть не в блеске. Если думать над тем, чтобы делать «быстро» без сложной фрагментной части в целом. У нас есть 8 параметров доступных для записи (4 координаты тангентов и вертекс колоров) Если делать процедурненький алгоритм, то мы просто записываем что-то вроде нормал мапа в тангенты, а данные о полюсах в вертекс колоры меша. Для того чтобы разбросать лужи — генерируем шум (поэтому в проекте можно найти простой генератор текстуры шума перлина, так как сама генерация интегрирована в юнити) Дальше, делаем лужи хайполи, а остальную геометрию лоуполи (процедурно — это не так сложно на самом деле, просто по шуму генерируем сетку меша специальным образом) По идее в данном случае нормали в вертексе в соответствии с «кривизной лужи» дадут правильный эффект. Шум станет картой отражений (так как лужа должна отражать сильнее, чем меш под ней) и должно получиться красиво и +- универсальненько. Но условно этот проект я собирал дня 4 где-то (так как надо ещё же найти всю информацию, которую я постарался структурировано описать), а вот всё что я описал писать ещё недельку, и мне пока не до того.

В шейдере с несколькими полюсами сделано вообще неоптимально, лучше параметры полюса передавать в этом случае через vertexColor, а не через текстуру. В данном случае текстура не имеет особого смысла

Понятное дело, что изначальная идея, что этот эффект накладывается на лужи, где такой эффект и будет. И то с такого ракурса это не имеет смысла. Если сделать по подобному уроку на таком расстоянии тоже будет красиво, пользователь разницы не увидит точно. Статья именно про математику волны, так как изучая вопрос я столкнулся с забавной вещью. Я находил разные видео, где выражение подбиралось видимо «на глаз». Так как кроме базы скажем почему выражение в тут именно такое — непонятно. Собственно цель статьи больше показать применение математики и небольшой кейс, а не сказать «решайте эту задачу так»
Если речь про пример с дорогой и дождём — это то, что было под рукой по сути. С такого ракурса и на таком расстоянии особого смысла действительно не имеет. Но если взять ведро с водой, случай VR и другие случаи когда пользователь может подойти в упор, то тогда математика выглядит в разы лучше. Плюс сам по себе шейдер вертексный и дешёвый, только требовательный к геометрии. Брызги партиклами доработать — это не супер сложно. Вообще суть была в волновой математике больше, чем в видео в конце. С той же волной можно сделать красивый эффект от падения метеорита и т.п.
Ну то есть цель статьи и примера скорее показать математику и применение. Если углубляться, то вообще лужи должны быть, или отдельными мешами и в шейдере должна присутствовать рефракция, или должны в фрагментном шейдере основного меша делать лужу и так же с рефракцией, сейчас деформируется сама дорога. На дальних планах выглядит адекватно, работает шустро. На ближних уже не так. Собственно благодаря тому, что деформируется сам меш и получается эффект похожий на рефракцию (пример с плиткой), но по хорошему для этого должна быть в фрагментном шейдере часть которая «выдавливает» лужи, чтобы они обладали реальной глубиной. С нынешним эффектом, если бы дорога была бы по ровнее, это выглядело бы так, как будто вся дорога под водой. Нынешний шейдер с небольшой доработкой по рефракции уже будет выглядеть лучше.
Первые 5 секунд с эффектом, дальше без. Чтобы как раз показать разницу. Из-за качества видео и ракурса может быть визуально не так заметно, но общее впечатление от картинки создают такие мелочи. Хотя пример с машиной далёк от идеала, так как нужно ещё сделать всплески, нормально настроить партиклы самого дождя, разбить на лужи и сделать эффект преломления. Но это не цель данной статьи. Вообще с таким ракурсом я бы чаще применял что-то попроще, но в случае когда пользователь может на всплески смотреть чуть ли не в упор (пролёт камеры в кат сценах, VR, шутеры) — незаменимая штука
Poly2Tri сильно слабее, и он генерит не очень хорошие сетки. Но он прям заточен под Unity, в отличии от Triangle.Net. Я использовал Poly2Tri в этом проекте — для такого норм. В целом зависит от конкретной задачи + лицензии тоже важны. Poly2Tri кажется под MSPL, а Triangle.Net — MIT. И MIT даёт больше возможностей по использованию.

У меня сейчас есть идея поиграться с FEM (метод конечных элементов) в Unity, а для этого лучше иметь Delanay Refinement алгоритмы под рукой.

Между этими двумя либами основная разница, что Poly2Tri сильно проще, но Triangle.Net в разы мощнее и позволяет решать большее число задач, так как судя по сетке Poly2Tri, у него под капотом Ear Clipping with Holes.
Если ты про эту задачу codesuppository.blogspot.com/2011/05/hacd-hierarchical-approximate-convex.html я находил только частные случаи или разные реализации HACD. В целом зависит от требований, но если писать с нуля — «обученный человек» дешевле и лучше сделает, если не продавать само такое решение. Мало кому это надо в промышленных масштабах
Тут можно прочитать про legal аспекты самого формата. А вот со стилем — вопрос спорный. С одной стороны ниже есть ремарка про «рендеры», что в сущности тоже самое, что и использование в игре. С другой стороны, без брендинга лего — кое-го тут нет, вопрос считается ли это лего. Копии конкретных наборов лего — думаю да, нельзя. Вообще я замечал, что многие пишут такую ремарку «LEGO® is a registered trademark of the Lego Group, which does not sponsor, endorse, or authorize this site. Visit the official Lego website at www.lego.com.», но лучше один раз дать ссылки на legal информацию юристу и проконсультироваться с ним. Я не использовал данную библиотеку в коммерческих проектах на сторы и не юрист, поэтому подробно подсказать не смогу.

Один юнит равный 100м в любом случае даст такую же ошибку флота, так как коичество значащих символов не изменится, а на вход PhysX получает флот, и там он округлится

По этой причине это сказано в самом начале до ката, что тут нет ничего супер сложного, и если вы разбираетесь в теме, то в статье не найдёте ничего нового. Но я работаю с огромным числом самых разных проектов, так как не являюсь штатным сотрудником, и чаще дорабатываю чужие решения. И вот костыли связанные с незнанием математики встречаются слишком часто. При этом достаточно простых вещей, а не того, что допустим при физическом моделировании, при использовании метода конечных элементов, ошибка зависит от самого острого угла треугольника, и поэтому EarClipping — не лучший алгоритм, чтобы триангулировать что-либо в подобных задачах. И надо использовать хотя бы Делоне.
Позиции в сцене юнити для рендера и позиции в симуляции не обязаны совпадать. Абстрагировать симуляцию так, чтобы у тебя камера всегда находилась в (0,0,0) в юнити сцене, а остальное двигалось с поправкой на это — не супер большая проблема. Смысла нет, так как действительно важно расстояние между камерой и объектами. OpenGL если мне не изменяет память работает с интом и флотом (GLSL), а PhysX с флотом, то есть дабл округлится в этой точке, и мы получим тоже самое. Задача симуляции — не так часто встречается и легко обыгрывается, но на уровне движка её обыгрывать нет смысла, так как это приводит к не очевидному поведению.

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

TRS — это вообще отдельная песня. Так как, как и с методом Хаусхолдера найти адекватное структурированное описание что это и из чего складывается — надо постараться. Сама матрица простая, если это написано не языком вышмата, а русским. Так как если мы перейдём к определению, в котором вообще это всё работает в гиперплоскости строго говоря, то думаю большинство тупо не сможет прочесть этот текст со справочником (матрица 4х4, а работаем мы с 3д пространством)

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

Потом постепенно может буду увеличивать сложность материала. Но условно если брать кватернионы, про них есть крутая огромная статья объясняющая что это, и вот её цель как раз таки научить. Цель же этого цикла показать — зачем читать эту огромную статью про кватернионы к примеру, и дать готовую реализацию каких-то простых компонент для примера, чтобы было ясно, как это можно использовать в Unity. В конкретно этой статье примера нет, так как про LDraw хочется написать отдельно
В общем дело тут не только в Unity. Сам PhysX на такое не рассчитан, а с точки зрения рендера такой диапазон чисел просто смысла не имеет. Так как если дистанция между объектом и камерой будет 17км, то объект тупо не будет видно в большинстве случаев с перспективной камерой. А дабл жрёт больше памяти, работает медленнее и т.п. Конечно было бы удобное апи, чтобы люди стреляли себе в ногу и не понимали, почему фпс в разы медленнее, чем на флоте, и почему PhysX всё равно глючит, если в него прокидывается дабл. А так, учитывая что всё то, что находится в фруструме камеры не требует такой точности, достаточно построить правильное преобразование всех позиций из одного трёхмерного пространства в другое. Да, применить ко всем объектам. Исходя из «абстрактной позиции мира» и «позиции камеры». Самое простое (но правда для реалтайма вряд ли подходит при сложной симуляции) — считать что камера в (0,0,0) вообще всегда для рендера, и к ней подтягивается мир. В этом случае у нас ломается только OcclusionCulling, но зато самая высокая точность с точки зрения рендера будет по идее)
Ну с 17 км будет сантиметровая точность. Но вообще в Unity да — floating origin. Можно придумать какой угодно маппинг, но по своей сути — это floating origin. И сохранить значения PhysX физики не так сложно (ну проскочит один кадр или можно сделать ручную компенсацию)

В целом тут две основные причины почему рендер на double особого смысла не имеет. Если камера движется вместе с симуляцией, то с помощью тех же матриц компенсировать позиции чисто для рендера — не самая страшная задача. Дабл работает медленнее, так как просто процессору нужно больше регистров складывать. И скажем PhysX сам по себе работает с флотом. С точки зрения рендера такая точность не имеет смысла, так как объект на расстоянии 17 км от камеры или 18 км от камеры это в большинстве случаев и так, и так пару пикселей. Если нужна точность для расчёта самой симуляции и без PhysX (какая-нить жидкостная симуляция или просто математическая, а юнити для визуализации) то проще считать всё в дабле в своих методах, где нужна точность, а потом делать отображение модели симуляции во флот со сдвигом.
Спасибо) Но в целом видимо математику не любят. По сравнению с другими статьями статистика прям печальная)
Исходники открытые, так что можно изучить и посмотреть как реализовано, чтобы потом использовать уже в чём-то своём. Сейчас я готовлю статью по аффинным преобразованиям. Потом может руки написать про триангуляции и генерацию процедурных мешей в целом.

Генерация меша комнаты не сказать, что что-то супер сложное. Там чуть-чуть пришлось покопаться, чтобы была возможность задавать толщину стен, а в остальном всё +- просто. Вот сам класс отвечающий за генерацию меша (всего 253 строки) (для триангуляции используется Poly2Mesh)
В целом есть много численных методов интегрирования лучше, чем метод прямоугольников, я не спорю, но ещё раз. Цель статьи показать, какие задачи в целом решаются математикой, а не показать наилучшее решение конкретной задачи.

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

Можно вспомнить много численных методов, из популярных метод Симпсона ещё лучше, но тем не менее это не цель статьи, научить математике. На это в вузах по 4 года тратят. Интеграл нужен для вот такой-то задачи. Какой метод интегрирования подставить в GetApproxSquareAnimCurve — дело третье.
Я хз, что это за формула, и что в ней такое кси, но вообще на сколько мне известно, абсолютная погрешность на определённом интеграле равна v * (b — a)^2/(2n). А теперь подставим значения из конкретно приведённого мной примера. Распределение скорости в целом лучше брать нормализованным, так как дистанция определяется позже, но в задаче у нас v = 1, a = 0, b = 1, n = 1000, то есть мы получаем 1/2000 — казалось бы, что это много. Но при вычислении интеграла мы 1000 раз складываем float значения < 1, что даёт ошибку 10^(-6)*1000 = 1/1000, что уже больше. Но помимо этого в следующей формуле для вычисления скорости ошибка ещё выше, так как там увеличивается степень вычислений.

Так что в данном конкретном примере проблема во float. Но вообще точность float почти всегда будет хуже, чем вычисление подобными методами на достаточно большом количестве операций

Information

Rating
1,362-nd
Location
Москва, Москва и Московская обл., Россия
Registered
Activity

Specialization

Game Developer, Chief Technology Officer (CTO)
Lead
Git
C#
C++
Python
OOP
.NET
English
Research work
Algorithms and data structures
Applied math