Перейти к основному содержимому

Графические данные

Всем

Play ITЗагрузка интерактивного демо…

Play ITЗагрузка интерактивного демо…

Play ITЗагрузка интерактивного демо…

Маршрут по разделу
  • Базовый уровень — что такое графика, 2D и 3D, стек "приложение → GPU → экран", кадр и FPS.
  • Форматы — статьи "Вектор и растр", "Растровые/векторные форматы", таблица сравнения.
  • Практика — "Работа с геометрией" (координаты, масштаб, прокрутка, столкновения).
  • Углубление — блок "Графический конвейер" в этой же статье (шейдеры, текстуры, PBR); его можно прочитать после форматов.
  • Код — как числа в .js/.py превращаются в картинку: 4.18 Разработка графики.

Графика​

Что такое графика?​

Компьютерная графика — это представление, обработка и вывод визуальной информации в вычислительной системе: от пикселя на экране до трёхмерной сцены в игре или CAD.

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

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

Современная компьютерная графика — результат длительной эволюции, начавшейся с простых символьных терминалов и осциллографов 1950–1960-х годов и завершившейся сегодняшними системами, генерирующими фотореалистичные изображения в реальном времени. При этом графика лежит в основе систем визуализации данных (dashboard, GIS), интерфейсов (GUI, VR/AR), проектирования (CAD/CAM), медицинской диагностики (томография), автоматизированного управления (HMI), а также машинного зрения и генеративного ИИ.

Графический объект и качество изображения​

В школьном курсе и на экзамене полезно различать:

ПонятиеСмысл
Графический объектОтдельный элемент рисунка: линия, дуга, прямоугольник, надпись
Цифровой графический объектТот же объект, записанный в файле числами (пиксели или векторные команды)
Линия (вектор)Отрезок между двумя точками; при увеличении остаётся гладкой
Пиксель (растр)Одна ячейка цветовой сетки; при сильном увеличении видна «лесенка»
Градации цветов и полутоновПлавные переходы яркости и оттенка (критично для фото)
Фотографическое качествоНасколько цифровое фото похоже на натуральную сцену
Искажения, потеря качестваБлоки JPEG, размытие, шум, артефакты пересохранения
Группировка / разгруппировкаОбъединить объекты в один блок / снова редактировать по отдельности

Полный обзор технологий (форматы BMP–PDF, ввод со сканера, коррекция) — базовая информатика, раздел 17.


Двумерная и трёхмерная графика​

Принципиальное деление графики по измерности — на двумерную (2D) и трёхмерную (3D) — отражает геометрические свойства изображаемых объектов и различия в архитектуре обработки, в логике работы API, в требованиях к вычислительной мощности и в парадигмах разработки.


Двумерная графика​

Двумерная графика оперирует плоскими объектами, позиционируемыми в координатной системе с двумя осями — горизонтальной (X) и вертикальной (Y). В рамках этой модели отсутствует понятие глубины как физической размерности; всё, что происходит "вглубь экрана", имитируется с помощью художественных приёмов — перекрытия, масштабирования, воздушной перспективы, градиентов и теней. Такая имитация, однако, остаётся статичной и не позволяет изменить точку наблюдения без перерисовки всей сцены.

2DPaint.png

Типичные представители 2D-графики — рисунки, сканированные изображения, снимки с цифровых камер, интерфейсные элементы (кнопки, иконки, текст), схемы, диаграммы, анимация в стиле традиционного мультипликационного кино. Несмотря на "плоскость", двумерная графика может включать сложную внутреннюю структуру — многослойные композиции, альфа-каналы прозрачности, анимационные кривые, интерактивные зоны. Важно — 2D-графика не обязательно "простая" — современные 2D-движки (например, Godot 2D, PIXI.js, Cairo) поддерживают сложные эффекты постобработки, физику, частицы, шейдерную обработку и даже псевдо-3D-проекции (parallax scrolling, isometric view, faux-3D вроде mode 7 на SNES).

С точки зрения выполнения, 2D-рендеринг часто ближе к прямоугольной компоновке — операции сводятся к наложению спрайтов (изображений с прозрачностью), рисованию примитивов (линии, прямоугольники, кривые Безье), применению трансформаций (аффинных — сдвиг, поворот вокруг Z, масштаб) и композитингу. Это позволяет достигать высокой производительности даже на слабых устройствах — от микроконтроллеров с дисплеями до мобильных телефонов. Многие современные UI-фреймворки (Qt Quick, Flutter, Jetpack Compose, SwiftUI) используют именно 2D-графическую модель как основу, даже если визуально интерфейс создаёт иллюзию объёма.


Трёхмерная графика​

Трёхмерная графика вводит третью координатную ось — Z (глубину), что позволяет описывать объекты как объёмные тела, обладающие формой на плоскости и пространственным положением, ориентацией и взаимным расположением в сцене. В 3D-модели отсутствует жёсткая привязка к "виду" — одно и то же описание сцены может быть визуализировано с любой точки наблюдения, с любым углом обзора, под разным освещением — без необходимости хранить или перерисовывать отдельные изображения.

3DBlender.png

Процесс создания 3D-графики — это конвейер, состоящий из нескольких логических этапов, каждый из которых может быть реализован как на CPU, так и на GPU:

  1. Моделирование — этап создания геометрического описания объектов. Обычно это полигональная сетка (mesh) — совокупность вершин (vertex), рёбер и граней (чаще всего треугольников), задающих поверхность объекта. Также возможны аналитические представления (NURBS, subdivision surfaces), воксельные модели, signed distance fields (SDF), но в реальном времени доминирует именно полигональный подход из-за его эффективности и аппаратной поддержки.

  2. Трансформация и анимация — каждая вершина подвергается последовательности матричных преобразований:

    • модельная (перенос из локального пространства объекта в мировое),
    • видовая (перенос из мирового пространства в систему координат камеры),
    • проекционная (отображение 3D-сцены в 2D-плоскость — перспективное или ортогональное искажение).
      Эти операции часто объединяются в одну составную матрицу и применяются в vertex shader.
  3. Освещение и шейдинг — расчёт вклада источников света в цвет каждой точки поверхности. Модели освещения могут быть феноменологическими (Phong, Blinn-Phong), физически корректными (PBR — Physically Based Rendering), основанными на трассировке лучей (ray tracing) или на глобальном освещении (radiosity, photon mapping). В реальном времени ключевую роль играют шейдеры — небольшие программы, исполняемые параллельно на GPU:

    • vertex shader — обрабатывает вершины,
    • fragment (pixel) shader — определяет итоговый цвет каждого фрагмента,
    • geometry/tessellation/compute shaders — расширяют возможности для генерации геометрии, детализации, GPGPU.
  4. Растеризация и постобработка — завершающая стадия конвейера, на которой происходит:

    • разбиение примитивов на фрагменты (пиксельные кандидаты),
    • тесты глубины (Z-buffering), прозрачности, шаблона (stencil),
    • интерполяция атрибутов (цвет, нормаль, UV-координаты),
    • применение текстур (sampling, filtering, mipmapping),
    • запись в буфер кадра (framebuffer),
    • пост-эффекты (bloom, SSAO, motion blur, tone mapping).
  5. Рендеринг — общий термин, охватывающий всё вышеперечисленное. В контексте "оффлайн" (кино, архитектурная визуализация) рендеринг может занимать часы на кадр и использовать методы, такие как path tracing, photon mapping, Metropolis light transport. В "реальном времени" (игры, VR) — он ограничивается ~16 мс на кадр (60 FPS) и вынужден полагаться на аппроксимации и упрощения.

Важно подчеркнуть: 3D-графика не обязательно "реалистична". Стилизованные подходы (cel-shading, NPR — non-photorealistic rendering) намеренно отклоняются от физической достоверности для достижения художественного эффекта — аниме-рендеринг в The Legend of Zelda — Wind Waker, мультяшная графика в Borderlands, карандашный стиль в Okami — всё это 3D, но с сознательным подавлением глубины, теней, текстур в пользу чётких контуров и плоских цветовых зон.


Краткий глоссарий​

ТерминСмысл в двух словах
ПиксельМинимальная точка растрового изображения на экране
ФрагментКандидат в пиксель на этапе 3D-конвейера (до записи в кадр)
ТексельЭлемент текстуры при наложении на поверхность
Draw callОдна команда API "нарисовать порцию геометрии"
FramebufferБуферы кадра: цвет, глубина, иногда stencil
РастрированиеПеревод геометрии (или вектора) в сетку пикселей
ШейдерПрограмма на GPU (вершинная, фрагментная, compute)

Подробнее о координатах и преобразованиях на плоскости — в статье Работа с геометрией.


Архитектурные уровни графической обработки​

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

  • Прикладной уровень — код приложения (игра, редактор, браузер). Здесь определяется логика сцены — какие объекты отображаются, как они анимируются, как реагируют на ввод. Разработчик работает с высокоуровневыми API: Three.js, BabylonJS, Unity, Unreal Engine, Qt3D — или напрямую с низкоуровневыми графическими API.

  • Графический API (Application Programming Interface) — интерфейс между приложением и драйвером GPU. Он стандартизирует вызовы — создание контекста, выделение ресурсов (буферов, текстур), отправка команд отрисовки (draw calls), синхронизация. Основные API:

    • OpenGL — кроссплатформенный, устаревший, но всё ещё используемый (особенно в embedded и legacy-системах);
    • Vulkan — современный, низкоуровневый, явный, требует ручного управления памятью и синхронизацией, но даёт максимальный контроль и производительность;
    • DirectX 12 — эквивалент Vulkan для Windows и Xbox, тесно интегрирован с экосистемой Microsoft;
    • Metal — проприетарный API для устройств Apple (iOS, macOS), оптимизированный под их SoC;
    • WebGL / WebGPU — API для браузерного рендеринга; WebGL основан на OpenGL ES, WebGPU — на Vulkan/Metal/DX12 и представляет будущее веб-графики.
  • Драйвер устройства — ПО, предоставляемое производителем GPU (NVIDIA, AMD, Intel). Он переводит вызовы API в команды, понятные конкретному чипу, управляет ресурсами памяти, планирует выполнение, обеспечивает изоляцию и безопасность. Драйвер — "мост" между стандартизированным интерфейсом и уникальной архитектурой железа.

  • Графический процессор (GPU) — специализированное вычислительное устройство, построенное по принципу massively parallel processing. Современные GPU содержат тысячи ядер (CUDA cores, Stream Processors), кэши, высокоскоростную память (GDDR6X, HBM), подсистемы декодирования/кодирования видео, RT-ядра (для ускорения ray tracing), тензорные ядра (для ИИ-ускорения). GPU не "рисует" напрямую — он выполняет программы (шейдеры), читает данные (вершины, текстуры), записывает результат (в цветовой и глубинный буферы).

  • Дисплейная подсистема — компоненты, отвечающие за вывод изображения — видеовыход (HDMI, DisplayPort), контроллер дисплея, сам дисплей (LCD, OLED, CRT — в историческом контексте). Здесь происходят:

    • вертикальная синхронизация (vsync) — согласование частоты обновления кадров и дисплея,
    • двойная/тройная буферизация — предотвращение tearing’а,
    • HDR-обработка, цветокоррекция, масштабирование.

Время и интерактивность​

Особое значение в графике имеет временной аспект. В статической графике (изображения, PDF, печать) результат фиксирован. В динамической графике (анимация, интерфейсы, игры) изображение пересчитывается многократно в секунду. Это вводит понятие кадра (frame) — единицы визуального обновления, и частоты кадров (FPS — frames per second), определяющей плавность восприятия.

Низкая частота (< 30 FPS) воспринимается как "рывки"; 60 FPS — стандарт для большинства приложений; 90–120+ FPS — требование для VR (во избежание кинетоза). Однако важно не только количество кадров, но и их стабильность: резкие просадки (stuttering) ощущаются сильнее, чем равномерное снижение FPS.

Для достижения интерактивности критична сквозная задержка (end-to-end latency) — время от ввода (нажатие клавиши, движение мыши) до отображения результата. В шутерах, авиасимуляторах, музыкальных играх эта задержка должна быть минимальной (желательно < 20 мс), что требует быстрого рендеринга и оптимизированных систем ввода, предсказания движения (prediction), асинхронного отображения (ASW, ATW).


Современные тенденции и перспективы​

Несмотря на зрелость технологии, графика продолжает развиваться. Основные направления:

  • Гибридный рендеринг — комбинация растеризации (быстро) и трассировки лучей (реалистично). RTX-ядра в GPU позволяют выполнять ray tracing в реальном времени частично — для теней, отражений, глобального освещения — при этом основная геометрия всё ещё растеризуется.

  • Программируемая графика — рост роли compute shaders, где GPU используется для отрисовки, для физики, ИИ, обработки данных. Это стирает границы между графикой и GPGPU.

  • Виртуализация и облачная графика — рендеринг происходит на удалённом сервере (NVIDIA GeForce NOW, Xbox Cloud Gaming и аналоги), клиент получает видеопоток. Требует низкой задержки сети и адаптивного кодека.

  • Нейрогенеративная графика — использование нейросетей для суперразрешения (DLSS, FSR), интерполяции кадров (Frame Generation), автоматической генерации текстур, моделей, анимаций. Это не заменяет традиционную графику, но дополняет её новыми инструментами.

  • Доступность и инклюзивность — развитие графики не только для "мощных десктопов", но и для устройств с ограниченными ресурсами — веб (WebGPU), мобильные (Vulkan Mobile), embedded (OpenGL ES, Vulkan SC для safety-critical систем).


Углубление

Ниже — графический конвейер в 3D — vertex/fragment shader, Z-buffer, текстуры, deferred и ray tracing. Для первого прохода достаточно понять, что 3D-сцена превращается в кадр на GPU

детали этапов можно вернуться после разделов про форматы и геометрию.


Графический конвейер​

Графический конвейер — это абстрактная модель, описывающая поток данных и управления в системе визуализации. Он существует как на уровне спецификаций API (например, pipeline stages в Vulkan), так и на уровне аппаратной архитектуры GPU (fixed-function units и программируемые блоки). Конвейер не является физической "трубой", по которой движутся пиксели — это скорее логическая последовательность этапов, каждый из которых может выполняться параллельно, конвейерно, с перекрытием, при условии соблюдения зависимостей.

Современные конвейеры можно разделить на две большие категории:

  • Графический конвейер реального времени — оптимизированный под скорость, с доминированием растеризации (rasterization pipeline). Используется в играх, интерфейсах, интерактивных приложениях.
  • Оффлайн-конвейер — оптимизированный под физическую точность, с доминированием трассировки лучей и её обобщений (ray tracing pipeline, path tracing). Используется в кино, архитектурной визуализации, симуляциях.

Ниже рассматривается растеризационный конвейер, поскольку он лежит в основе подавляющего большинства интерактивных систем (включая браузеры через WebGL и мобильные приложения через Metal/Vulkan). При этом мы будем отмечать, как этапы меняются или заменяются в гибридных и ray tracing-подходах.


Определение сцены и подготовка данных​

Всё начинается в приложении. Разработчик (или движок) формирует описание сцены — структурированный набор объектов и параметров:

  • Геометрия — вершины, индексы, нормали, UV-координаты. Хранится в буферах вершин (vertex buffers) и индексных буферах (index buffers). Вершины могут включать дополнительные атрибуты — цвет, тангенс-базис (для normal mapping), skinning weights (для анимации).
  • Материалы — описания того, как объект взаимодействует со светом — базовый цвет, шероховатость, металличность, эмиссия, прозрачность. В PBR-подходе эти параметры соответствуют физическим свойствам поверхности.
  • Текстуры — растровые данные, накладываемые на геометрию — diffuse/albedo (основной цвет), normal (рельеф), roughness/metallic (PBR-параметры), height/displacement (высота), ambient occlusion (затенённость складок).
  • Свет — источники — точечные, направленные, прожекторы, area lights. В реальном времени часто используются proxy-объекты (light probes, reflection probes) для имитации сложного освещения.
  • Камера — параметры наблюдения — положение, направление, угол обзора (FOV), ближняя и дальняя плоскости отсечения (near/far clipping planes), соотношение сторон.

Эти данные загружаются в память GPU через буферы и текстурные объекты. Важно: передача данных между CPU и GPU — дорогая операция с точки зрения задержки. Поэтому современные API (Vulkan, DX12) требуют явного управления — выделение памяти, staging-буферы, синхронизация через барьеры и семафоры — чтобы избежать простоев и конфликтов.


Вершинная обработка (Vertex Processing)​

На этом этапе обрабатываются вершины геометрических примитивов (обычно треугольников). Каждая вершина поступает в vertex shader — программируемый блок, исполняемый параллельно для всех вершин в draw call.

Основные задачи vertex shader:

  • Применение модельно-видовой трансформации: перенос вершины из локального пространства объекта (object space) в пространство камеры (view space). Это достигается умножением вектора положения на матрицу ModelView.
  • Применение проекционной трансформации — преобразование координат из view space в clip space — однородное 4D-пространство, в котором дальнейшая обработка (отсечение, перспективное деление) становится унифицированной. Результат — gl_Position (в OpenGL) или SV_Position (в HLSL).
  • Передача интерполируемых атрибутов во фрагментный шейдер — нормали, UV-координаты, цвет вершины. Эти значения будут плавно изменяться между вершинами при растеризации.

Важно: vertex shader работает на одну вершину, без знания о соседних. Это обеспечивает параллелизм, но ограничивает возможности — нельзя, например, сгладить нормали без предварительного расчёта на CPU или в geometry shader.

В некоторых сценариях используется tessellation shader (Hull + Domain в DX11, Tessellation Control + Evaluation в OpenGL) — этап, вставляемый после vertex shader, позволяющий динамически детализировать геометрию на основе уровня детализации (LOD) или кривизны поверхности. Например, плоская сетка может быть разбита на тысячи мелких треугольников для изображения каменистой поверхности — без увеличения объёма данных, передаваемых с CPU.


Преобразование примитивов и сборка (Primitive Assembly & Clipping)​

После vertex shader полученные вершины группируются в примитивы (точки, линии, треугольники). Затем выполняется отсечение (clipping) — удаление частей примитивов, лежащих вне видимой области (frustum). Frustum задаётся шестью плоскостями (left, right, top, bottom, near, far); всё, что находится за ними, отбрасывается.

Отсечение происходит в clip space, до перспективного деления. Если примитив частично выходит за пределы frustum, он разрезается, и образуются новые вершины на пересечении с плоскостями. Этот этап, как правило, реализован в фиксированной логике GPU (fixed-function hardware), не программируется пользователем.

После отсечения проводится перспективное деление (perspective divide) — координаты (x, y, z, w) преобразуются в (x/w, y/w, z/w, 1), переходя из однородных в нормализованные координаты устройства (NDC — Normalized Device Coordinates), где X и Y лежат в диапазоне [-1, +1], а Z — в [0, 1] (в DirectX) или [-1, +1] (в OpenGL/Vulkan).


Преобразование в экранные координаты (Viewport Transform)​

NDC-координаты преобразуются в координаты экрана — целочисленные позиции пикселей в буфере кадра. Это делается с помощью viewport transform: масштабирование и смещение, чтобы уместить изображение в заданную прямоугольную область (viewport) на экране. Z-координата сохраняется для depth buffer.

На этом этапе также может выполняться back-face culling — отбрасывание треугольников, обращённых "обратной стороной" к камере (определение по порядку обхода вершин — clockwise/counterclockwise). Это простая, но эффективная оптимизация: в закрытых объектах внутренние грани никогда не видны.


Растеризация (Rasterization)​

Ключевой этап конвейера — преобразование геометрических примитивов (в основном треугольников) в фрагменты — кандидаты на пиксели. Растеризатор определяет, какие пиксели покрываются треугольником, и для каждого такого пикселя генерирует фрагмент (fragment), содержащий:

  • Экранные координаты (x, y),
  • Интерполированное значение Z (для depth test),
  • Интерполированные атрибуты из vertex shader (нормаль, UV, цвет и т.д.).

Интерполяция — перспективно-корректная — чем дальше точка, тем сильнее "растягивается" интерполяция, что предотвращает искажение текстур и освещения. Это требует деления на w при интерполяции — механизм, заложенный в аппаратуру GPU.

Растеризация — высокопараллельная операция: миллионы треугольников могут обрабатываться независимо. Современные GPU используют tile-based rendering (в мобильных чипах — PowerVR, Mali, Adreno), где экран делится на маленькие тайлы (например, 32×32 пикселя), и растеризация выполняется по тайлам, чтобы минимизировать обращения к памяти.


Фрагментная обработка (Fragment Processing)​

Каждый фрагмент поступает во фрагментный шейдер (fragment shader / pixel shader). Это наиболее вычислительно ёмкий этап: для FullHD-кадра может выполняться более двух миллионов вызовов шейдера за 16 мс.

Задачи фрагментного шейдера:

  • Выборка текстур (texture sampling) — чтение значений из текстурных буферов по UV-координатам. Здесь применяются фильтрация (linear, anisotropic), mipmapping (автоматический выбор уровня детализации текстуры в зависимости от расстояния), wrapping modes (repeat, clamp).
  • Расчёт освещения — на основе полученных нормалей, параметров материала и данных о свете. В простейшем случае — диффузное (Lambert) и зеркальное (Phong) отражение; в сложных — full PBR с image-based lighting (IBL), parallax mapping, subsurface scattering.
  • Обработка прозрачности — смешивание цвета фрагмента с уже записанным в буфер (blending). Требует сортировки прозрачных объектов по глубине (от дальних к ближним), что нарушает параллелизм.
  • Произвольная логика — генерация эффектов — волны воды, искажение (refraction), пост-обработка на уровне объекта (outlines, toon shading), отбрасывание фрагмента (discard), например, для альфа-тестирования (листья, решётки).

Фрагментный шейдер работает независимо для каждого фрагмента, без доступа к соседним — это гарантирует параллелизм, но затрудняет реализацию эффектов, требующих локального контекста (например, edge detection). Такие задачи выносятся в пост-обработку или compute shaders.

Перед записью результата фрагмент проходит серию тестов:

  • Depth test — сравнение Z-значения фрагмента с текущим значением в depth buffer. Если фрагмент дальше, он отбрасывается (раннее отбрасывание — early-Z). Это критически важно для производительности: позволяет не запускать фрагментный шейдер для невидимых пикселей (при условии, что шейдер не меняет глубину и не использует discard).
  • Stencil test — проверка по маске (stencil buffer), используемой для сложных эффектов — теней, зеркал, порталов, выделения объектов.
  • Scissor test, alpha test — дополнительные условия отсечения.

Запись в буфер кадра (Framebuffer Operations)​

Если фрагмент прошёл все тесты, его цвет записывается в буфер кадра (framebuffer). Framebuffer — это совокупность буферов:

  • Color buffer — хранит итоговый цвет (обычно RGBA16F или RGBA8),
  • Depth buffer — хранит Z-значения (обычно 24 или 32 бита),
  • Stencil buffer — 8-битная маска.

Запись может включать:

  • Blending — смешивание нового цвета со старым (например, src * alpha + dst * (1 - alpha)),
  • Logic operations — побитовые операции (редко используются),
  • Dithering — добавление шума для уменьшения полос (banding) при 8-битной цветопередаче.

Современные рендереры редко рисуют сразу в "экран". Вместо этого используется рендер в текстуру (render-to-texture):

  • сначала сцена рендерится в offscreen framebuffer (например, для теней — в depth-only buffer),
  • затем результат используется как текстура в основном проходе (shadow mapping),
  • многократные проходы (multipass rendering) позволяют реализовать deferred shading, screen-space отражения (SSR), SSAO.

Постобработка и вывод​

После завершения всех геометрических проходов выполняется постобработка (post-processing): серия эффектов, применяемых к уже сформированному изображению как к текстуре. Типичные этапы:

  • Tone mapping — преобразование HDR-значений в LDR для дисплея (ACES, Reinhard),
  • Bloom — имитация рассеяния света в объективе,
  • Color grading — коррекция цвета по 3D-таблице (LUT),
  • Anti-aliasing — сглаживание — MSAA (на этапе растеризации), FXAA/SMAA (пост-обработка), TAA (temporal, с учётом предыдущих кадров),
  • Motion blur, depth of field — имитация оптики.

Затем изображение передаётся в систему отображения:

  • При включённой вертикальной синхронизации (vsync) кадр ожидает начала нового цикла развёртки дисплея.
  • Используется двойная буферизация (front/back buffer): пока один буфер отображается, следующий рендерится. При тройной — добавляется промежуточный, чтобы избежать ожидания.
  • На мобильных устройствах и VR применяется асинхронная смена буферов (Adaptive Sync, G-Sync, FreeSync) — дисплей подстраивает частоту обновления под FPS приложения, устраняя tearing и stuttering.

Отклонения от классического конвейера​

Классический растеризационный конвейер — не единственный путь. Рассмотрим альтернативы:


Compute-based rendering​

Вместо фиксированного конвейера приложение использует compute shaders — программы общего назначения, выполняемые на GPU без привязки к графическим этапам. В них можно реализовать:

  • Полностью кастомный рендерер (например, software rasterizer на GPU),
  • Гибридные подходы: растеризация основной геометрии + ray tracing для отражений,
  • GPGPU-ускоренные эффекты — частицы, ткань, волосы, физика жидкости.

Vulkan и DX12 предоставляют тесную интеграцию compute и graphics queues, позволяя переключаться между ними в рамках одного кадра.


Трассировка лучей (Ray Tracing)​

В отличие от растеризации, где лучи "идут от камеры к объектам" только косвенно (через Z-buffer), в ray tracing каждый пиксель порождает луч, который проходит через сцену, сталкивается с объектами, отражается, преломляется — имитируя реальные законы оптики.

Этапы ray tracing pipeline:

  1. Генерация первичных лучей (по одному на пиксель или сэмпл),
  2. Пересечение лучей с геометрией (через BVH — bounding volume hierarchy),
  3. Для каждой точки пересечения — расчёт цвета (освещение, материал),
  4. Генерация вторичных лучей (отражение, преломление, тень),
  5. Рекурсивное повторение до предела глубины или порога энергии.

Проблема: вычислительная сложность. Даже с аппаратным ускорением (RT-ядра) полный path tracing в реальном времени невозможен. Поэтому применяется гибридный рендеринг:

  • Основная видимость — растеризация,
  • Отражения, тени, глобальное освещение — ray tracing,
  • Шум от недостаточного числа сэмплов — подавляется denoising-нейросетями (OptiX, XeSS).

Deferred Rendering​

Альтернативная организация конвейера, где сначала в G-buffer записываются геометрические и материал-параметры (позиция, нормаль, albedo, roughness...), а освещение рассчитывается отдельно, уже в screen space. Это позволяет использовать сотни источников света без повторного рендеринга геометрии — но требует больших объёмов памяти и плохо совместимо с прозрачностью.


Текстуры и материалы​

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

Термин "текстура" в компьютерной графике исторически возник как аналог тканевой текстуры — повторяющегося узора, накладываемого на поверхность. Сегодня же под текстурой понимается любой растровый ресурс, используемый в шейдере для модуляции параметров отрисовки. Это может быть изображение, но также — карта нормалей, карта высот, карта шероховатости, таблица поиска цвета (LUT), маска анимации, шум Перлина в сжатом виде и даже данные для вычислений (например, таблица интегралов для IBL).


Семантические роли текстур​

Не все текстуры "красивые". Некоторые полностью невидимы пользователю, но критичны для физики отображения. Условно их можно разделить на группы по назначению:

  • Цветовые текстуры — определяют базовый визуальный облик.

    • Albedo / Base Color — чистый цвет поверхности без теней и освещения. В PBR-подходе этот канал не должен содержать теней, бликов или ambient occlusion — только "фотометрически нейтральная" информация.
    • Diffuse — устаревший термин из non-PBR-рендеринга; часто включал в себя и влияние окружающего света, что затрудняло повторное освещение.
    • Detail maps — мелкомасштабные текстуры, накладываемые поверх основных для увеличения разрешения (например, царапины на металле при близком рассмотрении).
  • Геометрические текстуры — имитируют или изменяют форму поверхности.

    • Normal map — хранит направления нормалей в касательном пространстве (tangent space), позволяя создавать иллюзию рельефа без увеличения числа полигонов. Каждый пиксель кодирует вектор (X, Y, Z), преобразуемый в пространство камеры и используемый при расчёте освещения.
    • Height map / Displacement map — одно- или многоканальная карта, задающая смещение вершин (в tessellation или геометрических шейдерах) или фрагментов (в parallax mapping). Height map — грубая аппроксимация, displacement — реальное изменение геометрии.
    • Ambient Occlusion (AO) map — премаппинг затемнённых участков (стыки, углубления), где мало отражённого света. Используется для усиления ощущения глубины, особенно при слабом освещении. В современных движках часто заменяется на screen-space AO (SSAO, HBAO+), но pre-baked AO остаётся важен для статичных сцен.
  • Физические параметры — ключевые для PBR.

    • Roughness map — степень шероховатости поверхности (0 — идеально гладкая, 1 — матовая). Определяет форму бликов и рассеяние отражённого света.
    • Metallic map — бинарная или градиентная карта, указывающая, является ли участок металлом (1) или диэлектриком (0). В PBR металлы не имеют диффузного отражения — весь свет либо отражается, либо поглощается.
    • Specular — устаревший аналог roughness+metallic в non-PBR; задавал интенсивность и цвет зеркального отражения напрямую.
  • Управляющие текстуры — не несут визуальной информации, но управляют логикой отрисовки.

    • Alpha map — канал прозрачности. Может использоваться для alpha testing (discard фрагментов с alpha < порога), alpha blending (полупрозрачность) или alpha-to-coverage (антиалиасинг прозрачных краёв).
    • Mask maps — объединяют несколько параметров в один канал (например, R — metallic, G — roughness, B — AO) для экономии памяти и количества сэмплов.
    • Vertex color / Lightmap — запечённое освещение, нанесённое непосредственно на UV-развёртку. Используется в статичных сценах (архитектура, уровни игр) для экономии ресурсов.

Важно: ни одна из этих карт не существует изолированно. Их комбинация образует материал — логический объект, связывающий набор текстур, параметры шейдера, логику смешивания и реакцию на освещение.


Материал как программируемая сущность​

В ранних системах (OpenGL 1.x, DirectX 7) материал задавался фиксированным набором параметров — diffuse color, specular color, shininess, emissive. Это был material state — глобальное состояние конвейера, изменяемое вызовами вроде glMaterialfv.

С переходом к программируемым шейдерам (начиная с DirectX 8 / OpenGL 2.0) понятие материала стало контекстно-зависимым. Материал — это интерфейс между данными и шейдером:

  • Он определяет, какие текстуры должны быть привязаны к каким юнитам (texture units),
  • Какие uniform-параметры передать (например, float roughnessMultiplier),
  • Какой шейдерный вариант использовать (например, "металл", "стекло", "кожа" — с разной логикой в fragment shader),
  • Как обрабатывать специальные случаи — параллакс, subsurface scattering, emissive glow.

Современные движки (Unreal Engine, Unity HDRP, Filament) используют material graphs или shader variants — системы, позволяющие визуально или декларативно собирать материалы, автоматически генерируя шейдерный код под конкретный набор параметров. Это позволяет:

  • Избегать ветвлений в шейдере (if/else), снижающих производительность,
  • Компилировать только нужные комбинации (например, материал без emissive не включает соответствующий код),
  • Обеспечивать единообразие на всём проекте.

Материал также несёт семантическую нагрузку для инструментов: система освещения может автоматически применять IBL только к PBR-материалам, а система постобработки — исключать emissive-поверхности из tone mapping.


Текстурные координаты и развёртка​

Текстура — двумерный массив данных. Чтобы наложить его на трёхмерную поверхность, требуется отображение — соответствие между точками поверхности и точками текстуры. Это достигается с помощью UV-координат — двухмерных значений (U, V), приписанных каждой вершине, интерполируемых при растеризации.

UV-координаты нормализованы — (0,0) — нижний левый угол текстуры, (1,1) — верхний правый (в OpenGL; в DirectX — (0,0) вверху, что требует вертикального флипа при загрузке). Значения вне [0,1] обрабатываются в соответствии с режимом наложения (wrapping mode):

  • REPEAT — текстура повторяется (для бесшовных материалов: кирпич, трава),
  • CLAMP_TO_EDGE — крайние пиксели растягиваются (для некафельных изображений: лица, интерфейс),
  • MIRROR_REPEAT — зеркальное повторение (редко, для специфических эффектов).

Качество наложения зависит от UV-развёртки — процесса "разглаживания" 3D-поверхности в 2D-плоскость. Плохая развёртка (с перекрытиями, искажениями, разрывами) приводит к артефактам — растяжению текстур, видимым швам, несоответствию масштаба. В профессиональном 3D-моделировании этому уделяется столько же внимания, сколько самой геометрии.

Современные подходы включают:

  • UDIM — система, позволяющая использовать несколько текстурных плиток (tiles) для одной модели, нумеруемых по схеме U+1000×V. Это позволяет достичь высокого разрешения (8K+ на объект) без ограничений GPU на размер текстуры (макс. 16K в 2025 г.).
  • Triplanar mapping — наложение текстур по трём осям (X, Y, Z) с весами, зависящими от нормали. Устраняет необходимость UV-координат для простых объёмных объектов (скалы, террейн).
  • World-space UVs — координаты зависят от мирового положения, а не от развёртки. Применяется для procedural текстуризации (шум, градиенты).

Сжатие и хранение текстур​

Текстуры — основной объём видеопамяти. Изображение 4K (3840×2160) в формате RGBA8 занимает ~63 МБ. При этом в сцене может быть сотни таких текстур.

Для экономии применяется аппаратное сжатие текстур — форматы, декодируемые GPU "на лету" при выборке:

  • S3TC / DXT (BC1–BC7) — стандарт де-факто на PC и консолях. BC1 — 4 бита/пиксель (RGB + 1-битная альфа), BC7 — 8 бит/пиксель (высококачественное RGBA). BC4/5 — для одно- и двухканальных данных (roughness, normal.xy).
  • ETC2 / EAC — стандарт для OpenGL ES и мобильных устройств (Android), требует меньших ресурсов декодера.
  • ASTC — адаптивное сжатие, поддерживает произвольные размеры блоков (от 4×4 до 12×12), балансируя качество и объём. Широко используется в мобильной графике и WebGPU.
  • Basis Universal / KTX2 — транспортные форматы, сжимающие текстуру один раз, а затем транскодирующие в BCn/ETC2/ASTC на целевом устройстве. Важны для веба и кроссплатформенных приложений.

Сжатие — не PNG или JPEG. Оно потеряющее, но оптимизировано под визуальное восприятие и равномерную ошибку. Особенно критично для normal map: даже небольшие искажения цвета приводят к "пузырькам" и шуму на поверхности.


Mipmapping​

Когда текстурированный объект удаляется от камеры, один пиксель экрана может покрывать сотни пикселей текстуры. Прямая выборка (nearest/linear) вызывает алиасинг — мерцание, шум, муар.

Mipmapping решает это, заранее создавая иерархию уменьшенных копий текстуры (mip levels): 1024×1024 → 512×512 → 256×256 → … → 1×1. При рендеринге GPU автоматически выбирает уровень, соответствующий экранной площади одного текселя (texture element), и применяет фильтрацию между уровнями (trilinear filtering).

Ключевые свойства:

  • Уменьшает шум и повышает стабильность изображения,
  • Улучшает кэширование текстур: близкие пиксели читают данные из одного блока памяти,
  • Требует ~33% дополнительного объёма (сумма ряда 1 + 1/4 + 1/16 + … = 4/3),
  • Может использоваться селективно — например, отключать для текстур интерфейса (где важна чёткость), или использовать только чётные уровни для экономии.

Современные API позволяют генерировать mipmaps на GPU (автоматически при загрузке) или управлять ими вручную — например, для streaming-систем, где уровни подгружаются по мере надобности.


Атласы и массивы текстур​

Для снижения числа переключений текстур (дорогая операция — state change) используются объединения:

  • Texture atlas — одна большая текстура, содержащая множество мелких (иконки, спрайты, GUI-элементы). Требует аккуратной UV-развёртки и padding между элементами во избежание "утечки" соседних пикселей при фильтрации.
  • Array texture — стек одинаковых по размеру текстур, доступных по индексу в шейдере (sampler2DArray). В отличие от атласа, не страдает от артефактов фильтрации на границах, поддерживает mipmapping по элементам. Используется для terrain blending, skinning в 2D-анимации, material layering.
  • Sparse textures / Virtual texturing — технология, при которой только видимые части огромной текстуры (например, 128K×128K) подгружаются в память. Применяется в симуляторах, open-world играх (id Tech 5, Unreal Engine 5 Nanite+Virtual Shadow Maps).

Unreal Engine 5 ввела Virtual Texture Streaming, где текстуры разбиваются на страницы (pages), и рендерер динамически определяет, какие страницы нужны для текущего кадра — на основе расстояния, угла, важности объекта. Это позволяет использовать текстуры общим объёмом в десятки гигабайт даже на консолях.


Анимация и динамические текстуры​

Не все текстуры статичны. Анимированные текстуры — последовательность кадров, переключаемых по времени или событию:

  • Sprite-листы (spritesheets) — решётка кадров анимации, переключаемых через смещение UV,
  • Texture arrays как анимационные слои — индекс кадра передаётся как uniform,
  • Render-to-texture — динамическая генерация — отражения в "зеркале", проекции (light cookies), UI-рендеринг в 3D-пространство (например, экраны в киберпанке),
  • GPU-driven animation — изменение текстуры внутри compute shader (например, волна на воде, тепловое искажение).

Особый класс — procedural текстуры. Они генерируются по формуле или алгоритму в шейдере — шум Перлина, вороной-ячейки, градиенты, фракталы. Преимущества:

  • Бесконечное разрешение (без потери качества при приближении),
  • Минимальный объём памяти,
  • Параметрическое управление (например, "сделать камень более треснувшим" — изменить один слайдер).

Недостатки — вычислительная нагрузка, сложность контроля, невозможность тонкой художественной правки. Часто используется как база, дополняемая hand-painted деталями.


Проблемы и ограничения​

Несмотря на зрелость технологии, текстуризация сталкивается с системными ограничениями:

  • Лимиты аппаратуры: максимальный размер текстуры (16384×16384 на большинстве GPU 2025 г.), число одновременно привязанных текстур (16–128 в зависимости от API и шейдера), пропускная способность памяти (memory bandwidth) — часто узкое место при использовании высокочастотных карт (normal, roughness).
  • Синхронизация CPU–GPU — загрузка текстуры — асинхронная операция, но может вызывать stall, если шейдер пытается использовать её до завершения передачи.
  • Кроссплатформенность: BCn не поддерживаются на iOS (там PVRTC/ASTC), ETC2 — на старых Adreno. Требуется runtime feature detection и fallback-форматы.
  • Лицензирование и инструменты: многие advanced-форматы (BC6H/7) требуют лицензирования от Khronos или Microsoft; генерация качественных mipmaps и normal maps требует специализированных инструментов (Substance 3D, xNormal, NVIDIA Texture Tools).