Найти в Дзене

Как работает видеокарта в играх

Игровая картинка выглядит как «фотореализм», но внутри — строгий конвейер вычислений, который GPU прогоняет заново на каждом кадре. Если понимать базовые этапы, проще объяснить себе, почему проседает FPS: где упираетесь в геометрию, где — в пиксели, где — в освещение, а где начинаются отдельные тяжёлые блоки вроде ray tracing и DLSS. Для ориентира по масштабу: пример детализированной сцены можно разложить в цифры — 2,1 млн вершин собираются в 3,5 млн треугольников, поверх назначены 976 цветов и текстур. И важный практический момент: камера не рендерит «весь мир». В сцене может быть 1 100 моделей, но поле зрения камеры отсекает лишнее — к рендерингу попадают 600 объектов. Отдельный объект тоже «обманчиво гладкий». Например, локомотив визуально круглый, но геометрически это 762 тыс. плоских треугольников, 382 тыс. вершин и 9 материалов/цветов на поверхностях. Смысл этапа — перенести все вершины из 3D-пространства в координаты 2D-экрана. Это делается тремя преобразованиями координат: Во в
Оглавление

Как GPU рисует 3D-картинку в играх: конвейер рендеринга без магии (vertex → raster → fragment)

Игровая картинка выглядит как «фотореализм», но внутри — строгий конвейер вычислений, который GPU прогоняет заново на каждом кадре. Если понимать базовые этапы, проще объяснить себе, почему проседает FPS: где упираетесь в геометрию, где — в пиксели, где — в освещение, а где начинаются отдельные тяжёлые блоки вроде ray tracing и DLSS.

Что именно GPU «переваривает» в сцене

Для ориентира по масштабу: пример детализированной сцены можно разложить в цифры — 2,1 млн вершин собираются в 3,5 млн треугольников, поверх назначены 976 цветов и текстур.

И важный практический момент: камера не рендерит «весь мир». В сцене может быть 1 100 моделей, но поле зрения камеры отсекает лишнее — к рендерингу попадают 600 объектов.

Отдельный объект тоже «обманчиво гладкий». Например, локомотив визуально круглый, но геометрически это 762 тыс. плоских треугольников, 382 тыс. вершин и 9 материалов/цветов на поверхностях.

Конвейер рендеринга: 3 шага, которые стоят за каждым кадром

Сцена в игре состоит из геометрии (вершины и треугольники) и назначенных материалов/текстур. Камера отсекает невидимое — из 1 100 моделей в кадр попадают 600 объектов. Затем GPU прогоняет данные через три ключевых этапа:

Vertex shading — перенос вершин из 3D в координаты 2D-экрана (плюс глубина Z).

Rasterization — определение, какие пиксели закрывает каждый треугольник (появляются фрагменты).

Fragment shading — расчёт освещения и материала по пикселям, чтобы картинка выглядела объёмной.
На выносках показаны реальные масштабы: 2,1 млн вершин / 3,5 млн треугольников / 976 цветов и текстур; пример объекта (локомотив) — 382 тыс. вершин / 762 тыс. треугольников / 9 материалов.
Сцена в игре состоит из геометрии (вершины и треугольники) и назначенных материалов/текстур. Камера отсекает невидимое — из 1 100 моделей в кадр попадают 600 объектов. Затем GPU прогоняет данные через три ключевых этапа: Vertex shading — перенос вершин из 3D в координаты 2D-экрана (плюс глубина Z). Rasterization — определение, какие пиксели закрывает каждый треугольник (появляются фрагменты). Fragment shading — расчёт освещения и материала по пикселям, чтобы картинка выглядела объёмной. На выносках показаны реальные масштабы: 2,1 млн вершин / 3,5 млн треугольников / 976 цветов и текстур; пример объекта (локомотив) — 382 тыс. вершин / 762 тыс. треугольников / 9 материалов.

1) Vertex shading: как 3D превращается в 2D «вид на экран»

Смысл этапа — перенести все вершины из 3D-пространства в координаты 2D-экрана. Это делается тремя преобразованиями координат:

  • из model space в world space
  • из world space в camera space
  • из перспективы поля зрения на view screen

Во входных данных — координаты вершины X/Y/Z в model space, положение/масштаб/поворот модели в world space, координаты/поворот камеры и её поле зрения. Всё это собирается в матрицы преобразований и перемножается.

На выходе у каждой вершины появляются:

  • X и Y на view screen (то есть «где это на экране»)
  • Z (depth) — глубина, которая дальше решает, кто кого перекрывает

И так — для каждой вершины. В итоге на 2D-плоскость проецируются те же 3,5 млн треугольников (просто уже в экранных координатах).

2) Rasterization: как треугольники превращаются в пиксели и фрагменты

Дальше нужно понять: какие пиксели экрана закрывает каждый треугольник.

Для масштаба: 4K — это 3840×2160, то есть около 8,3 млн пикселей. GPU берёт экранные координаты вершин треугольника (X/Y), «накладывает» его на сетку пикселей и определяет, какие пиксели внутри.

Тут появляется базовый термин:

Фрагменты (fragments) — группы пикселей, пришедшие от одного растеризованного треугольника и разделяющие одну текстуру/цвет.

Так GPU проходит по всем треугольникам и формирует 4K-кадр в frame buffer, который уходит на дисплей.

2.1) Проблема видимости: Z-buffer (depth buffer)

В 3D объекты перекрывают друг друга, а ещё у модели есть треугольники «сзади», которые математически проходят конвейер, но в финальном кадре не должны появиться.

Это решает Z-buffer: у каждого пикселя (из тех самых ~8,3 млн) хранится дополнительное значение глубины относительно камеры.

Правило простое:

  • если новый треугольник ближе (его depth меньше) — пиксель перерисовывается, depth обновляется
  • если дальше — вклад отбрасывается

Визуализация depth buffer обычно трактуется так: чёрный — близко, белый — далеко.

Важный нюанс: у треугольника в 3D часто три разные Z на вершинах, поэтому depth приходится вычислять для каждого пикселя треугольника по координатам вершин. Это же позволяет корректно рисовать пересечения треугольников пиксель-за-пикселем.

2.2) «Лесенка» на краях и SSAA

Классический конвейер (vertex/raster/fragment) формирует базовый кадр, здесь он представлен как low-res кадр. Ray tracing в игровых сценариях выступает как надстройка для отдельных задач — теней, отражений и улучшенного освещения — добавляя вычисления поверх базового кадра. Затем DLSS апскейлит low-res кадр до 4K с помощью нейросети (CNN).
Классический конвейер (vertex/raster/fragment) формирует базовый кадр, здесь он представлен как low-res кадр. Ray tracing в игровых сценариях выступает как надстройка для отдельных задач — теней, отражений и улучшенного освещения — добавляя вычисления поверх базового кадра. Затем DLSS апскейлит low-res кадр до 4K с помощью нейросети (CNN).

Почему края «ступеньками»? Если треугольник проходит через пиксель под углом, пиксель часто закрашивается целиком, даже если треугольник покрывает его частично.

Один из способов уменьшить эффект — SSAA (Super Sampling Anti-Aliasing). В описанном варианте в один пиксель кладут 16 точек выборки. Если треугольник покрывает только часть из этих 16 точек, пиксель получает дробный оттенок — края становятся мягче, пикселизация заметно падает.

3) Fragment shading: как появляется свет, объём и материал

После растеризации «просто покрасить» недостаточно — реализм дают освещение и материал. Fragment shading учитывает:

  • направление и силу света
  • положение камеры
  • отражения и тени от объектов

На примере металлического объекта это очевидно: если дать всем пикселям один цвет, получится плоская фигура. Но если добавить корректный шейдинг (низ темнее, верх светлее) и specular highlights (блики), «чёрный металл» начинает выглядеть как металл.

Динамика тоже туда же: при движении «солнца» меняется распределение света, ночью материалы темнеют и подсвечиваются огнём.

И да — даже Super Mario 64 (почти 30 лет) использует простую идею: цвета поверхностей меняются из-за света и теней.

Математика освещения: нормали, cos(theta), ambient и несколько источников

Упрощённо логика такая: поверхность, направленная на источник света, ярче; повернутая в сторону — темнее.

Для расчёта нужны:

  • направление света
  • нормаль поверхности (surface normal) — вектор, перпендикулярный плоскости треугольника

Яркость берут через cos(theta) между направлением света и нормалью:

  • cos(theta)=1, если поверхность «смотрит» на свет
  • cos(theta)=0, если поверхность перпендикулярна свету

Дальше:

  • cos(theta) умножается на интенсивность света
  • и на цвет материала

Чтобы поверхность не становилась «провалом в чёрное», отрицательные значения не используют: минимум фиксируется как 0, а сверху добавляют ambient light (окружающий свет). В дневных сценах ambient выше, ночью — ближе к 0.

Если источников света несколько, расчёт делают несколько раз и суммируют вклад. Но это дорого: большое число источников вычислительно тяжело, поэтому сцены ограничивают их количество и иногда ограничивают радиус влияния, чтобы треугольники игнорировали дальние источники.

Техническая деталь: на практике cos(theta) считают через векторную математику — dot product, делённый на norm векторов.

Условная форма записи логики выглядит так:

shaded = (max(0, cos_theta) * light_intensity + ambient_intensity) * material_color

Flat vs Smooth: почему «гладкий объект» может выглядеть гранёным

Проблема flat shading: у каждого треугольника одна нормаль — значит, цвет по треугольнику одинаковый, и кривые поверхности выглядят «фасеточно».

Для smooth shading:

  • берут нормаль на каждую вершину (усреднение нормалей соседних треугольников)
  • внутри треугольника нормаль интерполируют через barycentric coordinates

Для конкретного фрагмента берут центр пикселя и по координатам треугольника и vertex normals вычисляют barycentric normal этого пикселя. Итог — плавные градиенты освещения «пиксель за пикселем».

Где в этой схеме ray tracing и DLSS

Классический конвейер (vertex/raster/fragment) формирует базовый кадр, здесь он представлен как low-res кадр. Ray tracing в игровых сценариях выступает как надстройка для отдельных задач — теней, отражений и улучшенного освещения — добавляя вычисления поверх базового кадра. Затем DLSS апскейлит low-res кадр до 4K с помощью нейросети (CNN).
Классический конвейер (vertex/raster/fragment) формирует базовый кадр, здесь он представлен как low-res кадр. Ray tracing в игровых сценариях выступает как надстройка для отдельных задач — теней, отражений и улучшенного освещения — добавляя вычисления поверх базового кадра. Затем DLSS апскейлит low-res кадр до 4K с помощью нейросети (CNN).

Ray tracing

Трассировка лучей традиционно даёт очень точные свет и отражения (типично для кино/TV), и один кадр может рендериться десятки минут или больше.

В играх обычно делают гибрид:

  • основная видимость и базовый шейдинг — через классический конвейер
  • ray tracing в отдельных проектах добавляют для теней, отражений и улучшенного освещения

DLSS

DLSS берёт кадр в низком разрешении и апскейлит до 4K с помощью convolution neural network. По описанной схеме DLSS выполняется после того, как ray tracing и базовый конвейер сформировали low-resolution кадр.

Почему современные GPU «вывозят» RT+DLSS лучше: три типа ядер

Отдельный практический факт: у последних поколений GPU выделены разные вычислительные блоки:

  • CUDA / shading cores — классический конвейер (vertex/raster/fragment)
  • ray tracing cores — трассировка
  • tensor cores — DLSS

Когда включены RT и DLSS, GPU использует все ресурсы параллельно. Отсюда цифры по времени кадра:

  • с RT+DLSS можно рендерить 4K-кадры менее чем за 10 мс
  • если полагаться только на CUDA/shading cores, кадр занял бы около 50 мс

Производительность в цифрах: почему 120 FPS — это «бюджет 8,3 мс»

GPU оптимизированы под треугольные сетки и математику шейдеров. Пример порядка величин: около 10 000ish ядер могут выполнять до 35 трлн операций 32-битного умножения и сложения в секунду. За счёт параллелизма GPU распределяет вершины и данные трансформаций по ядрам и тянет сцену до 120+ FPS.

Перевод в понятный ограничитель: 120 FPS = 8,3 мс на кадр. И этот бюджет должен вместить vertex shading, rasterization и fragment shading заново — каждый кадр.

Нюансы и подводные камни

  • 4K — это 3840×2160 и около 8,3 млн пикселей: цена «пиксельных» этапов растёт резко.
  • Геометрия не исчезает сама: в сцене может быть 1 100 моделей, и только поле зрения камеры сокращает это до 600 объектов для рендера.
  • Даже «круглое» — это плоские треугольники: пример локомотива — 762 тыс. треугольников, 382 тыс. вершин, 9 материалов.
  • Z-buffer работает на уровне каждого пикселя (те же ~8,3 млн) и требует считать глубину внутри треугольника, потому что у вершин разные Z.
  • SSAA уменьшает «лесенку», но использует 16 точек выборки на пиксель — визуально эффективно, вычислительно не бесплатно.
  • Много источников света — дорого, поэтому сцены режут их число и/или радиус влияния.
  • Flat shading даёт «гранёность»; smooth shading требует vertex normals и интерполяции через barycentric coordinates.
  • Ray tracing и DLSS — не «настройки качества», а отдельные вычислительные блоки: RT обычно добавляет тени/отражения/свет, DLSS апскейлит low-res кадр до 4K нейросетью и выполняется после формирования low-res кадра.

Итог: кому разбираться, кому хватит пресетов

Если вы настраиваете графику под стабильный FPS или оцениваете «что даст новая видеокарта», держите в голове разделение по нагрузкам:

  • геометрия (вершины/треугольники) давит на ранние этапы
  • разрешение (пиксели) давит на растеризацию и шейдинг
  • освещение усложняет fragment shading
  • ray tracing и DLSS живут отдельными блоками и сильно меняют картину по времени кадра

Чек-лист настройки без гадания

  • Зафиксируйте цель по времени кадра: 120 FPS = 8,3 мс на весь конвейер.
  • Определитесь с разрешением: 4K = 3840×2160 ≈ 8,3 млн пикселей на кадр.
  • Помните, что видимость решается глубиной: Z-buffer хранит глубину для каждого пикселя и оставляет ближайшее.
  • Если включаете сглаживание SSAA, держите в голове механику 16 выборок на пиксель.
  • Если включаете ray tracing, воспринимайте его как отдельный блок, который часто считают для теней/отражений/света поверх классики.
  • Если используете DLSS, это апскейл low-res кадра до 4K через convolution neural network, выполняемый после формирования low-res кадра.
  • Если сравниваете GPU под RT+DLSS, учитывайте, что задействуются shading cores + RT cores + tensor cores, а не только шейдерные ядра.

Mini-FAQ

Почему у сцены «миллионы треугольников», но она всё равно в реальном времени?

Потому что GPU — параллельная машина под треугольные сетки и математику шейдеров: пример порядка величин —
10 000ish ядер и до 35 трлн 32-битных операций умножения/сложения в секунду.

Почему 4K так больно по производительности?

Потому что это около
8,3 млн пикселей на кадр, и дальше многие вычисления идут «по пикселям».

Зачем Z-buffer, если уже есть 3D-координаты?

Потому что на выходе растеризации нужно решить видимость для каждого пикселя: Z-buffer хранит глубину и оставляет ближайший треугольник.

DLSS — это «после рендера»?

По описанной схеме — да: DLSS апскейлит low-res кадр до 4K и выполняется
после того, как классический конвейер и ray tracing сформировали low-res кадр.

Почему RT+DLSS могут быть быстрее, чем «только шейдеры»?

Потому что в современных GPU есть отдельные блоки:
ray tracing cores и tensor cores, которые работают параллельно с CUDA/shading cores. В приведённых цифрах это даёт <10 мс на кадр против порядка 50 мс, если бы всё считалось только на шейдерных ядрах.

Эту же статью но под другим углом + схемы я написал на нашем портале:
https://tehnari.ru/ams/kak-rabotayet-videokarta-v-igrakh-rendering-sheidery-rasterizatsiya-i-z-buffer.30/