Трудно быть Коротаевым – Telegram
Трудно быть Коротаевым
665 subscribers
135 photos
132 videos
255 links
🎨 Генеративное искусство, сложные алгоритмы визуализации
🔍 Разбор графики в играх и как это работает,
🎮 Свежие проекты из мира креативного кодинга
😎 Сообщества и конференции о которых стоит знать.

Автор: @lekzd
Download Telegram
Мемарт 1 апреля

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

Вчера, 1 апреля, там решили обновить аватарку и начали генерить арт со свидетелем из Фрязино. Получилось настолько весело, что в дело впряглись несколько человек и нагенерили пару десятков работ)
🔥7😁41😍1😈1💘1
Media is too big
VIEW IN TELEGRAM
Шары с физикой на компьютах

600 объектов, 1 draw call без учета пост процессинга благодаря инстансингу. Физика притяжения к аттрактору и калькуляция коллизий на видеокарте с помощью компьют шейдеров.

Просто залипательная штука. В сафари тоже работает :)

Эта демка - часть моего завтрашнего доклада на HolyJS. Буду вещать про то какой TSL классный, даже несмотря на то что еще сыроват.

Live: https://pavelmazhuga.com/lab/attractor-collisions/webgpu

Source code: https://github.com/pavel-mazhuga/portfolio/tree/main/src/app/lab/attractor-collisions/webgpu
🔥9😍3💘1
This media is not supported in your browser
VIEW IN TELEGRAM
Кто такой этот TSL и почему это важно

Threejs Shading Language это новое апи, позволяющее декларативно описать флоу течения данных из одних переменных в другие, используя узлы и связи, как на гифке выше, но кодом. Ну и где там революция?, поясню:

— это все исполняется на видеокарте
— это замена GLSL
— просто пишешь ноды, а Threejs генерит два шейдера на GLSL из этого
— теперь чтобы поменять что-то в материалах Threejs не нужно делать string.replace() 🤦
— туда завезли кроссбраузерные вычисления на видеокарте

Только посмотрите какой путь предлагал Threejs ранее:

var myMaterial = new THREE.MeshStandardMaterial()
myMaterial.onBeforeCompile = shader => {
shader.fragmentShader = //this is the fragment program string in the template format
shader.fragmentShader.replace( //we have to transform the string
'#include <alphamap_fragment>', //we will swap out this chunk
require('my_alphamap_fragment.glsl') //with our own
)
}


И документации не было, все копали в исходниках сами. Короче ура
115💘1
HolyJS Spring 2025

— Здравствуйте, Александр, вот вы очередной раз поучаствовали в организации крупной конференции, что чувствуете?
— Как же я задолбался...

Вот и прошли 2 дня встреч и долгожданных докладов, которые готовились последние 4 месяца, а некоторых спикеров я убеждал выступить с докладами на протяжении года. А другие буквально за 6 часов согласились выступить на открытом микрофоне, в конце первого дня.

Вот в эти дни довольно трудно было, но без них было бы еще труднее.
🎉3014🔥2💘1
This media is not supported in your browser
VIEW IN TELEGRAM
Прорыв в блюре, свечении и тенях

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

...our first priority had to be glows and shadows, or Guido would start flipping tables. (╯°□°)╯︵ ┻━┻


Ну сделали и сделали, а что раньше было не так?

Все дело, в том, что тени, антиалисинг и размытие реализованы на всех популярных платформах, которые могут выводить анимации Lottie и Rive, но вот беда: реализации везде разные, а значит с разными ограничениями.

— только на iPhone есть нативный блюр фона,
— на Android тени рассчитываются строго по гайдам Material Design и никак больше,
— на вебе есть Box Shadow.

При этом на каждой платформе можно самостоятельно взять и нарисовать тени и блюр, но здесь кроется главная проблема — производительность.

Вот пример кода, который нужен, чтобы получить R из RGB для центрального пиксела в сетке 3x3, где в с уже матрица со средним арифметическим соседних пикселей всего изображения (называется Convolution)

float r = c[0][0] 
+ c[1][0] + c[2][0]
+ c[0][1] + c[1][1]
+ c[2][1] + c[0][2]
+ c[1][2] + c[2][2];


и что это даст? сглаживание размером в 1 пиксел! Никто даже не заметит разницы на современных экранах, чтобы она была заметна нужно хотя бы повторить это 16 раз, последовательно, так и реализуется размытие по Гауссу.

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

Так что же сделали в Rive?

Во-первых, хороший рендер SVG который отлично разбивает полигоны на треугольники, для того, чтобы эффективнее рисовать это на GPU. (подробнее про Триангуляцию)

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

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

Про свой метод поиска пересечений и особенности триангуляции, конечно же, умолчали)
10💘2
Новосибирск, 31 мая, попробую замотивировать людей создавать сообщества.

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

Надеюсь, все не зря

https://15.codefest.ru/lecture/2831
7🔥4💘3👍1
Муса тоже топ, увидел его посты и решил позвать выступить на HolyJS, получился очень нескучный доклад про WebGPU, срывающий покровы.
💘1
Халява, ребятки, наконец-то. 💰

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

Выражаю мой конкретный респект моему куратору Александру Коротаеву — мужик конкретный, и посты у него классные 😘

Ну и всему программному комитету HolyJS, хоть они и посадили меня в самый маленький зал 😄

Посмотреть →
https://www.youtube.com/watch?v=sqkSrTq1Kos 🎥
Please open Telegram to view this post
VIEW IN TELEGRAM
💘5
This media is not supported in your browser
VIEW IN TELEGRAM
Фон для открывающей презентации SPB-Frontend

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

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

https://codepen.io/lekzd/pen/WbNVXzM
🔥163💘2👍1
История на миллион, о которой никто не знает

Всё началось в 2016 году, когда я сделал браузерную версию Героев 3 на JavaScript и выступил с докладом об этом проекте. Тогда для меня открылся совершенно новый мир — мир выступлений, конференций и поездок по разным странам.

В декабре 2024 года мне начали массово присылать ссылку на пост про новых Героев 3 в браузере. Пост разлетелся по пабликам как вихрь. Несмотря на просьбы автора упоминать его при цитировании, СМИ благополучно проигнорировали это. В самом посте был упомянут @caiiiycuk как разработчик браузерного порта. Не раздумывая ни секунды, я написал ему и предложил выступить с докладом на HolyJS. Он согласился — и я был этому безумно рад.

Мы созвонились, и он рассказал, что всё началось ещё 10 лет назад, когда он начал работать над портом DOSBox под браузер — js-dos. Так он создал полноценную среду для эмуляции DOS-игр в вебе. Позже он познакомился с игровым журналистом по прозвищу 54-й, который обожает старые игры и загорелся идеей находить их, портировать и выкладывать на сайт. Так, не торопясь, вдвоём они собрали более 2000 ретро-игр на https://dos.zone. Причём всё это — ни разу не встретившись вживую.

Весь март 2025 года мы вместе готовили презентацию (я выступал в роли ревьюера). Изначально рабочее название звучало как «Проблемы портирования игр через WASM», но со временем оно трансформировалось в более цепляющее — «Герои Меча и Магии 3 в браузере. Сложно или нет?». Мне очень хотелось продать этот труд по максимуму, и я убедил автора, что в названии стоит использовать самый громкий тайтл из трёх, которые фигурируют в презентации. К счастью, работать с Александром было одно удовольствие — материал получился и хардкорным, и нескучным одновременно.

И вот наступает день выступления — 8 апреля. В зале собираются слушатели. Александр — простой парень в очках — выходит на сцену в футболке, которую он специально напечатал для доклада. На ней — логотипы Героев 3, Вангеров и Периметра — тех самых игр, про портирование которых он расскажет. Техники подключают микрофон, проверяют всё в последний раз. Начинаем. Я оглядываюсь по залу и… ДА КАКОГО ЧЕРТА, ТУТ ВСЕГО ЛИШЬ ТРЕТЬ ЗАЛА??? Каждый раз, когда я сам рассказывал про Героев 3, залы были битком, люди стояли в дверях. Неужели все забыли?..

Так зачем я всё это рассказываю?

Потому что благодаря HolyJS, Александр впервые за много лет посетил Москву и встретился с 54-м вживую — вот так, спустя 10 лет совместной работы.
25🔥10💘5
This media is not supported in your browser
VIEW IN TELEGRAM
Славянский орнамент

Построил из примеров SDF фигур из статьи Индиго Квилеза: https://iquilezles.org/articles/distfunctions2d/

https://codepen.io/lekzd/pen/KwwKmNP
12😍4💘2
This media is not supported in your browser
VIEW IN TELEGRAM
Мою вчерашнюю работу повторили, но в 11 строчек кода 0_0

Ночью Иван Дианов, написал в Генклубе, мол привет, форкнул твою работу, а я глянул и ахнул, там всего 11 строчек кода на GLSL:

void main() {
vec2 uv = (gl_FragCoord.xy*2.-resolution.xy)/resolution.y;
uv=vec2(atan(uv.y,uv.x)/6.283*128.,(log(length(uv))-time)*20.);
uv.x+=32.*sin(time+floor(uv.y/16.));
uv=abs(mod(uv,16.)-8.);
uv=-abs(uv)+4.;
uv*=mat2(sin(vec4(11,0,0,33)+.785))*sqrt(2.);
float l=abs(uv.y-2.)-1.;
if(uv.y<uv.x)uv.yx=uv.xy;
gl_FragColor.r+=step(0.,min(abs(abs(uv.x)-2.)-1.,l));
gl_FragColor.a=1.;
}


Если у вас в голове только одна мысль: "Я что-то ничего в коде не понял", то у меня та же)

Я у себя в коде подбирал прямоугольники, двигал их, совмещал вместе, а Ваня нашел небольшой повтряющийся тайл и описал его алгоритмически только кодом.

https://codepen.io/illus0r/pen/LEEYrKm
🔥18💘6
This media is not supported in your browser
VIEW IN TELEGRAM
А вот и мой шейдер в реальной жизни

Код в этом посте
🔥165💘1
This media is not supported in your browser
VIEW IN TELEGRAM
Когда чтобы нарисовать кружок рисуешь прямую и скручиваешь холст

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

uv=vec2( 
atan(uv.y, uv.x),
log(length(uv))
);


1. atan(uv.y, uv.x)

Это двухаргументная версия арктангенса — atan2(y, x) — которая возвращает угол (в радианах) между положительным направлением оси X и вектором (x, y).
То есть это преобразует (uv.x, uv.y) в угол вокруг центра.
Например:
• Вектор (1, 0) даёт угол 0
• Вектор (0, 1) даёт угол π/2
• И так далее по кругу.

2. length(uv)

Это расстояние от точки (uv.x, uv.y) до центра (0,0), то есть радиус в полярной системе координат.

3. log(length(uv))

Логарифм от радиуса. Это сжимает координаты по радиальной оси — часто используется, чтобы создать “туннельный” эффект.

https://codepen.io/lekzd/pen/ogggajz
🔥5💯3😱21💘1
Словарик разработчика графики и почему все так

Примерно как i в циклах или "hello world" в демках, в графике очень много терминов, которые исторически сложились и без изменений копируются из одной кодовой базы в другую:

📍 Координаты и трансформации

UV — текстурные координаты (вместо XY).
Исторически пришло из 3D-графики, где XYZ — для пространства, а UV — для поверхности (в 2D).
ST — тоже текстурные координаты, часто в GLSL, когда UV уже занято 😆
modelViewMatrix / projectionMatrix — составные трансформации, поначалу путаются. Ctrl+C, Ctrl+V переменные, их стоит менять только для искривления пространства, если понимаешь что делаешь.

💡 Свет и материалы

• Diffuse — это рассеянный свет, то есть освещение, которое падает на поверхность и рассеивается во всех направлениях.
Specular — зеркальное отражение света (часто противопоставляется “diffuse”).
Phong / Blinn-Phong — модели освещения (названия от фамилий авторов) c бликами и рефлексами. Если на поверхности виден "блинчик" блика, то значит перед нами модель Блинна-Фонга 😏.
Lambert — простая модель рассеянного света.
Ambient — “фоновое” освещение (не привязанное к источнику).
FresnelЭффект Френеля, это когда по краям объекта, грани которого становятся почти параллельны взгляду сильно увеличивается отражения, создавая ореол в цвет окружения.
Albedo — отражательная способность материала (просто “цвет”, но физически корректный).
PBRPhysically Based Rendering, набор техник для более реалистичного рендеринга, использующая сразу несколько текстур для разметки карты бликов, объемов, отражений и прочих эффектов. В ААА играх он буквально везде.

🔧 Шейдеры и GLSL

Lerp(a, b, t) — Linear Interpolate — название из HLSL, в GLSL это mix(a, b, t). Путает, потому что названия разные в разных языках.
fragColor — переменная для выходного цвета фрагмента (в шейдере пикселей).
varying — переменные, передаваемые от вершинного шейдера к фрагментному (в GLSL 1.0).
attribute — данные на вершину (в GLSL 1.0); заменено на in в GLSL 3.0.
uniform — значения, одинаковые для всех вершин/фрагментов на вызов шейдера.
discard — команда в фрагментном шейдере, чтобы “выкинуть” пиксель.

🧠 Математика и алгоритмы

Euler — понятный способ представления вращения 3-мя осями как у гироскопа, прост для понимания, но при определенном повороте устраивает полную дичь
Quaternion — менее понятный способ представления вращения 4-мя осями, но исправляет глюки Эйлера.
Dot / Cross — скалярное и векторное произведение (звучит как операция с числами, но делает векторную магию).
Normal — вектор, перпендикулярный поверхности.

🧱 Моделирование и геометрия

BufferGeometry — сырая геометрия из массивов чисел (без удобных объектов).
Index / indices — способ “шарить” вершины между треугольниками.
Instancing — отрисовка множества копий одной геометрии с разными параметрами в один проход, как будто рисуется только 1 объект.
• Culling — техника отрезания невидимых плоскостей модели ради оптимизации, например если они чем-то перекрыты или не попадают в камеру
Frustum — усечеченная пирамида, модель которой используется для рассчетов попадания чего-либо в область камеры
Occlusion — это затемнение тех мест, куда свет плохо попадает, потому что они “спрятаны” от света другими частями геометрии. Так же называется AO и имеет разные подвиды, которые можно встретить в настройках графики в играх: RTAO, SSAO, HBAO или HDAO короче штука настолько важная для графона, что каждая крупная компания посчитала нужным изобрести свой алгоритм.
Render pass — это один “проход” рендера сцены. Визуально это как накладывание слоёв — ты рендеришь сцену несколько раз, каждый раз с разными эффектами.

Для тех кто осилил хотя бы прочитать названия, вот вам видео где реальные разработчики игр, очень пытаются говорить понятно, но слова из словарика выше у них регулярно проскакивают 😄, когда узнаешь эти термины слушать профессионалов становится куда приятнее https://www.youtube.com/watch?v=I-w-w5SoJok
10🔥6💘1
Сегодня у меня стало 200+ подписчиков в канале и 2 ребенка в семье

Было не до генарта сегодня, на какое-то время быть мной станет еще труднее)
🔥3520🎉10❤‍🔥5😱4💘2👏1