uk
Feedback
Математика в Gamedev по-простому

Математика в Gamedev по-простому

Відкрити в Telegram

Как на самом деле работают стрельба, толпа NPC, графика, физика тканей. Канал про то, что ИИ не заменит: понимание. Разборы на пальцах, рабочий код, интерактивы. dev-math.ru Сотрудничество: @it_bizdev

Показати більше
464
Підписники
+424 години
+77 днів
+4130 день

Триває завантаження даних...

Схожі канали
Немає даних
Виникли проблеми? Будь ласка, оновіть сторінку або зверніться до нашого support-менеджера.
Вхідні та вихідні згадування
---
---
---
---
---
---
Залучення підписників
липень '26
липень '26
+13
в 1 каналах
червень '26
+90
в 1 каналах
Get PRO
травень '26
+369
в 2 каналах
Get PRO
квітень '260
в 4 каналах
Get PRO
березень '26
+8
в 1 каналах
Дата
Залучення підписників
Згадування
Канали
11 липня0
10 липня+4
09 липня+1
08 липня+1
07 липня0
06 липня+2
05 липня0
04 липня0
03 липня+3
02 липня+2
01 липня0
Дописи каналу
Путь одного draw call Всю неделю мы считали, чем платим за кадр: в понедельник — командами, во вторник — байтами на шине, в с
Путь одного draw call Всю неделю мы считали, чем платим за кадр: в понедельник — командами, во вторник — байтами на шине, в среду — когерентностью варпов, в четверг — сменами состояния. Обещанная статья готова: «Путь одного draw call» — проходим дорогу команды рисования целиком, от строчки в вашем коде до пикселя на экране, со всеми четырьмя валютами на местах. В общем я довольно подробно описал разные части графического конвейера, и не как стандартную схему и так далее, а более практично в контексте движка. Читать: https://dev-math.ru/articles/drawcall/ #devmath #графика #математика #gpu #drawcall #оптимизация

2
Гонитесь за числом дроуколлов, а тормозит другое Допустим в оптимизации вы гонитесь за числом draw calls: объединяете меши, ч
Гонитесь за числом дроуколлов, а тормозит другое Допустим в оптимизации вы гонитесь за числом draw calls: объединяете меши, чистите объекты — и счётчик Batches ползёт вниз. Дело конечно хорошее. А кадр работает всё так же медленно, особенно на мобилке. Смотрите профайлер внимательнее: draw calls упали, а вторая цифра рядом, SetPass calls, — нет. Что это за цифра? Дело в том, что это две разные вещи. Batch (draw call) — это просто команда «нарисуй» на текущем состоянии. А SetPass случается, только когда состояние надо СМЕНИТЬ: другой шейдер, другая текстура, другой блендинг, другой Z-тест. Сто вызовов на одном материале — это один SetPass и куча дешёвых команд следом. А смена материала между вызовами — это новый SetPass: перенастройка конвейера, и в тяжёлом случае видеокарта сливает всё, что уже запустила, прежде чем переключиться. Это и есть флаш конвейера (pipeline flush). Собственно, вот тема дня: цену кадру набивает не сколько вы рисуете, а сколько раз между вызовами меняете стейт. Поэтому один материал со статик-батчингом летит — сотни мешей идут одним SetPass'ом; а десяток материалов вперемешку кладёт кадр, хотя вы не добавили ни полигона — вы добавили переключений контекста. Жёстче всего флаш на смене render target: у мобильных тайловых GPU это выгрузка целого тайла в память,. Техника дальше весьма логичная. Меньше разных материалов и шейдеров, свести похожее в один материал и атлас, сортировать по стейту, чтобы объекты с одним состоянием шли подряд. Батчинг, инстансинг и SRP Batcher по-разному делают одно и то же — держат стейт на месте, чтобы конвейер переставлять приходилось как можно реже. Подробнее разберу завтра. #devmath #графика #математика #gpu #батчинг #оптимизация
202
3
Обернул шейдер в if, чтобы считать реже. А быстрее не стало Вы нашли в шейдере тяжёлый кусок — дорогой цикл, лишний проход, в
Обернул шейдер в if, чтобы считать реже. А быстрее не стало Вы нашли в шейдере тяжёлый кусок — дорогой цикл, лишний проход, ветку с кучей математики — и обернули его в if: мол, для половины пикселей эту дорогую ветку пропустим и сэкономим. Пропустили. А кадр не разгрузился ни на сколько. Видеокарта прячет задержку памяти тем, что держит не один поток, а тысячи. Один встал на выборке из памяти — планировщик тут же пускает считать другой, у которого данные уже приехали; пока первый ждёт свою порцию, вычислители заняты чужой работой. Вот зачем на GPU тысячи потоков. Мало потоков— прятать нечем, и тогда видеокарта реально встаёт на сотни тактов ожидания. Но тут и зарыта плата. Одно ядро GPU — это не маленький процессор, а простая и небыстрая линия: ни хитрого предсказания ветвлений, ни глубоких кэшей, один поток на нём медленнее, чем на CPU. Сила — в количестве. И эти линии не независимы: они идут строем, группами (у NVIDIA — по 32), и вся группа исполняет одну и ту же инструкцию разом, каждая над своими данными. Это SIMT — одна команда, много потоков. Представьте не тысячу гонцов, у каждого свой маршрут, а колонну, марширующую в ногу: шаг у всех общий. Собственно, вот и разгадка вашего if. У этого есть имя — дивергенция ветвлений (branch divergence, ещё говорят «расхождение варпа»). Когда потоки одной группы на развилке расходятся, железу приходится прогнать обе ветки по очереди, отключая на каждой те линии, которых там нет. Группа идёт так же долго, как все пути её потоков вместе взятые. Ваш «пропустить дорогой код» экономит, только если его пропускает вся колонна разом. Один поток свернул в тяжёлую ветку — и остальные тридцать один стоят и ждут его. По сути, ветвления тут не под запретом — платите вы не за if, а за расхождение внутри группы. Противоположность расхождения — когерентность: это когда соседние потоки заняты одним и тем же, все сворачивают в одну сторону и шагают в ногу. Такая когерентная ветка почти бесплатна — вторая сторона просто не исполняется. Пример. Материал с enum-режимом и switch (_Mode) в шейдере (классический ubershader, куда свалили все варианты освещения). Если режим один на весь материал — uniform-параметр, — весь варп читает одно значение и идёт одной веткой, остальные просто не исполняются: расхождения нет, дёшево. Но стоит выбирать режим попиксельно — из маски материалов, material-ID в G-буфере, слоёв терреина — и соседние пиксели одного варпа уходят в разные ветки: на стыках материалов варп прогоняет все режимы по очереди. И та же боль в raymarching и SDF: часть лучей упирается в поверхность за пару шагов, часть марширует до предела — и вся группа топчется в цикле, пока не закончит самый глубокий луч. Ранний выход по одному лучу ничего не даёт: время группы держит самый медленный поток. В четверг — почему переключение шейдера или материала сбивает весь этот разгон: смена стейта и флаш конвейера, и чем тут спасают батчинг с инстансингом. #devmath #графика #математика #gpu #simt #оптимизация
222
4
Поговорим про шину Вы взяли ту же геометрию, тот же свет, те же материалы — просто заменили текстуры с 1K на 4K, чтобы было п
Поговорим про шину Вы взяли ту же геометрию, тот же свет, те же материалы — просто заменили текстуры с 1K на 4K, чтобы было почетче. Ни одной новой строки в шейдере. А fps просел, и на телефоне куда сильнее, чем на компе. Профайлер показывает знакомое: ядра GPU недогружены — видеокарта не считает, она ждёт. Ждёт данные. Дело в том, что у видеокарты две очень разные функции. Считать — умножать, складывать, гонять шейдерную арифметику — она умеет чудовищно быстро, тысячами потоков разом. А доставать данные из памяти — текстуру, вершины, буфер — заметно медленнее: байты лежат в видеопамяти далеко от вычислительных ядер, и их надо провезти по шине через кэши к тому месту, где над ними наконец сделают пару операций. Bandwidth (пропускная способность) — это сколько байт в секунду успевает проехать по этой дороге. Собственно, ключевое свойство: на современном GPU довезти байт до вычисления дороже, чем само вычисление сделать. 4K-текстура — это вчетверо больше пикселей по каждой стороне, то есть в шестнадцать раз больше байт, которые тащатся по той же шине через тот же кэш. Шейдер не поменялся, а данных, которые надо подвезти, стало в разы больше — и подвоз не поспевает. Вот почему безобидная замена текстур чего-то стоит, и не только текстур. Похожий механизм — дешёвый на вид полноэкранный эффект: блюр или bloom заняты не арифметикой, а выборкой текстур и чтением-записью целого кадрового буфера — и проходов таких много. На телефоне часто это буквально гоняет кадр во внешнюю память и обратно: та самая шина. По сути, у кадра две точки для ключевой оптимизации. Одна — сколько GPU может посчитать, другая — сколько данных можно провезти. Уперлись в первый — оптимизируйте шейдеры. Уперлись во второй — арифметику хоть в два раза ускорьте, быстрее не станет; лечить надо другое: мельче текстуры, мипмапы, сжатие, меньше проходов по полноэкранному буферу. Мипмапы, кстати, дают fps не только за счёт сглаживания — уменьшенная копия лежит в памяти компактно и попадает в кэш, а полноразмерная текстура на далёком объекте читается вразнобой и впустую гоняет данные по шине. А в пятницу в статье «Путь одного draw call» проследим всю дорогу команды — от вызова в коде через шину и стадии GPU до пикселя. #геймдев #графика #математика #gpu #bandwidth #оптимизация
228
5
Лоу-поли, а тормозит: кто съел ваш FPS? Поговорим о дроуколлах. А то про графику мы зашли сразу с дитеринга, давайте пойдёмся
Лоу-поли, а тормозит: кто съел ваш FPS? Поговорим о дроуколлах. А то про графику мы зашли сразу с дитеринга, давайте пойдёмся по базе. Так сказать с самого начала. Думаю за 2-3 месяца можно рассказать интересно о том, как рендер работает в современном мире в деталях. Собираете уровень из лоу-поли-пака: деревня, лес, заборы, камни — по паре сотен треугольников на модель. Геометрия копеечная, а кадр проседает. Открываете профайлер и видите странное: видеокарта простаивает, весь кадр съел процессор, а счётчик батчей в статистике рендера ушёл в тысячи. Та же история в другом костюме — клон Minecraft: мир из кубов по 12 треугольников, каждый куб — отдельный объект, и уже десяток чанков кладёт игру. Как так? Ведь треугольников мало и причем тут процессор? Процессор не рисует — он раздаёт команды. Draw call — это команда «нарисуй вот этот меш вот этим материалом», которую CPU через графический драйвер отправляет видеокарте. И перед каждой такой командой — бумажная работа: собрать состояние (какой шейдер, какие текстуры, какие буферы, как смешивать), драйвер всё это проверит, переведёт на язык GPU и положит в командный буфер. Только после этого видеокарта доберётся до треугольников. Собственно, ключевое свойство: цена этой бумажной работы от количества треугольников почти не зависит. Это как заказы в интернет-магазине: оформить один заказ на тысячу ручек — пара минут, оформить тысячу заказов по одной ручке — вечер. Товар тот же, вся разница — в накладных расходах на каждый заказ. Лоу-поли-пак экономит то, что и так ничего не стоит. Миллион треугольников одним вызовом GPU прожуёт легче, чем деревню из тысячи заборов — тысячей вызовов. Поэтому важно следить за числом дроуколлов. Статья этой недели «Путь одного draw call»: пройдём всю дорогу команды от вызова в коде до пикселей на экране. #геймдев #графика #математика #gpu #drawcall #оптимизация
234
6
Дизеринг и гамма-коррекция: почему градиенты «бандятся» и откуда грязь в тёмных сценах https://dev-math.ru/articles/dithering
Дизеринг и гамма-коррекция: почему градиенты «бандятся» и откуда грязь в тёмных сценах https://dev-math.ru/articles/dithering/ Люблю писать такие статьи. Когда я начинал заниматься что графикой, что трекингом, меня очень часто больше всего увлекало на сколько это мир физических ограничений. Нюансы вывода изображения на экран. Нюансы человеческого зрения и тому подобное. Параллельно изучая такие технические моменты ещё и узнаешь, а как что в этом мире работает. И это то, чем меня увлекла когда-то клиентская разработка в отличии от бекенда. Помимо мнгновенного результата действий, то что ты не живешь в чистой абстракции, а сталкиваешься с нюансами практического мира. Итак. Мы разбирали по кускам тему всю неделю. Теперь полная статья с разбором, интерактивами и так далее. Бандинг, дизеринг, как работает гамма-коррекция, что такое линейное цветовое пространство и зачем оно надо (да и попутно объясняется зачем была нужна гамма). На сайте произошел большой редизайн. Светлая тема мне нравится наверное чуть больше. Но в основном так как я решил делать игру во вселенной своих комиксов и рилсов, и позже анонс будет размещён на сайте по игре (думаю я управлюсь за 4 месяца ну или хотя бы постараюсь). А так репосты и 🔥 как всегда приветствуются. Это мотивирует писать статьи и дальше. Ведь кому-то это интересно. #devmath #графика #квантование #дизеринг #sRGB #linearworkflow
977
7
Среднее двух цветов темнее, чем должно быть Наложите полупрозрачный туман на сцену или сожмите текстуру в мип — и по краям, н
Среднее двух цветов темнее, чем должно быть Наложите полупрозрачный туман на сцену или сожмите текстуру в мип — и по краям, на контрастных границах, поползёт грязная тёмная окантовка. Те же тёмные ореолы вылезают на швах освещения. Картинка будто пачкается сама. Причина — в том, что почти всё считается прямо в sRGB-кодированных числах. Движок, старый шейдер, да и Photoshop по умолчанию берут два пикселя и усредняют их значения. Но значение — это точка на гамма-кривой, а не количество света. Среднее двух значений не равно значению средней яркости — оно всегда уезжает в тёмное. Отсюда тёмные каймы при альфа-блендинге, мутные швы на мипмапах и даунсэмпле, грязь на краях после сглаживания. Свет складывается линейно — фотоны просто суммируются. Значит, и считать цвет надо в линейном. Линейный workflow (linear space) — это decode → математика → encode: раскодировал sRGB в линейное, сложил-перемножил-осветил, и только на выводе закодировал обратно в sRGB. Тогда каймы исчезают, а 50% серого — это и правда половина света. В Unity это галочка Color Space → Linear. И тут важное: линейный режим — не «без гаммы». Гамма остаётся на хранении текстур и на выводе кадра, линейной делается только математика между ними. Гамма и линейное не спорят — это две стадии одного конвейера. И сюда же стыкуется дизер из вторника: разбивать полосы шумом нужно тоже в правильном месте конвейера — на финальном кодировании в 8 бит, иначе зерно ляжет криво. #геймдев #графика #математика #linearworkflow #гамма #шейдеры
329
8
В тёмных сценах кончаются биты — отсюда и грязь Глаз устроен нелинейно. Разницу между почти-чёрным и чуть-светлее он видит ре
В тёмных сценах кончаются биты — отсюда и грязь Глаз устроен нелинейно. Разницу между почти-чёрным и чуть-светлее он видит резко; такую же разницу в ярких цветах почти не замечает — это Вебер–Фехнер. Если раскидать 256 уровней равномерно по яркости, в тенях шаг окажется слишком крупным, и глаз увидит банды, а в ярких участках будет с избытком, и они пропадут зря. Поэтому яркость хранят не линейно. Гамма-коррекция (gamma) — это степенная кривая, по которой кодируют цвет: она отдаёт больше тёмному, где глаз придирчив, и меньше светлому. Стандарт — sRGB, кривая порядка 2.2. Те же 8 бит растягиваются под восприятие, и 256 уровней хватает на гладкую тень. Приём умный. А «грязь в тенях» — что это физически? Две вещи разом. Первая — банды: даже с гаммой 8 бит в глубоких тенях не хватает, на тёмное приходится горстка бит, и оно идёт ступеньками. Глаз ловит это именно в темноте — в полумраке зрачок раскрывается, и к перепадам в тенях зрение придирчивее всего. Вторая — муть: если считать свет в неправильном пространстве, тёмные тона разъезжаются по оттенку и грязнятся. В пятницу — что значит «считать в линейном, а кодировать в sRGB», и почему это меняет всё. #геймдев #графика #математика #гамма #sRGB #linearworkflow
320
9
Чтобы убрать полосы, в картинку нарочно подмешивают шум Идея дизеринга обратная интуиции. Дизеринг (dithering) — это точно от
Чтобы убрать полосы, в картинку нарочно подмешивают шум Идея дизеринга обратная интуиции. Дизеринг (dithering) — это точно отмеренный шум, который подмешивают к цвету перед тем, как округлить его до ближайшей из 256 ступенек. Там, где раньше длинный участок ложился на одну ступеньку, теперь часть пикселей перескакивает на соседнюю — вперемешку. Вместо плоской полосы со швом — мелкая крупа из двух уровней. Глаз усредняет её обратно в плавный переход, которого в битах уже нет. Но шум шуму рознь. Закинуть Random.Range — белый шум — и картинка реально станет грязной: зерно лезет в глаза. Ordered-дизер (матрица Байера) дёшев, но оставляет регулярную сетку-крест. А синий шум (blue noise) и распространение ошибки (Флойд–Стейнберг) кладут зерно так, что глаз его почти не вычленяет: энергия шума уходит в высокие частоты, к которым зрение нечувствительно. Поэтому современный движок дизерит синим шумом. И это не только про градиенты. Тот же приём — dither-fade: пунктирная прозрачность для плавного LOD-перехода, волос, волюметрики, мягких теней, и вывод 10-битного кадра в 8 бит без полос. В пятницу разложим, какой дизер куда и почему синий шум победил. #геймдев #графика #математика #дизеринг #bluenoise #шейдеры
304
10
Художник рисует гладкое небо, а разработчик видит полосы Дейв вывел в свой мир закатное небо — мягкий переход от оранжевого к
Художник рисует гладкое небо, а разработчик видит полосы Дейв вывел в свой мир закатное небо — мягкий переход от оранжевого к синему. А на мониторе по небу пошли полосы. Картинку он не трогал. Поменялось только то, как её упаковали в биты. Разберём, что это. Откройте любой редактор, залейте плавным градиентом от чёрного к серому, растяните на весь экран. Гладко? Кажется, что да. Но на больших плавных площадях или при импорте глаз вдруг ловит вертикальные полосы. Откуда они, если в текстуре непрерывный переход? Дело в том, что цвет в кадре хранят побайтно: 8 бит на канал — это 2⁸ = 256 уровней яркости, и между соседними нет ничего, и это без сжатия. Непрерывный градиент квантуется: длинный плавный участок ложится на одну и ту же ступеньку, потом резко прыгает на следующую. Получаются плоские полосы постоянного цвета со швом между ними. Это и есть бандинг (banding) — видимые ступени-полосы на месте плавного градиента, когда уровней яркости не хватает на гладкий переход. И тут подключается зрение. На границе двух почти одинаковых тонов оно само добавляет контраст — это полосы Маха, эффект латерального торможения в сетчатке. Разница между ступеньками 1/255, физически почти ноль, а кайму по шву вы видите ясно. Глаз не меряет яркость абсолютно, он меряет перепады (закон Вебера) — и ровно на швах квантования перепад вылезает. В пятницу — почему именно 8 бит, и три способа убрать полосы. #геймдев #графика #математика #бандинг #квантование #гамма
290
11
Самая загадочная строчка кода https://youtube.com/shorts/m55BTiN-AJc?si=Xgf80LrTeeqmQthv В коде Quake III есть строчка, а рядом — // what the fuck?. Кто её написал, спорят до сих пор. Чтобы свет в шутере считался правильно, направление каждого луча надо нормировать — поделить на длину, а это корень. Тысячи делений на корень за кадр, и на железе конца девяностых не тянуло. Кто-то срезал эту дорогую операцию магическим числом 0x5F3759DF и сдвигом битов. Вся красота в одной идее: биты дробного числа — это почти его логарифм. Поэтому обратный корень считается почти даром — пара действий над битами и один шаг Ньютона на уточнение. Невидимая математика, которая держала фпс в норме. Автора так и не нашли. Не Кармак — следы ведут к Гэри Таролли и Грегу Уолшу, но в самой id Software не признался никто.
280
12
Как вам новые форматы?
298
13
Дейв теперь в Рилсах https://www.instagram.com/reel/DaFostRIAxo/?igsh=OXd4cnM0b2x5cGFx В сторис я выложу видос, но телега жрет качество, так что советую глянуть в инсте. Я продумал, на мой взгляд, довольно интересный научнопопулярный формат видео, с роликами о прикольных вещах и парадоксах в математике + забавных историй. Как раз самое то для инсты. Быстро, ненапряжно и легко потреблять. Первый рилс про парадокс Симпсона. Если вдруг не знаете забавную историю про Беркли в 1973 году. Советую глянуть 🙂 #парадоксСимпсона #статистика #данные
305
14
Неделя 1: четыре дыры зашиты — а карты целиком нет Дейв догонял Хардкода и рефакторил его костыли один за другим: почему чисе+3
Неделя 1: четыре дыры зашиты — а карты целиком нет Дейв догонял Хардкода и рефакторил его костыли один за другим: почему чисел именно три (это про глаз, а не про цвет), почему камни-близнецы разъезжаются под другой лампой, почему тонкая плёнка глитчит и как свернуть её аналитически, почему дисперсию не подделать сдвигом RGB-каналов. RGB — это техника со своей областью применимости, и Дейв теперь видит, где она кончается. Но Хардкод сбежал в трещину, а Статика только набрала силу: честного эталона у него пока нет. На следующей неделе: — небо: трюк, ставший формулой, — тут RGB честнее некуда; — флуоресценция: то, чего три числа не умеют в принципе; — каустики с дисперсией: два фейка сталкиваются; — финал: спектральный эталон против RGB — и сколько правда стоит в миллисекундах.
382
15
О цвете в играх по-простому https://dev-math.ru/articles/rgb-tricks/ Как и планировалось в пятницу новый формат. Всю пугающую
О цвете в играх по-простому https://dev-math.ru/articles/rgb-tricks/ Как и планировалось в пятницу новый формат. Всю пугающую математику свернул в спойлеры, чтобы текст читался проще. Без спойлеров получается научно-популярный текст. В спойлерах детали. Всю неделю в канале мы разбирали, где RGB обманывает — началось с того, что Дейв нашёл два самоцвета: под одной лампой близнецы, под другой — разного цвета. Камни те же, поменялся только свет. Чтож, теперь всё собрано в одну статью, и её можно не только прочитать, но и покрутить руками. По сути, RGB — это не то, как устроен свет. Это то, как устроен ваш глаз: три типа колбочек сворачивают весь спектр в три числа. Для картинки на экране этого почти всегда хватает. Для физики света — уже нет. В статье — четыре места, где трёх чисел перестаёт хватать: — метамерия — два разных спектра дают один цвет, пока не сменишь лампу; — обратная задача — как вернуть спектр из трёх чисел и почему решений бесконечно много; — тонкие плёнки — переливы мыльного пузыря и бензина на луже; та самая иридесценция, что в Unity HDRP уже лежит галочкой; — дисперсия — «огонь» бриллианта, который дешёвый фейк не вытягивает на крупном плане. И всё это — четыре живые 3D-сцены прямо в браузере: переливающаяся плёнка, бриллиант, рассыпающий спектр по граням, метамерные свотчи под разными лампами. Зачем это вам? В реалтайме вы всё равно фейкаете — вопрос только в том, насколько качественно. А понимание того, как цвет устроен на самом деле, как раз и подсказывает, как фейкать правильно: что важно сохранить, а чем можно пренебречь. Не забываем делиться статьёй и ставить 🔥— это помогает развитию канала и моей мотивации писать дальше :) #геймдев #графика #математика #цвет #дисперсия #призма #шейдеры#геймдев #графика #математика #цвет #RGB #иридесценция #дисперсия
336
16
Перезапуск White Label Games https://whitelabelgames.ru/ Сделал полный редизайн, конструктор с ценами, написал нормальные статьи и разобрал простенький кейс. Весьма низкобюджетный, но зато живой 🙂 Как появятся бюджеты отредактирую в крупобюджетный. Конечно остался ряд правок, которые я ещё внесу в течении недели, но результат мне в общем нравится. С тем сколько крутых проектов я сделал выглядит думаю эффектно. И это часть ещё за NDA. #оработе
4
17
«Огонь» бриллианта — это не блеск камня Вы наверняка видели, как бриллиант в кадре вдруг рассыпает спектр по граням. И почти
«Огонь» бриллианта — это не блеск камня Вы наверняка видели, как бриллиант в кадре вдруг рассыпает спектр по граням. И почти наверняка — хроматическую аберрацию по краям картинки: красный уехал в одну сторону, синий в другую. Выглядит дорого. На деле — почти бесплатно. Трюк индустрии простой. Берём текстуру и сэмплируем три раза со смещением: R чуть туда, B чуть сюда, G посередине, радиально от центра кадра — вот вам «линза камеры». Либо три луча под тремя фиксированными углами, по одному на канал. Дёшево, один проход, и в массе сцен глаз считывает это как оптику объектива и не сверяет с физикой. Так что приём работает — почти всегда. Почти. Ломается на крупном плане огранённого прозрачного объекта: бриллиант, призма, стопка стекла, магический кристалл — всё, где луч гуляет внутри. Камень переотражается несколько раз (полное внутреннее отражение), и спектр должен размазываться на КАЖДОМ преломлении. А фейк разделил каналы один раз — и тащит это разделение неизменным. Накопления нет, спектр выходит плоским и не зависит от геометрии огранки. Тут глаз ловит подделку мгновенно. Где это вылезает в играх? Хром. аберрация постом по краям кадра, лёгкий спектр на гранях дальнего самоцвета — никто не идёт сверять это с физикой, и трюка хватает. Сыпется он там, где сошлись крупный план И множественные преломления: hero-камень в инвентаре, бриллиант в кат-сцене, тот самый сюжетный макгаффин-кристалл. Если «огонь» камня не пляшет по огранке, а едет вместе с экраном — это он и выдал себя. Глубже — то, что сдвиг каналов выкинул: дисперсия живёт не в пикселе, а на пути луча. Показатель преломления зависит от длины волны — n(λ). Синий преломляется сильнее красного, угол по закону Снелла свой для каждой λ, поэтому спектр и веерится. Но только когда трассируешь сам путь, а не двигаешь каналы в экранном пространстве. В пятницу разберём руками: фейковый сдвиг каналов против честного λ-raymarch на одном бриллианте. С формулами и демкой, где режимы переключаются вживую. #геймдев #графика #математика #цвет #дисперсия #призма #шейдеры
309
18
Радуга без единой краски Мыльный пузырь, лужа бензина, синяя побежалость на нагретой стали — переливаются всеми цветами, хотя
Радуга без единой краски Мыльный пузырь, лужа бензина, синяя побежалость на нагретой стали — переливаются всеми цветами, хотя пигмента в них ноль. Это тонкая плёнка толщиной с длину волны: свет отражается от верхней и нижней границы, волны складываются и гасятся. Чистая интерференция. В играх вы это видите чаще, чем думаете: перламутр автокраски, надкрылья жуков, та самая побежалость, бензин в луже, любая «не от мира сего» sci-fi-поверхность. И в Unity HDRP это уже готовая галочка — Iridescence. Сколько длин волн надо посчитать на пиксель? В лоб — десятки: отражение плёнки бешено осциллирует по спектру. А у вас три числа. И вот трюк, который почти честный (Belcour & Barla, 2017): дрожащий спектр не семплируют — его аналитически сворачивают сразу в RGB, в замкнутом виде. Мало того, авторы доказали: для диэлектрической плёнки (пузырь, масло) результат совпадает с честным спектральным расчётом. Не «похоже» — совпадает. Редкий случай, когда упрощение почти не врёт. Почти. Спотыкается он на металлах. У меди показатель преломления резко пляшет по спектру, и предынтеграл начинает мазать: оттенок и насыщенность уезжают. В пятницу — почему плёнка вообще осциллирует, как её сворачивают в три числа и где щёлкает медь. С интерактивным side-by-side. #геймдев #графика #математика #цвет #иридесценция #шейдеры
318
19
Обратная задача: вернуть спектр из трёх чисел Вчера я рассказал как глаз сворачивает спектр в три числа — и вышло, что у одно
Обратная задача: вернуть спектр из трёх чисел Вчера я рассказал как глаз сворачивает спектр в три числа — и вышло, что у одного цвета таких спектров бесконечно много. Сегодня идём в обратную сторону: из трёх чисел собрать спектр. Вот тут и начинается боль. Художник красит текстуру в RGB. Никакого спектра на входе нет и не было — так устроена вся индустрия, и это удобно: текстура весит как три канала, а не как десятки чисел на пиксель, инструменты привычные. Умно? Да. Ровно до момента, когда движку нужно посчитать что-то спектральное — дисперсию, цвет под цветным светом, тонкую плёнку. Там на пиксель нужен спектр, а у вас три числа. Развернуть три числа обратно в спектр — задача недоопределённая. Та же вчерашняя метамерия, только смотрим с другого конца: одному RGB отвечает бесконечно много спектров, и какой из них «настоящий» — узнать неоткуда. Поэтому задачу не решают, а обходят. Spectral upsampling: по RGB достраивают один правдоподобный спектр — гладкий и физичный (значения в [0,1], без резких пиков), просто чтобы было что отдать в расчёт. Методов хватает: Smits — наивная отправная точка, Meng и Jakob & Hanika — рабочие (последний стоит по умолчанию в PBRT и Mitsuba), а Belcour вообще выдаёт целое семейство спектров под один цвет. Нужно это далеко не везде. В реалтайме трёх чисел хватает, гнать каждый пиксель в спектр незачем. А вот когда RGB-текстура попадает в физичный расчёт — офлайн-рендер, product-viz, конфигуратор авто, где перламутр должен честно играть под разным светом, — недоопределённость и вылезает. Правильного ответа среди метамеров нет, так что каждый рендерер выбирает свой. #геймдев #графика #математика #цвет #спектр
331
20
RGB — это не свойство света. Это свойство вашего глаза Вчера Дейв поймал это на двух самоцветах: под факелом — близнецы, под
RGB — это не свойство света. Это свойство вашего глаза Вчера Дейв поймал это на двух самоцветах: под факелом — близнецы, под другой лампой — разного цвета. Камни не менялись. Менялся только свет. Разберём, что это было. Откройте color пикер: три ползунка R, G, B — и любой оттенок. Кажется, что цвет так и устроен — три числа. Да? Конечно же нет. Три числа — это про ваш глаз, а не про мир. В сетчатке три типа колбочек (L, M, S), и каждая сворачивает весь спектр света в одно число — берёт интеграл спектра по своей кривой чувствительности. На входе непрерывный спектр, на выходе три отклика. Глаз сжимает свет до трёх чисел. RGB — просто базис поверх этого сжатия: умное упрощение, а не «реальность». В примере с камнями. Два РАЗНЫХ спектра под одной лампой дают одинаковые три отклика и выглядят одинаково. Сменили лампу — отклики разошлись, и цвет за ними. Это метамерия: совпал цвет ≠ совпал спектр. Важно понимать что дает эти три числа: цвет это не точка, а целый спектр, свёрнутый глазом в три отклика. У одной «тройки» бесконечно много спектров-прообразов. При чём тут ваши игры? Бытовая версия «цвет — не три числа» — это color management: линейка vs sRGB, гамут, тонмаппинг, HDR. Ассет, выверенный под один свет, «уезжает» под другим — близкая родня метамерии. RGB при этом остаётся нормальным базисом для большинства игр; смысл не «отказаться», а знать, как всё устроено на самом деле. Что мы и разберем. Как устроен цвет, зачем в играх нужен спектральный рендер, как рендерить красивые самоцветы и другие подводные данной темы камни. #геймдев #графика #математика #цвет #RGB #метамерия
302