Компьютерная графика

Растеризация и пиксели

1995 год. Pixar выпускает Toy Story - первый полнометражный CGI-фильм. Каждый кадр рендерился 4-13 часов на кластере из 117 Sun SPARCstation. 2024 год: RTX 4090 рендерит тот же кадр за секунды. Но принцип не изменился ни на бит. Toy Story: 800 000 полигонов. Spider-Man: No Way Home: 250 миллионов. Всё что видишь на экране - треугольники. И всё что с ними происходит - rasterization pipeline, z-buffer, шейдеры. Это не магия и не «3D-графика». Это целочисленная арифметика и умные трюки с памятью.

  • **Unreal Engine 5 (Nanite):** виртуальная геометрия - система растеризует до миллиарда полигонов за кадр, динамически выбирая уровень детализации на GPU
  • **Chrome (Skia / Dawn):** каждый div, тень, текст - проходят GPU-растеризацию. На M1 Mac весь UI рендерится в Metal командах, которые собирает Skia
  • **Apple Core Animation:** каждый слой UIKit - отдельный framebuffer texture. Прокрутка на 120 Hz требует swap буфера каждые 8.3 мс без tearing
  • **Stable Diffusion (SDXL):** финальный шаг диффузии - это CUDA-тензор 1024×1024×4 float16. Отобразить его на экране - значит растеризовать float в RGBA8888 пиксели

Растеризация: из геометрии в пиксели

Экран - это сетка квадратов. GPU - это машина для закрашивания этих квадратов. Всё остальное - детали. Процесс перевода математической геометрии (линий, треугольников, кривых Безье) в набор конкретных пикселей называется **растеризация** - и это самая горячая петля в графическом pipeline: в AAA-игре GPU растеризует 10-100 миллионов треугольников каждые 16 миллисекунд.

**Растеризация** (rasterization) - преобразование векторной геометрии (отрезки, треугольники, полигоны) в растровое изображение (сетку пикселей). Это основа реального времени графики: GPU растеризует миллионы треугольников 60+ раз в секунду.

Простейшая задача растеризации: нарисовать отрезок от (x₁, y₁) до (x₂, y₂). Наивный путь - вычислять y = kx + b для каждого x: умножение, деление, округление float. Медленно. Брезенхэм в 1962-м придумал лучше: накапливать целочисленную ошибку и принимать решение о сдвиге по y через простое сравнение. Никаких float - только сложения и вычитания.

Алгоритм Брезенхэма (1962)

Джек Брезенхэм разработал алгоритм для плоттера IBM 1401. В эпоху, когда деление стоило сотни тактов, целочисленный алгоритм с только сложениями и сдвигами был прорывом. 60+ лет спустя тот же принцип используется в GPU.

Главное преимущество алгоритма Брезенхэма перед наивным y = kx + b:

Пиксели и цветовые модели

Пиксель - это число в памяти. Точнее - три числа: Red, Green, Blue. Или четыре, если есть прозрачность. В VRAM они упакованы плотно подряд, и GPU читает их тысячами за такт. Цветовая модель - это просто договорённость о том, что эти числа означают.

**RGB** - аддитивная цветовая модель. Каждый канал (Red, Green, Blue) хранит интенсивность от 0 до максимума. **Bit depth** определяет точность: 8 бит = 256 уровней на канал (16.7 млн цветов), 10 бит = 1024 уровня (1.07 млрд цветов).

ФорматБит/пиксельКаналыПрименение
RGB56516R:5, G:6, B:5Мобильные устройства, embedded
RGB88824R:8, G:8, B:8Стандартный (JPEG, BMP)
RGBA888832R:8, G:8, B:8, A:8UI, игры (с прозрачностью)
RGB10101030R:10, G:10, B:10HDR мониторы, кино
RGBA16F644×16bit floatHDR rendering, compositing

**Альфа-канал** - четвёртое число. A = 255: пиксель непрозрачный. A = 0: пиксель прозрачный, не рисуем ничего. A = 128: блендинг. Формула alpha blending: `result = src * α + dst * (1 - α)`. Каждое полупрозрачное окно, каждая тень, каждый tooltip в вашем UI - это эта формула, применяемая миллионы раз за кадр. В GPU она реализована как аппаратная операция ROP (Render Output Unit).

Сколько уникальных цветов может представить формат RGBA8888?

Framebuffer и Double Buffering

После растеризации пиксели уходят в **framebuffer** - это просто непрерывный массив в VRAM. Монитор читает его строка за строкой слева направо, сверху вниз - с частотой refresh rate. При 60 Hz это происходит 60 раз в секунду. При 120 Hz - 120 раз. GPU должен успеть нарисовать следующий кадр до следующего прохода монитора - иначе пользователь увидит «разрыв».

**Framebuffer** - непрерывный блок памяти (video RAM), хранящий растровое изображение экрана. Для разрешения W×H с C байтами на пиксель: размер = W × H × C байт. Пример: 1920×1080 RGBA = 8,294,400 байт ≈ 8 МБ.

**Tearing** - монитор читает framebuffer в момент, когда GPU туда же пишет. Верхняя половина экрана - новый кадр. Нижняя - старый. Горизонтальная линия разрыва прыгает по экрану. В шутерах это болезненно заметно. Решение - не рисовать в тот буфер, который монитор сейчас читает. Два буфера, swap между ними.

МетодTearingЗадержкаFPS
Single bufferДа (видимые разрывы)МинимальнаяНеограничен
Double buffer (без VSync)ВозможенМинимальнаяНеограничен
Double buffer + VSyncНет+1 кадр (16мс при 60Hz)≤ частота монитора
Triple bufferНетМеньше чем VSync≤ частота монитора

**Triple buffering** - третий буфер разрывает жёсткую связку: GPU рисует в один back buffer, второй ожидает VSync, третий - перед монитором. GPU никогда не ждёт монитора. Технологии G-Sync (NVIDIA) и FreeSync (AMD) идут дальше - они динамически синхронизируют refresh rate монитора под текущий FPS. Монитор подстраивается под GPU, а не наоборот.

Double buffering + VSync устраняет tearing. Какова цена?

Разрешение и Aspect Ratio

Разрешение - это размер framebuffer. Больше пикселей = больше памяти = больше работы растеризатора. Это линейная зависимость: удвоил площадь экрана - удвоил нагрузку. Переход с 1080p на 4K - это четырёхкратный прирост пикселей, и именно поэтому RTX 3060 «не тянет» 4K в требовательных играх, хотя в 1080p выдаёт 100+ FPS.

**Разрешение** - количество пикселей по горизонтали и вертикали. **Aspect Ratio** - соотношение ширины к высоте. 1920×1080 → 16:9. Больше пикселей → больше деталей, но GPU растеризует пропорционально больше.

НазваниеРазрешениеAspect RatioМегапикселиFramebuffer (RGBA)
720p (HD)1280×72016:90.92 МП3.5 МБ
1080p (Full HD)1920×108016:92.07 МП7.9 МБ
1440p (2K)2560×144016:93.69 МП14.1 МБ
4K (UHD)3840×216016:98.29 МП31.6 МБ
Ultrawide3440×144021:94.95 МП18.9 МБ

**PPI** (pixels per inch) - плотность, а не разрешение. iPhone 15 при 2556×1179 на диагонали 6.1" даёт 461 PPI - пиксели физически не видны на нормальном расстоянии просмотра. 27" монитор при том же 4K разрешении - 163 PPI. Именно поэтому Apple называет Retina дисплеем дисплей от 220 PPI, а не конкретное разрешение: важна плотность, а не абсолютное число пикселей.

Toy Story в 1995-м рендерился 4 часа на кадр. Сегодня - секунды. Но математика та же: треугольники, растеризация, framebuffer. Брезенхэм написал свой алгоритм для плоттера IBM в 1962-м, не зная о GPU. 60 лет спустя его идея - в каждом NVIDIA, AMD и Apple Silicon. Принципы меняются медленно. Железо меняется быстро.

Ray tracing полностью заменил растеризацию в современных играх и GPU

Растеризация остаётся доминирующим методом рендеринга в real-time. Ray tracing используется гибридно: основная геометрия растеризуется, а RT добавляет отражения, тени и глобальное освещение. Чистый ray tracing слишком медленный для 60+ FPS

Растеризация - O(площадь треугольника в пикселях): GPU параллельно проверяет тысячи пикселей за такт. Ray tracing - O(W × H × глубина сцены): каждый луч обходит BVH-дерево всей геометрии сцены. При 4K и 200M треугольников чистый RT не выходит за 5-10 FPS даже на RTX 4090. Поэтому NVIDIA DLSS и AMD FSR: рендерить в 1080p через гибрид растеризации и RT, потом апскейлить нейросетью до 4K.

Ключевые идеи

  • **Растеризация** - перевод математической геометрии в пиксели. Алгоритм Брезенхэма (1962) делает это без float: только сложения целых чисел. Тот же принцип - в каждом GPU сегодня
  • **RGB/RGBA** - аддитивная модель. 8 бит/канал = 16.7 млн цветов. Alpha blending formula: `result = src * α + dst * (1 - α)` - основа любого полупрозрачного UI
  • **Framebuffer** - непрерывный блок VRAM. 1920×1080 RGBA = 7.9 МБ. Double buffering: GPU рисует в back buffer, монитор читает front - swap происходит на vertical blank
  • **Переход 1080p → 4K = 4× пикселей = 4× нагрузки на GPU.** Ray tracing добавляется поверх растеризации, не заменяет её - даже RTX 4090 использует гибридный подход

Связанные темы

Растеризация - первый шаг в понимании graphics pipeline:

  • Линейная алгебра для графики — Вершины треугольников трансформируются матрицами до растеризации
  • Координатные пространства — Геометрия проходит через цепочку пространств (model→world→screen) перед растеризацией
  • Двоичная система — RGB565, RGBA8888 - упаковка цветов в биты. Битовые операции для быстрого доступа к каналам

Вопросы для размышления

  • Почему алгоритм Брезенхэма до сих пор актуален, если современные GPU имеют аппаратные растеризаторы?
  • Как бы вы реализовали alpha blending для полупрозрачных объектов, которые перекрывают друг друга? Важен ли порядок рисования?
  • При переходе на 8K (7680×4320) - во сколько раз вырастет нагрузка на GPU по сравнению с 4K?

Связанные уроки

  • la-01-vectors-intro — Линейная алгебра - язык компьютерной графики: векторы, матрицы трансформаций, dot/cross product
  • gd-01 — Графика - основа геймдева: рендеринг, шейдеры, физика на GPU
  • arvr-01 — AR/VR строится поверх computer graphics: stereo rendering, reprojection, spatial mapping
  • dsp-01 — DSP обрабатывает сигналы во времени, computer graphics - в пространстве. Свёртка, фильтры, FFT применимы в обоих
  • arch-04-cpu
Растеризация и пиксели

0

1

Войти

Переход с 1080p на 4K увеличивает нагрузку на GPU примерно в: