Про отражения в Duke Nukem
https://youtube.com/shorts/2yb0Pn-n94k?si=I6mKOw7dFLzbh3xX
В зеркале Duke Nukem 3D — не отражение, а построенная за стеной вторая комната.
Движок 96-го не умел в отражения: за зеркалом просто копировали комнату целиком, и твой двойник вставал по ту сторону вживую, кадр за кадром.
#devmath #gamedev #dukenukem #рендеринг #математикавиграх
https://youtube.com/shorts/2yb0Pn-n94k?si=I6mKOw7dFLzbh3xX
В зеркале Duke Nukem 3D — не отражение, а построенная за стеной вторая комната.
Движок 96-го не умел в отражения: за зеркалом просто копировали комнату целиком, и твой двойник вставал по ту сторону вживую, кадр за кадром.
#devmath #gamedev #dukenukem #рендеринг #математикавиграх
YouTube
Про отражения в Duke Nukem
В зеркале Duke Nukem 3D — не отражение, а построенная за стеной вто...
🔥4
Почему далекие поверхности мерцают?
Проблема: две далёкие поверхности — стена и налепленный на неё декаль, земля и дорога — начинают дрожать и «драться за пиксель», стоит чуть двинуть камеру. Первое желание — лезть в материалы, сортировку, освещение. А чинится это обычно в настройках камеры.
Виновник — ближняя плоскость near, выставленная слишком близко к нулю. Классика: near = 0.01, чтобы близкое не обрезалось, и far = 1000, чтобы видно было далеко. Выглядит безобидно. Но точность буфера глубины распределена не поровну. При near = 0.01 и far = 1000 у дальней плоскости соседние значения глубины (в типичном 24-битном буфере) ошибаются почти на 6 единиц — всё, что ближе ~6 единиц друг к другу, буфер там уже не различает. Отсюда мерцание.
И вот что неочевидно: далёкую точность рушит именно ближняя плоскость. Сдвиньте near с 0.01 до 1 при том же far — и различимость глубины вдали улучшится примерно в сто раз. Даже 0.01 → 0.1 даёт ×10. Решает не разность far − near, а их отношение far/near: чем оно больше, тем хуже вдали, а главный рычаг — не тянуть near к нулю.
Практический вывод, который снимает целый класс мерцания: держите near настолько далеко, насколько терпит сцена, а far — настолько близко, насколько можно. Чем у́же диапазон, тем чище глубина. Прежде чем крутить материалы — проверьте эти два числа.
А почему точность вообще нелинейна — это прямое следствие проекции и деления на w. Разберём в пятницу: в статье будет интерактив, где видно кривую глубины и что с ней делает ползунок near.
#геймдев #графика #математика #zfighting #рендер #камера
Проблема: две далёкие поверхности — стена и налепленный на неё декаль, земля и дорога — начинают дрожать и «драться за пиксель», стоит чуть двинуть камеру. Первое желание — лезть в материалы, сортировку, освещение. А чинится это обычно в настройках камеры.
Виновник — ближняя плоскость near, выставленная слишком близко к нулю. Классика: near = 0.01, чтобы близкое не обрезалось, и far = 1000, чтобы видно было далеко. Выглядит безобидно. Но точность буфера глубины распределена не поровну. При near = 0.01 и far = 1000 у дальней плоскости соседние значения глубины (в типичном 24-битном буфере) ошибаются почти на 6 единиц — всё, что ближе ~6 единиц друг к другу, буфер там уже не различает. Отсюда мерцание.
И вот что неочевидно: далёкую точность рушит именно ближняя плоскость. Сдвиньте near с 0.01 до 1 при том же far — и различимость глубины вдали улучшится примерно в сто раз. Даже 0.01 → 0.1 даёт ×10. Решает не разность far − near, а их отношение far/near: чем оно больше, тем хуже вдали, а главный рычаг — не тянуть near к нулю.
Практический вывод, который снимает целый класс мерцания: держите near настолько далеко, насколько терпит сцена, а far — настолько близко, насколько можно. Чем у́же диапазон, тем чище глубина. Прежде чем крутить материалы — проверьте эти два числа.
А почему точность вообще нелинейна — это прямое следствие проекции и деления на w. Разберём в пятницу: в статье будет интерактив, где видно кривую глубины и что с ней делает ползунок near.
#геймдев #графика #математика #zfighting #рендер #камера
🔥17
Где на экране этот треугольник
https://dev-math.ru/articles/spaces/
Всю неделю я рассказывал о том где именно находится вершина. Что камеру в 3D на самом деле не двигают — двигается весь мир вокруг неё. Что далёкие поверхности мерцают не из-за материалов, а из-за near, прижатого к нулю. Обещанная статья готова: проходим дорогу одной вершины целиком — от строчки в вашем коде до конкретного пикселя на экране.
Плюс разбор, почему отметка Static и статик-батчинг в Unity вообще не спорят с «мир едет навстречу камере».
Да, если серия нравится, и статья интересна. Делимся ей с друзями и ставим 🔥. А то я что, не блогер, это не сказать.
#devmath #графика #математика #3d #mvp #проекция
https://dev-math.ru/articles/spaces/
Всю неделю я рассказывал о том где именно находится вершина. Что камеру в 3D на самом деле не двигают — двигается весь мир вокруг неё. Что далёкие поверхности мерцают не из-за материалов, а из-за near, прижатого к нулю. Обещанная статья готова: проходим дорогу одной вершины целиком — от строчки в вашем коде до конкретного пикселя на экране.
Плюс разбор, почему отметка Static и статик-батчинг в Unity вообще не спорят с «мир едет навстречу камере».
Да, если серия нравится, и статья интересна. Делимся ей с друзями и ставим 🔥. А то я что, не блогер, это не сказать.
#devmath #графика #математика #3d #mvp #проекция
🔥14
Квиз: Как игры рисуют кадр?
https://youtube.com/shorts/F6enWvT6lQk?si=pXOCdl87qk5F6BiC
А что вы думали? Статьи просто так? А ну взяли ручки и проходим контрольную. По статье по дроуколлам и пространствам.
Собрал небольшой видео-квиз. Такие штуки вообще проходить полезно, так как информация лучше запоминается, когда с ней сталкиваешься несколько раз в разных контекстах. Хотя мы пока разбираем только базу.
#геймдев #игры #графика #квиз #devmath
https://youtube.com/shorts/F6enWvT6lQk?si=pXOCdl87qk5F6BiC
А что вы думали? Статьи просто так? А ну взяли ручки и проходим контрольную. По статье по дроуколлам и пространствам.
Собрал небольшой видео-квиз. Такие штуки вообще проходить полезно, так как информация лучше запоминается, когда с ней сталкиваешься несколько раз в разных контекстах. Хотя мы пока разбираем только базу.
#геймдев #игры #графика #квиз #devmath
🔥5
Как вы получаете пиксель
Далёкие провода ЛЭП, перила моста, ванты, тонкая антенна на крыше — вроде на месте, но стоит чуть повести камерой, и линия начинает рваться: тут кусок есть, тут его нет, и всё это дрожит. Первое объяснение, которое приходит в голову: «ну, деталь мельче пикселя, разрешения не хватает». Оно почти верное, но только почти.
Растеризатор (узел, который превращает три вершины в закрашенные пиксели) не считает, какую долю пикселя накрыл треугольник. Для него пиксель — вообще не маленький квадратик, который можно зацепить краем. Пиксель — это одна точка в его центре. И треугольник закрашивает пиксель тогда и только тогда, когда накрывает эту точку. Так записано в правилах растеризации Direct3D, так же ведут себя OpenGL и Vulkan.
Собственно, отсюда и мерцание. Он не «слишком маленький» — он проходит между центрами пикселей. Камера сдвинулась на полпикселя: где-то центры попали внутрь, где-то нет — по линии побежали мерцающие дырки.
Вывод: тонкую геометрию не чинят геометрией. Добавить проводу полигонов бесполезно — толще в экранных пикселях он от этого не станет. Работает другое: держать деталь шириной хотя бы в пиксель на экране (билборд или шейдер, который не даёт ширине упасть ниже пикселя), брать несколько точек покрытия на пиксель (MSAA), либо увести деталь из геометрии в текстуру, где у неё есть альфа и фильтрация. Если у вас мерцают перила — разговор не про меш, а про то, чем вы их рисуете.
Ну и крайний случай: треугольник может не нарисоваться совсем. Мелкий треугольник или длинный тонкий слайвер проскакивает в зазоре между центрами и не даёт в этом кадре ни одного фрагмента, хотя площадь у него есть и вершины на месте. Сдвинулись на полпикселя — даёт. Для геометрии размером около пикселя вопрос «виден или нет» решает субпиксельная позиция.
И из того же правила растёт вопрос, о котором обычно не думают. А если точка-сэмпл легла ровно на ребро, общее у двух соседних треугольников меша? Закрасить у обоих — по шву пройдёт двойная краска, на прозрачности это заметный тёмный рубец. Не закрасить ни у кого — по мешу побежит строчка дырок. Железо этот случай разруливает, и разруливает одинаково у всех.
Как именно растеризатор решает «внутри или снаружи», как он поступает с сэмплом на общем ребре и кто из тысячи треугольников, попавших в один пиксель, остаётся на экране — разберём в пятницу.
#devmath #графика #математика #рендер #растеризация #gamedev
Далёкие провода ЛЭП, перила моста, ванты, тонкая антенна на крыше — вроде на месте, но стоит чуть повести камерой, и линия начинает рваться: тут кусок есть, тут его нет, и всё это дрожит. Первое объяснение, которое приходит в голову: «ну, деталь мельче пикселя, разрешения не хватает». Оно почти верное, но только почти.
Растеризатор (узел, который превращает три вершины в закрашенные пиксели) не считает, какую долю пикселя накрыл треугольник. Для него пиксель — вообще не маленький квадратик, который можно зацепить краем. Пиксель — это одна точка в его центре. И треугольник закрашивает пиксель тогда и только тогда, когда накрывает эту точку. Так записано в правилах растеризации Direct3D, так же ведут себя OpenGL и Vulkan.
Собственно, отсюда и мерцание. Он не «слишком маленький» — он проходит между центрами пикселей. Камера сдвинулась на полпикселя: где-то центры попали внутрь, где-то нет — по линии побежали мерцающие дырки.
Вывод: тонкую геометрию не чинят геометрией. Добавить проводу полигонов бесполезно — толще в экранных пикселях он от этого не станет. Работает другое: держать деталь шириной хотя бы в пиксель на экране (билборд или шейдер, который не даёт ширине упасть ниже пикселя), брать несколько точек покрытия на пиксель (MSAA), либо увести деталь из геометрии в текстуру, где у неё есть альфа и фильтрация. Если у вас мерцают перила — разговор не про меш, а про то, чем вы их рисуете.
Ну и крайний случай: треугольник может не нарисоваться совсем. Мелкий треугольник или длинный тонкий слайвер проскакивает в зазоре между центрами и не даёт в этом кадре ни одного фрагмента, хотя площадь у него есть и вершины на месте. Сдвинулись на полпикселя — даёт. Для геометрии размером около пикселя вопрос «виден или нет» решает субпиксельная позиция.
И из того же правила растёт вопрос, о котором обычно не думают. А если точка-сэмпл легла ровно на ребро, общее у двух соседних треугольников меша? Закрасить у обоих — по шву пройдёт двойная краска, на прозрачности это заметный тёмный рубец. Не закрасить ни у кого — по мешу побежит строчка дырок. Железо этот случай разруливает, и разруливает одинаково у всех.
Как именно растеризатор решает «внутри или снаружи», как он поступает с сэмплом на общем ребре и кто из тысячи треугольников, попавших в один пиксель, остаётся на экране — разберём в пятницу.
#devmath #графика #математика #рендер #растеризация #gamedev
🔥5
Поговорим про Overdraw
Сложная сцена проседает по fps. Первым делом вы идёте резать полигоны: упрощаете меши, расставляете LOD'ы, чистите вершины. Треугольников стало заметно меньше — а кадр не полегчал. Профайлер показывает, что видеокарта всё время сидит в пиксельном шейдере, а не в геометрии.
Дело в том, что один пиксель за кадр закрашивается не по разу. Поставьте три объекта друг за другом по глубине: дальше всех стена, перед ней ящик, перед ящиком стойка. Рисуются они в том порядке, в каком их отдал движок, — и если дальняя стена попадёт под кисть первой, она закрасит свои пиксели и целиком отработает шейдер: текстуры, свет, туман. Потом поверх ляжет ящик — и тоже целиком. Потом стойка. На экране виден только ближний слой, а пиксельный шейдер отработал по числу слоёв. Это и есть overdraw — работа, оплаченная за пиксели, которые в итоге никто не увидит.
Плотный интерьер, свалка пропов, наслоённые полупрозрачные эффекты — там overdraw набегает быстро. Горит fillrate. Fillrate (филлрейт) — это скорость, с которой видеокарта заливает пиксели в буфер кадра: её пропускная способность на закраску, отдельная от пропускной способности на геометрию.
Поймать довольно просто. Подведите камеру вплотную к скоплению объектов: если fps проседает там, где в кадр влезает даже меньше геометрии, но она плотно перекрывается по глубине, — вы уперлись в overdraw, а не в треугольники. А ещё лучше — включите режим overdraw: он есть у Unity, Unreal и мобильных профайлеров. Места, перекрашенные много раз, светятся всё ярче. Это буквально ваш счёт за кадр, нарисованный поверх сцены, — один раз увидев его, вы перестаёте гоняться за полигонами.
Видеокарта умеет выбрасывать перекрытые пиксели ещё ДО того, как посчитает их шейдер. Но у этого механизма есть условие, и когда объекты рисуются «как легли в сцене», условие не выполняется — и каждый невидимый слой всё равно оплачен. Что это за условие и что делать, когда шейдеры настолько дорогие, что и сортировка не спасает, — разберём в пятницу.
#devmath #графика #математика #рендер #оптимизация #gamedev
Сложная сцена проседает по fps. Первым делом вы идёте резать полигоны: упрощаете меши, расставляете LOD'ы, чистите вершины. Треугольников стало заметно меньше — а кадр не полегчал. Профайлер показывает, что видеокарта всё время сидит в пиксельном шейдере, а не в геометрии.
Дело в том, что один пиксель за кадр закрашивается не по разу. Поставьте три объекта друг за другом по глубине: дальше всех стена, перед ней ящик, перед ящиком стойка. Рисуются они в том порядке, в каком их отдал движок, — и если дальняя стена попадёт под кисть первой, она закрасит свои пиксели и целиком отработает шейдер: текстуры, свет, туман. Потом поверх ляжет ящик — и тоже целиком. Потом стойка. На экране виден только ближний слой, а пиксельный шейдер отработал по числу слоёв. Это и есть overdraw — работа, оплаченная за пиксели, которые в итоге никто не увидит.
Плотный интерьер, свалка пропов, наслоённые полупрозрачные эффекты — там overdraw набегает быстро. Горит fillrate. Fillrate (филлрейт) — это скорость, с которой видеокарта заливает пиксели в буфер кадра: её пропускная способность на закраску, отдельная от пропускной способности на геометрию.
Поймать довольно просто. Подведите камеру вплотную к скоплению объектов: если fps проседает там, где в кадр влезает даже меньше геометрии, но она плотно перекрывается по глубине, — вы уперлись в overdraw, а не в треугольники. А ещё лучше — включите режим overdraw: он есть у Unity, Unreal и мобильных профайлеров. Места, перекрашенные много раз, светятся всё ярче. Это буквально ваш счёт за кадр, нарисованный поверх сцены, — один раз увидев его, вы перестаёте гоняться за полигонами.
Видеокарта умеет выбрасывать перекрытые пиксели ещё ДО того, как посчитает их шейдер. Но у этого механизма есть условие, и когда объекты рисуются «как легли в сцене», условие не выполняется — и каждый невидимый слой всё равно оплачен. Что это за условие и что делать, когда шейдеры настолько дорогие, что и сортировка не спасает, — разберём в пятницу.
#devmath #графика #математика #рендер #оптимизация #gamedev
🔥11
Мобильный рендер: Дело не в мощности GPU
https://youtube.com/shorts/6WtXTERxLaI?si=65mL_ZQZno6b0fdO
Так как сейчас у нас недели разбора графики, то я решил попробовать и видосы поделать, как более простой формат подачи информации нежели статьи.
Про шину помнить очень важно. Как она загружается и тому подобное. В статье про дроуколлы это разбиралось. Просто где-то с 2017 года я в основном разбирался в том, как запустить красивую картинку на «калькуляторе». Если взять даже этот проект, где нужно было под вебгл с поддержкой мобилки сделать рабочую красивую 3д сцену. Когда нужно завести миллионы полигонов в вебе или что еще страшнее в WebAR, то нужно знать что вертексные параметры можно подрезать.
И в этом случае понимать всякие нюансы вроде того же тайлового рендера кадра на мобилках, почему там шина важнее чем на пк и т.п. довольно важно. И знать вообще что такое есть.
#devmath #gamedev #unity3d #оптимизацияигр #мобильныйгеймдев
https://youtube.com/shorts/6WtXTERxLaI?si=65mL_ZQZno6b0fdO
Так как сейчас у нас недели разбора графики, то я решил попробовать и видосы поделать, как более простой формат подачи информации нежели статьи.
Про шину помнить очень важно. Как она загружается и тому подобное. В статье про дроуколлы это разбиралось. Просто где-то с 2017 года я в основном разбирался в том, как запустить красивую картинку на «калькуляторе». Если взять даже этот проект, где нужно было под вебгл с поддержкой мобилки сделать рабочую красивую 3д сцену. Когда нужно завести миллионы полигонов в вебе или что еще страшнее в WebAR, то нужно знать что вертексные параметры можно подрезать.
И в этом случае понимать всякие нюансы вроде того же тайлового рендера кадра на мобилках, почему там шина важнее чем на пк и т.п. довольно важно. И знать вообще что такое есть.
#devmath #gamedev #unity3d #оптимизацияигр #мобильныйгеймдев
YouTube
Мобильный рендер: Дело не в мощности GPU
На телефоне лишний UV-канал в меше стоит дороже, чем на ПК. И дело ...
🔥5
Треугольник становится пикселями
https://dev-math.ru/articles/raster/
Вершина добралась до экрана — три точки в пиксельных координатах. Но сам треугольник ещё не закрашен, а на этом коротком отрезке конвейера живёт своя пачка знакомых багов.
Разбираем:
— почему тонкий провод вдали мерцает и рвётся;
— и почему добавить ему полигонов бесполезно;
— отчего далёкие поверхности дерутся полосами друг сквозь друга — и при чём тут near, а не far;
— как один и тот же кадр выходит то в пять слоёв, то в один — не тронув ни единого полигона;
— почему на PlayStation 1 текстуры «плыли» — и что за одно деление это лечит.
#devmath #графика #математика #рендер #растеризация
https://dev-math.ru/articles/raster/
Вершина добралась до экрана — три точки в пиксельных координатах. Но сам треугольник ещё не закрашен, а на этом коротком отрезке конвейера живёт своя пачка знакомых багов.
Разбираем:
— почему тонкий провод вдали мерцает и рвётся;
— и почему добавить ему полигонов бесполезно;
— отчего далёкие поверхности дерутся полосами друг сквозь друга — и при чём тут near, а не far;
— как один и тот же кадр выходит то в пять слоёв, то в один — не тронув ни единого полигона;
— почему на PlayStation 1 текстуры «плыли» — и что за одно деление это лечит.
#devmath #графика #математика #рендер #растеризация
🔥6🤝1
Фильтрация текстур
Подошли в игре вплотную к стене — и вместо кирпича размытое пятно. Можно подумать: «фильтрация мылит, поставлю point». Ставите — мыло уходит, приходят квадратики. Ощущение, что выбираешь между двумя видами испорченной картинки. Так и есть, и вот почему.
Текстура для шейдера — не картинка, а функция: подали координату, получили цвет. Только в памяти лежит конечный массив, и значение каждого текселя — это точка в центре его клетки. Ровно как пиксель на экране, про который мы говорили на прошлой неделе.
Когда вы подошли к стене вплотную, на один тексель приходится несколько экранных пикселей — и между известными точками надо что-то придумать. Nearest придумывает «возьму ближайшую» — получаются квадратики. Билинейная фильтрация придумывает «смешаю четыре соседние точки по расстоянию» — получается плавно, то есть мыло. Новой информации ни там, ни там не появилось: обе читают одну и ту же текстуру. Фильтр не создаёт новых деталей — он выбирает, как будет выглядеть их нехватка.
Отсюда вывод, который экономит время: если текстура мылит вблизи, крутить фильтр бесполезно. Мылит — значит текселей на этот кусок экрана просто мало. Лечится плотностью текселей: крупнее текстура, мельче тайл на поверхности, отдельная detail-карта поверх — или, если так и задумано, point-фильтр и пиксель-арт как художественное решение (Minecraft именно поэтому и не мылит).
И бонус. Если картинка не столько мылит, сколько «чуть мылит и чуть съехала» — обычно это забытые полтекселя. Значение текселя лежит в центре клетки, поэтому при переводе координаты в текселе-пространство вычитают 0.5. Забыли — и вся текстура уехала на полклетки; на кирпичной стене незаметно, на UI и атласах иконок видно сразу.
Но самое интересное начинается, когда всё наоборот: не текселей мало на пиксель, а пикселей мало на тексель. Посмотрите на ту же стену не вблизи, а метров с тридцати: в один пиксель попадает уже несколько десятков текселей — и картинка вдали начинает кипеть при малейшем движении камеры. Что там читает сэмплер, откуда берутся уменьшенные копии текстуры и как он выбирает между ними — разберём в пятницу.
#devmath #графика #математика #рендер #текстуры #gamedev
Подошли в игре вплотную к стене — и вместо кирпича размытое пятно. Можно подумать: «фильтрация мылит, поставлю point». Ставите — мыло уходит, приходят квадратики. Ощущение, что выбираешь между двумя видами испорченной картинки. Так и есть, и вот почему.
Текстура для шейдера — не картинка, а функция: подали координату, получили цвет. Только в памяти лежит конечный массив, и значение каждого текселя — это точка в центре его клетки. Ровно как пиксель на экране, про который мы говорили на прошлой неделе.
Когда вы подошли к стене вплотную, на один тексель приходится несколько экранных пикселей — и между известными точками надо что-то придумать. Nearest придумывает «возьму ближайшую» — получаются квадратики. Билинейная фильтрация придумывает «смешаю четыре соседние точки по расстоянию» — получается плавно, то есть мыло. Новой информации ни там, ни там не появилось: обе читают одну и ту же текстуру. Фильтр не создаёт новых деталей — он выбирает, как будет выглядеть их нехватка.
Отсюда вывод, который экономит время: если текстура мылит вблизи, крутить фильтр бесполезно. Мылит — значит текселей на этот кусок экрана просто мало. Лечится плотностью текселей: крупнее текстура, мельче тайл на поверхности, отдельная detail-карта поверх — или, если так и задумано, point-фильтр и пиксель-арт как художественное решение (Minecraft именно поэтому и не мылит).
И бонус. Если картинка не столько мылит, сколько «чуть мылит и чуть съехала» — обычно это забытые полтекселя. Значение текселя лежит в центре клетки, поэтому при переводе координаты в текселе-пространство вычитают 0.5. Забыли — и вся текстура уехала на полклетки; на кирпичной стене незаметно, на UI и атласах иконок видно сразу.
Но самое интересное начинается, когда всё наоборот: не текселей мало на пиксель, а пикселей мало на тексель. Посмотрите на ту же стену не вблизи, а метров с тридцати: в один пиксель попадает уже несколько десятков текселей — и картинка вдали начинает кипеть при малейшем движении камеры. Что там читает сэмплер, откуда берутся уменьшенные копии текстуры и как он выбирает между ними — разберём в пятницу.
#devmath #графика #математика #рендер #текстуры #gamedev
🔥7👍3
10 000$ за баг в GTA
https://youtube.com/shorts/3iJa_wPmGKM?si=pdZ1e-VWVgGtrMhh
Семь лет GTA Online грузилась по пять минут — на любом железе. Чинить взялся не Rockstar, а игрок под ником t0st взялся, и хватило ему выходных. И получил за это 10 000$.
Оказалось, при каждом входе игра разбирала список из 63 тысяч товаров так, что на каждой позиции пересчитывала всю строку заново. Плюс проверка каждого с каждым на дубли. Около двух миллиардов холостых проверок — и минуты ожидания у миллионов людей.
#devmath #разработкаигр #gta #программирование #gamedev
https://youtube.com/shorts/3iJa_wPmGKM?si=pdZ1e-VWVgGtrMhh
Семь лет GTA Online грузилась по пять минут — на любом железе. Чинить взялся не Rockstar, а игрок под ником t0st взялся, и хватило ему выходных. И получил за это 10 000$.
Оказалось, при каждом входе игра разбирала список из 63 тысяч товаров так, что на каждой позиции пересчитывала всю строку заново. Плюс проверка каждого с каждым на дубли. Около двух миллиардов холостых проверок — и минуты ожидания у миллионов людей.
#devmath #разработкаигр #gta #программирование #gamedev
YouTube
10 000$ за баг в GTA
Семь лет GTA Online грузилась по пять минут — на любом железе. Чини...
🔥2👎1
Пол вдали превратился в кашу?
Смотрите вдоль пола — и метрах в десяти плитка перестаёт быть плиткой. Не мерцает, не рябит, а ровно и мутно мылит, как будто туда забыли положить текстуру. При этом та же самая текстура на стене прямо перед носом читается прекрасно, и под ногами всё резко. Мылит именно то, что уходит вдаль под острым углом: пол, дорога, длинная стена сбоку.
Дальше начинается знакомый заход. Раз мыло — значит мало разрешения. Дорогу поднимают с 1024 до 2048, потом до 4096, память растёт вчетверо на каждый шаг, стриминг начинает захлёбываться на въезде в локацию — а дорога вдали всё такая же мутная. Ловили такое?
Собственно, вот в чём дело. Пиксель накрывает на поверхности не точку, а кусок. Когда поверхность стоит к вам лицом, этот кусок — аккуратный квадратик. А когда пол наклонён почти под ноль, он превращается в длинную узкую полосу: поперёк взгляда пиксель накрывает пару текселей, а вглубь — несколько десятков. И подробность сэмплер выбирает одним числом на весь след — по его длинной стороне. Тридцать два текселя вглубь — берётся версия текстуры, уменьшенная в тридцать два раза. Поперечная деталь, которой разрешения хватало с большим запасом, усредняется вместе со всем остальным. Вот и мыло.
Причём это не баг, а вынужденный выбор. Возьми сэмплер короткую сторону вместо длинной — вдоль взгляда пошла бы не резкость, а кипящая рябь, потому что там сигнал меняется быстрее, чем его щупают. Одним числом на вытянутый след можно выбрать либо мыло, либо шум. Третьего в этой схеме нет.
По сути отсюда и ответ, почему апскейл ассета не помогает: текстура крупнее — обе оси следа растут одинаково, вытянутость остаётся той же. Вы отыгрываете один уровень подробности ценой вчетверо большей памяти, а перекос как был, так и остался. Настройка, которая чинит именно перекос, называется анизотропная фильтрация — та самая строчка «Anisotropic Filtering: 16x» в настройках графики. Она щупает вытянутый след не одной точкой, а несколькими вдоль длинной оси.
И приятная часть: число выборок считается для каждого пикселя отдельно. Там, где след круглый — стена перед носом, пол под ногами, — оно равно единице, и никакой доплаты нет. Платят только скользящие углы, а их в кадре обычно меньшинство. Так что это одна из тех галочек, которые дают заметно больше, чем стоят.
Ну а самое интересное — дальше. Откуда вообще берётся то самое одно число на весь след и почему в нём стоит именно максимум; сколько на деле стоит ×16 и почему не в шестнадцать раз дороже; и почему выкрученная анизотропия при выключенных мипмапах не работает вовсе — а такую комбинацию встречаешь регулярно. Разберём в пятницу. Там же пол, который можно наклонить ползунком и кликнуть по нему: видно и сам след пикселя в пространстве текстуры, и как в нём выстраиваются точки выборки, когда вы переключаете ×1 → ×16.
#геймдев #графика #математика #рендер #текстуры #gamedev
Смотрите вдоль пола — и метрах в десяти плитка перестаёт быть плиткой. Не мерцает, не рябит, а ровно и мутно мылит, как будто туда забыли положить текстуру. При этом та же самая текстура на стене прямо перед носом читается прекрасно, и под ногами всё резко. Мылит именно то, что уходит вдаль под острым углом: пол, дорога, длинная стена сбоку.
Дальше начинается знакомый заход. Раз мыло — значит мало разрешения. Дорогу поднимают с 1024 до 2048, потом до 4096, память растёт вчетверо на каждый шаг, стриминг начинает захлёбываться на въезде в локацию — а дорога вдали всё такая же мутная. Ловили такое?
Собственно, вот в чём дело. Пиксель накрывает на поверхности не точку, а кусок. Когда поверхность стоит к вам лицом, этот кусок — аккуратный квадратик. А когда пол наклонён почти под ноль, он превращается в длинную узкую полосу: поперёк взгляда пиксель накрывает пару текселей, а вглубь — несколько десятков. И подробность сэмплер выбирает одним числом на весь след — по его длинной стороне. Тридцать два текселя вглубь — берётся версия текстуры, уменьшенная в тридцать два раза. Поперечная деталь, которой разрешения хватало с большим запасом, усредняется вместе со всем остальным. Вот и мыло.
Причём это не баг, а вынужденный выбор. Возьми сэмплер короткую сторону вместо длинной — вдоль взгляда пошла бы не резкость, а кипящая рябь, потому что там сигнал меняется быстрее, чем его щупают. Одним числом на вытянутый след можно выбрать либо мыло, либо шум. Третьего в этой схеме нет.
По сути отсюда и ответ, почему апскейл ассета не помогает: текстура крупнее — обе оси следа растут одинаково, вытянутость остаётся той же. Вы отыгрываете один уровень подробности ценой вчетверо большей памяти, а перекос как был, так и остался. Настройка, которая чинит именно перекос, называется анизотропная фильтрация — та самая строчка «Anisotropic Filtering: 16x» в настройках графики. Она щупает вытянутый след не одной точкой, а несколькими вдоль длинной оси.
И приятная часть: число выборок считается для каждого пикселя отдельно. Там, где след круглый — стена перед носом, пол под ногами, — оно равно единице, и никакой доплаты нет. Платят только скользящие углы, а их в кадре обычно меньшинство. Так что это одна из тех галочек, которые дают заметно больше, чем стоят.
Ну а самое интересное — дальше. Откуда вообще берётся то самое одно число на весь след и почему в нём стоит именно максимум; сколько на деле стоит ×16 и почему не в шестнадцать раз дороже; и почему выкрученная анизотропия при выключенных мипмапах не работает вовсе — а такую комбинацию встречаешь регулярно. Разберём в пятницу. Там же пол, который можно наклонить ползунком и кликнуть по нему: видно и сам след пикселя в пространстве текстуры, и как в нём выстраиваются точки выборки, когда вы переключаете ×1 → ×16.
#геймдев #графика #математика #рендер #текстуры #gamedev
🔥4❤3🫡2
Почему далёкая текстура мерцает
https://dev-math.ru/articles/textures/
Мне очень нравится конечно составлять эти статьи, так как помимо описаний для понимания компьютерной графики, для меня они являются погружением в ностальгическое прошлое. Как всё было придумано и зачем.
В статье разберем:
- почему тексель — не пиксель и что на самом деле делают nearest и билинейная фильтрация;
- откуда берётся мерцание вдали — алиасинг при уменьшении — и как его лечат мипмапы;
- почему при взгляде вдоль пола картинка мылится и что с этим делает анизотропная фильтрация;
- сколько всё это весит в памяти и как устроено блочное сжатие BCn и ASTC;
- и как эти решения складываются в один запрос к сэмплеру.
Ставьте🔥 и делитесь с друзьями, если статья была интересна. В будущем возможно я сошью это в какой-то учебник по компьютерной графике, который уже будет за символическую цену, чтобы желающие могли поддержать автора так сказать. А пока поделиться постом лучшая поддержка.
#devmath #графика #математика #рендер #текстуры
https://dev-math.ru/articles/textures/
Мне очень нравится конечно составлять эти статьи, так как помимо описаний для понимания компьютерной графики, для меня они являются погружением в ностальгическое прошлое. Как всё было придумано и зачем.
В статье разберем:
- почему тексель — не пиксель и что на самом деле делают nearest и билинейная фильтрация;
- откуда берётся мерцание вдали — алиасинг при уменьшении — и как его лечат мипмапы;
- почему при взгляде вдоль пола картинка мылится и что с этим делает анизотропная фильтрация;
- сколько всё это весит в памяти и как устроено блочное сжатие BCn и ASTC;
- и как эти решения складываются в один запрос к сэмплеру.
Ставьте
#devmath #графика #математика #рендер #текстуры
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13