Так вот всё началось, когда я начал работать над коммерческим проектом, где нужно было из чёрно-белых видосов делать анимированные изображения из точек. Очень кстати пришлось то, что в генклубе sleeping подсказала ссылку на похожую работу. Там котик из точек складывается и под этим котиком были ссылки на реализацию. Реализация была такая:
Во-первых, у нас все частицы друг от друга отталкиваются. Это электростатическое взаимодействие. А во-вторых, они притягиваются к белым пикселям видоса, то есть там, где у нас светлое изображение, Тогда слетается больше частиц.
Изменяя, Ну то есть в можно настроить вид этого взаимодействия, управляя коэффициентами отталкивания и коэффициентом. притяжения к пикселям видео, если к видео притягиваются сильно то Будут в местах засвета будут скученности частиц, они будут друг друга толкать. а если Уменьшить то, наоборот на видео они будут практически не реагировать и заполнять будут экран более-менее равномерно.
Оставалось посчитать силы взаимодействия между частицами. Но тут была проблема, потому что частиц должно быть много, если бы их было мало, то мы бы брали каждую частицу. Мерили бы расстояние от неё до всех остальных частиц и по формуле вычисляли бы силу взаимодействия, складывали бы все эти маленькие силочки и получали общую силу, которая действует на частицу. Итак для каждой частицы То есть если вы очистить было 10, то нужно было бы произвести 100 измерений длины расстояние между ними, если бы частиц было тысяча, то миллионы смирений количество измерения, оно увеличивается пропорционально квадрату частиц. То есть это очень медленный вариант. Если частиц много нужно было как-то это оптимизировать.
Тогда я решил пожертвовать точностью, во-первых, я решил взять все частицы и нарисовать их на текстуре. Поставить на текстуре много точек, там, где все эти частицы находятся, а потом уменьшить разрешение этой частицы. Ой это текстуры век жили. Это очень легко делается буквально одной строчкой, кода это называется
теперь вместо того, чтобы Считать расстояние от частицы до каждой другой частицы нужно посчитать расстояние от частицы до каждого пикселя этой текстуры с низким разрешением. Проблема в том, что А ну, там, где мало точек попало в пиксель низкого разрешения. Там у нас будет бледный пиксель, там, где много, там будет яркий пиксель, то есть мы яркость пикселя умножаем на количество на его площадь. и получаем тот заряд Который раскидан по этому пилю. Если пиксель находится от нашей частицы далеко, то мы можем просто считать, что его координаты равны центру этого пикселя, то есть мы выбрасываем информацию о всех содержащих. об их конкретных расположениях усредняемых
И тут такой компромисс, Какой выбрать размер пикселя? То есть, какое разрешение этой текстуры сделать, если разрешение довольно высокое, то будет хорошая точность, но придётся считать расстояние до большого количества пикселей это замедлит. Выполнение программы, если мы возьмём крупные пиксели, то всё быстро посчитается, но при этом частицы будут лететь. Кто куда?
И тут пригождается другое свойство мигмефов. Это то, что они создаются пачкой, они создаются с сразу пачкой для разных размеров от одного пикселя до Копии изображения мы можем потом брать считывать пиксель из нужной текстуры из этой пачки. Мы можем с помощью Если это ноль, то мы сэмплим исходное изображение, если это единица, то изображение в два раза меньше. Разрешения и так далее вплоть до одного пикселя.
Остаётся только измерять расстояние до середины этого пикселя, если оно большое То всё-таки, если оно очень близко располагается к нашей точке, то начинает влиять уже вот вот это пренебрежение координатами зарядов, разбросанных по пикселю начинает влиять заметно. и приходится А уменьшать размер пикселя, то есть уменьшает левела в details, двигаться к нулю и практически вплоть до исходного изображения. Я путём экспериментов пришёл к тому, что мы должны добиться того, что размер пикселя. Я имею в виду пиксель пикселя текстуры пониженного разрешения, измеренного в пикселях исходной текстуры, что размер этого пикселя должен быть? В где-то в пять раз меньше, чем расстояние. от частицы до середины этого пикселя
Всё, Это вроде бы пыталась как-то работать, Но работала кривовато. Все пиксели дёргались, и они расползались всё время за края экрана было непонятно. Это правильно вообще или неправильно. Поэтому я сделал два дополнения, во-первых. Я стал рендерить пиксель на вот эту текстуру не частицу на эту текстуру не одним пикселем, а размытым пятном пикселей. Такой размытый кружочек он добавлял плавности, Потому что если частица оказывалась на границе двух. Квадратов двух пикселей, то она влияла, на каждый из них это давало более плавное взаимодействие. А с тем, что у нас частицы вылетали за края? Мне помогли. Формулы я не помню, как это называется? Модульная математика или блин, не помню. Ну, в общем, если мы как будто Соединяем, а края экрана правые слева верхние. То есть, топология Тора если мы уйдём вправо мы придём слева. То есть между двумя частицами можно поверить расстояние? Как будто бы они находятся не на квадрате крана, А на этом Торе есть. Ну то есть формула, она немножко отличается. Там добавляется пару условий, но она довольно просто Таким образом мы можем вычислять расстояние между пикселями и также Вектор от одного пикселя до другого с учётом того, что они не на квадрате.
Я до этого говорил о том, что мы делаем мепмапы и Сэмплим текстуру, в которую рендерится все частицы, но то же самое мы делаем из текстуры видео. Мы тоже Превращаем её в пачку текстур пониженного разрешения и также их сам прям только знак у с коэффициента другой, если к первому От первых они отталкиваются, то ко второму не притягивается.
И после этих двух изменений оно вдруг резко заработало. То есть я не мог поверить своим глазам, что нас сразу просто произошёл какой-то качественный скачок и анимация стала плавной перестала дёргаться. и всё заработало. Я прикрутил. Вот видео не из файла, А через веб-камеру тоже оказалось нетрудно. И всё стало классно анимироваться. Я рассказал один клубе про эту штуку, и мне тут же сказали, что это Очень напоминает алгоритм барнетта. Видимо я не знаю, тогда один человек или два, но это алгоритм, который Ну то есть как раз для решения на базе проблем. Когда у нас много-много частиц взаимодействует все со всеми. К сожалению я не оказался первооткрывателем этого алгоритма его придумали ещё до моего рождения, но всё равно было приятно такое велосипед изобрести.