Знакомимся с Real-time render [Черновик]

Привет всем подпольным дефолдерам и не только :smiling_face_with_sunglasses:
В общем, не я заварил эту кашу, мужики :face_in_clouds:

Начал читать книгу:


Тема, как по мне, трудная и точно на несколько месяцев для меня, к тому же, еще и на английском. Дорогу осилит идущий, как говорится. Этот раздел нужен, чтобы заложить фундамент, с помощью которого мы освоим магию — шейдеры. Книга, ориентирована для 3D, но мы же дальновидные дефолдеры, рано или поздно нам придётся столкнуться и с 3D :relieved_face:
Буду выкладывать под этим постом обработанный текст, со своими вопросами и ответами, с помощью которого каждый из нас сможет ознакомиться с этой темой или углубить свои знания.

Что такое Real-time Rendering?

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

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

За этот процесс отвечает технология, называемая рендеринг в реальном времени (real-time rendering).

Что это значит?

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

Чтобы достичь этого эффекта, движок игры (game engine) должен:

  • очень быстро обновлять сцену (например, перемещать объекты, менять освещение),
  • затем отрисовывать её кадр за кадром (то есть рендерить),
  • и отображать результат на экране игрока — 60 раз в секунду и более (частота обновления экрана, измеряется в герцах — Hz).

Почему это важно?

Чем выше частота кадров (FPS — frames per second), тем плавнее и более отзывчиво игра воспринимается. Если частота рендера не поспевает за частотой обновления экрана, появляется лаг, рывки, и ощущение “тормозов”.

Поэтому real-time rendering — ключевая технология для всех интерактивных приложений, особенно игр, VR/AR и симуляторов.

Как связана частота обновлений hz real-time рендером?

Вопрос заданный chat gpt:

Частота обновления экрана (Hz) и real-time rendering (RTR) — это два ключевых аспекта визуального вывода, и они напрямую влияют на то, насколько плавно и синхронно игра (или другое интерактивное приложение) ощущается пользователем.

Параметр Что означает
Частота обновления (Hz) Сколько раз в секунду монитор может обновить изображение (например, 60 Гц = 60 раз в секунду).
Частота кадров (FPS) Сколько кадров в секунду рендерит игра/движок.

Real-time rendering стремится к тому, чтобы каждая сцена отрисовывалась и отображалась сразу, как только готова, максимально синхронно с частотой обновления экрана. Вот как это работает:

1. Идеальный сценарий: FPS = Hz

  • Если рендерится 60 кадров в секунду и экран обновляется 60 раз в секунду, каждый кадр показывается сразу после его отрисовки.
  • :green_circle: Итог: супер плавно, без разрывов и задержек.

2. FPS < Hz (медленный рендеринг)

  • Игра рендерит, например, 30 FPS, а экран обновляется 60 Гц.
  • В этом случае каждый кадр показывается дважды, что вызывает дёргания (stutter).
  • :red_circle: Итог: плохая отзывчивость и визуальный дискомфорт.

3. FPS > Hz (слишком быстрый рендеринг)

  • Игра рендерит 120 FPS, экран — только 60 Гц.
  • Некоторые кадры “пропускаются”, может возникнуть разрыв изображения (tearing), если нет вертикальной синхронизации (VSync).
  • :yellow_circle: Итог: рендер работает отлично, но экран не поспевает — нужны дополнительные технологии (например, G-Sync, FreeSync).

2. Основные моменты о графическом конвейере рендеринга (Graphics Rendering Pipeline):

  • Что это: Графический конвейер — ключевой компонент реального времени рендеринга, который преобразует 3D-сцены (объекты, источники света, камера) в 2D-изображение.
  • Цель: Сгенерировать (render) двумерное изображение с учетом геометрии объектов, характеристик окружения и положения камеры.

  • Визуализация:
    • Левая картинка: виртуальная камера находится в вершине усечённой пирамиды (frustum), ограничивающей видимый объём.
    • Отрисовываются только объекты внутри этого объёма.
    • Правая картинка: изображение, которое “видит” камера — объекты вне frustum (например, красный пончик) не отображаются.
  • Влияющие факторы: Вид объектов зависит от материала, текстур, источников света и уравнений затенения.

2.1 Архитектура графического конвейера рендеринга

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

Основные этапы рендеринга (см. Рисунок 2.2):

Этап Описание
Application Управляется приложением, реализуется на CPU, отвечает за логику, физику, анимацию и т.д.
Geometry Processing Обработка геометрии: трансформации, проекции, подготовка примитивов (например, треугольников). Обычно выполняется на GPU.
Rasterization Определение пикселей, попадающих внутрь примитивов, передача их на следующий этап.
Pixel Processing Обработка каждого пикселя: вычисление цвета, тест глубины, смешивание цветов. Выполняется на GPU.

Дополнительные детали:

  • Каждый этап может содержать свои подэтапы и быть параллелизирован.
  • Скорость рендеринга измеряется в FPS (frames per second) или Hertz (Hz).
  • Application-этап обычно на CPU с многопоточностью.
  • Geometry, Rasterization и Pixel Processing — на GPU.
  • Более подробное описание GPU-обработки в следующей главе.

2.1. Этап Application в графическом конвейере

  • Контроль разработчика: Этот этап полностью управляется разработчиком и обычно выполняется на CPU, что даёт полную свободу реализации и возможность оптимизации.
  • Влияние на последующие этапы: Изменения на этом этапе могут уменьшить количество треугольников для рендеринга, улучшая производительность.
  • Возможности GPU: Некоторые задачи приложения могут выполняться на GPU через отдельный модуль — compute shader, который использует параллелизм GPU.
  • Основная задача: Формирование rendering primitives — точек, линий, треугольников, которые передаются на этап обработки геометрии.
  • Особенности реализации: В отличие от других этапов, application-этап обычно не разбит на подэтапы, но для повышения производительности может выполняться параллельно на нескольких ядрах CPU (superscalar).
  • Типичные задачи:
    • Обработка коллизий (collision detection) и генерация ответов.
    • Обработка ввода с устройств (клавиатура, мышь, VR-шлемы).
    • Выполнение алгоритмов ускорения (например, culling).
  • Связь с другими главами: Подробнее о многопроцессорной реализации и алгоритмах — в последующих главах (например, Chapter 18.5 и Chapter 19).

2.3. Этап Geometry Processing (Обработка геометрии)

  • Расположение: Выполняется на GPU.
  • Ответственность: Основная часть операций с примитивами и вершинами (точками, линиями, треугольниками).
  • Функциональные подэтапы:
    1. Vertex Shading — обработка вершин (например, трансформации, освещение).
    2. Projection — проекция 3D-координат в 2D-пространство экрана.
    3. Clipping — отсечение частей примитивов, выходящих за пределы видимого объёма.
    4. Screen Mapping — преобразование координат в экранные пиксели.

Эти подэтапы формируют конвейер внутри этапа обработки геометрии, обеспечивая подготовку примитивов для последующего растеризации.
image

2.3.1 Vertex Shading (Обработка вершин)

  • Основные задачи:
    • Вычислить позицию вершины.
    • Определить дополнительные данные вершины (нормали, текстурные координаты и др.).
  • Исторический контекст: Раньше освещение вычислялось на вершинах, а цвета интерполировались по треугольнику.
  • Современный подход: Vertex shader — программируемый блок GPU, который может выполнять любые операции с вершинами, включая анимацию.
  • Преобразования координат:
    • Модель изначально в model space (локальные координаты).
    • Применяется model transform — позиционирование и ориентация модели в мире.
    • После трансформации модель находится в world space (мировые координаты).
  • Камера и вид:
    • Камера имеет позицию и направление в world space.
    • Применяется view transform — перемещает и ориентирует сцену так, чтобы камера была в начале координат, смотрела вдоль оси (обычно -z).
    • Результат — view space (или camera space).
  • Проекция:
    • Преобразование view volume (объём видимости) в единичный куб.
    • Два основных типа:
      • Orthographic (параллельная) — сохраняет параллельность линий.
      • Perspective (перспективная) — объекты дальше кажутся меньше, линии сходятся в точке.
    • Проекция выражается матрицей 4×4.
  • Клиппинг: После проекции координаты называются clip coordinates (однородные координаты), готовые к отсечению (clipping).
  • Результат: Vertex shader должен выводить координаты в clip space для следующего этапа.

Иллюстрации:

  • Рисунок 2.4: Переход от world space к view space с помощью view transform.

  • Рисунок 2.5: Слева — ортографическая проекция, справа — перспективная.

2.3.2 Optional Vertex Processing (Дополнительная обработка вершин)

  • После базового vertex shading могут выполняться дополнительные опциональные этапы на GPU:

    1. Tessellation (Тесселяция):
    • Разбивает объекты на большее количество треугольников для улучшения качества.
    • Позволяет создавать гладкие поверхности с нужным уровнем детализации.
    • Использует несколько шейдеров: hull shader, tessellator, domain shader.
    • Количество треугольников зависит от расстояния до камеры (больше — ближе, меньше — дальше).
    1. Geometry Shader (Геометрический шейдер):
    • Работает с примитивами (точки, линии, треугольники).
    • Может создавать новые вершины и примитивы.
    • Пример использования — генерация частиц (например, имитация взрыва фейерверка).
    • Преобразует точки в квадраты (2 треугольника), которые покрывают несколько пикселей для более реалистичного отображения.
    1. Stream Output (Потоковый вывод):
    • Позволяет выводить обработанные вершины в массив для дальнейшей обработки CPU или GPU.
    • Используется для симуляций частиц и других сложных эффектов.
  • Эти этапы необязательны и могут использоваться в зависимости от возможностей GPU и задач разработчика.

2.3.3 Clipping (Отсечение)

  • Цель: Передать на растеризацию только примитивы, целиком или частично находящиеся внутри видимого объёма (view volume).
  • Что происходит:
    • Примитивы полностью вне объёма не передаются дальше (не рендерятся).
    • Примитивы, частично выходящие за границы, обрезаются (clipped).
    • Например, линия с одной вершиной внутри объёма, а другой — вне, обрезается так, чтобы вершина вне объёма была заменена на точку на границе.
  • Использование проекционной матрицы:
    • Примитивы отсеиваются относительно unit cube (единичного куба) после проекции.
    • Это упрощает и стандартизирует процесс отсечения.
  • Технические детали:
    • Используются 4-значные однородные координаты.
    • Четвёртая координата нужна для правильной интерполяции и отсечения в перспективном пространстве.
    • После отсечения выполняется perspective division — преобразование в нормализованные координаты устройства (normalized device coordinates).
  • Результат: Примитивы, находящиеся в диапазоне от (-1, -1, -1) до (1, 1, 1) в нормализованных координатах, готовы к отображению.

Иллюстрация (Рисунок 2.6):

  • Слева: примитивы до отсечения, часть выходит за пределы unit cube.
  • Справа: после отсечения примитивы обрезаны, новые вершины созданы на границах куба.

2.3.4 Screen Mapping (Отображение на экран)

Что происходит:

  • Примитивы, прошедшие отсечение, имеют координаты в трёхмерном пространстве (clip space).
  • Эти координаты преобразуются в screen coordinates — двумерные координаты на экране.
  • Координаты:
    • x и y — экранные координаты.
    • z — глубина (используется для буфера глубины).
  • Процесс:
    • Координаты сцены маппируются в окно вывода с минимальным (x_1, y_1) и максимальным (x_2, y_2).
    • Преобразование включает сдвиг и масштабирование.
  • Диапазоны:
    • В OpenGL z координата нормализуется в диапазон [z_1,z_2], обычно [0,1].
  • Результат: Примитивы готовы к растеризации — преобразованию в пиксели.

Иллюстрация (Рисунок 2.7):

  • Примитивы в единичном кубе после проекции.
  • Процесс отображения на экран с координатами (x_s, y_s).

Следующий этап — Растеризация (Rasterization):

  • Связь между координатами и пикселями.
  • Пример формулы для вычисления индекса пикселя из координаты:
    d=⌊c⌋, c=d+0.5d
    где d — индекс пикселя (целое число), c — плавающая точка внутри пикселя.

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

  • Цель: Найти все пиксели, покрываемые примитивом (например, треугольником), для последующей обработки.
  • Процесс растеризации делится на два этапа:
    1. Triangle Setup (Настройка треугольника): Подготовка данных для обхода треугольника.
    2. Triangle Traversal (Обход треугольника): Определение пикселей, попадающих внутрь треугольника.
  • Растеризация (или scan conversion): Преобразование вершин с глубиной и затенением в пиксели на экране.
  • Синхронизация: Растеризация служит точкой синхронизации между этапами обработки геометрии и пикселей.
  • Формирование треугольников: Треугольники формируются из трёх вершин и передаются на этап пиксельной обработки.

Иллюстрация (Рисунок 2.8):

  • Слева: разделение растеризации на triangle setup и triangle traversal.
  • Справа: этап пиксельной обработки разделён на pixel shading и merging.

2.4.1 Triangle Setup (Настройка треугольника)

  • Вычисляются дифференциалы, уравнения граней и другие данные треугольника.
  • Эти данные нужны для обхода треугольника (triangle traversal) и интерполяции параметров затенения.
  • Используется фиксированное аппаратное обеспечение.

2.4.2 Triangle Traversal (Обход треугольника)

  • Определяется, какие пиксели (или сэмплы) покрыты треугольником.
  • Для каждого покрытого пикселя создаётся фрагмент — часть пикселя, относящаяся к треугольнику.
  • Свойства фрагмента (глубина, данные затенения) интерполируются между вершинами.
  • Используются методы для корректной интерполяции перспективы.
  • Все фрагменты внутри треугольника отправляются на этап пиксельной обработки.

2.5 Pixel Processing (Обработка пикселей)

  • На этом этапе обрабатываются все пиксели, попавшие внутрь треугольника.
  • Включает:
    • Pixel shading — вычисление цвета и других свойств пикселя.
    • Merging — объединение результатов с уже существующими пикселями (например, с учётом глубины).

2.5.1 Pixel Shading (Пиксельное затенение)

  • Что происходит: Выполняются вычисления затенения для каждого пикселя с использованием интерполированных данных.
  • Исполнение: Запускается программируемый пиксельный шейдер (фрагментный шейдер) на ядрах GPU.
  • Возможности: Пиксельный шейдер может выполнять любые вычисления, например, текстурирование.
  • Текстурирование: Наложение одного или нескольких изображений на объект для создания реалистичных поверхностей.

  • Пример: На рисунке 2.9 показан дракон без текстур (слева вверху) и с наложенной текстурой (слева внизу), а справа — сама текстура.

2.5.2 Merging (Объединение)

  • Color buffer: Хранит информацию о цвете каждого пикселя — двумерный массив цветов.
  • Задача merging: Объединить фрагмент, вычисленный пиксельным шейдером, с текущим цветом в color buffer.
  • Z-buffer (буфер глубины): Хранит глубину (z-значение) для каждого пикселя, используется для определения видимости.
  • Алгоритм z-buffer:
    • При рендеринге примитива сравнивается z-значение нового фрагмента с текущим в буфере.
    • Если новый фрагмент ближе, цвет и глубина обновляются.
    • Если дальше — фрагмент отбрасывается.
  • Особенности:
    • Z-buffer и color buffer имеют одинаковый размер.
    • Z-buffer используется для правильного отображения перекрывающихся объектов.
    • Поддерживаются операции прозрачности, смешивания (blending) и другие.
  • Stencil buffer: Дополнительный буфер для сложных эффектов, например, масок.
  • Double buffering: Используется для плавного отображения — рисование происходит в back buffer, а затем происходит переключение с front buffer.

2.6 Проход через конвейер (Through the Pipeline)

  • Рассмотрен пример интерактивного CAD-приложения для проектирования вафельницы.
  • Основные этапы:
    • Application: Управление вводом пользователя, обновление параметров камеры и модели.
    • Geometry Processing: Преобразование вершин, проекция, затенение.
    • Rasterization: Определение пикселей, покрываемых примитивами.
    • Pixel Processing: Вычисление цвета пикселей и финальное отображение.
  • Каждый этап последовательно обрабатывает данные, передавая результат следующему.
  • Итоговое изображение отображается на экране.

Заключение

  • Конвейер рендеринга — результат десятилетий развития API и аппаратного обеспечения.
  • Помимо реального времени, существуют офлайн-рендеринг и новые методы (микрополигональные конвейеры, трассировка лучей).
  • Современные GPU позволяют программировать операции на всех этапах конвейера.

Глава 3: The Graphics Processing Unit (Графический процессор)

  • История: Аппаратное ускорение графики началось с интерполяции цветов по пикселям треугольника и отображения их.
  • Развитие: Появились специализированные графические процессоры (GPU), начиная с NVIDIA GeForce256, которые выполняют растеризацию и другие задачи.
  • Программируемость: Современные GPU поддерживают программируемые шейдеры, что повышает гибкость и эффективность.
  • Архитектура: GPU оптимизированы для параллельной обработки, особенно для операций с буфером глубины (z-buffer) и выборкой текстур.
  • Задержка (Latency): Важный фактор — время доступа к данным, которое влияет на производительность.
  • Шейдеры: Маленькие процессоры, выполняющие вычисления для вершин и пикселей, обрабатывают миллионы треугольников и пикселей.

3.1 Data-Parallel Architectures (Архитектуры с параллелизмом по данным)

  • GPU содержит тысячи шейдерных ядер (shader cores), которые обрабатывают данные параллельно.
  • Каждый шейдер — маленький процессор, обрабатывающий вершины или пиксели.
  • Для скрытия задержек при доступе к памяти используется переключение между группами потоков (warps).
  • Warps — группы из 32 потоков, которые выполняют одни и те же инструкции.
  • При задержке загрузки данных warp переключается на другой warp, что минимизирует простой.
  • Высокая параллельность и переключение потоков позволяют GPU эффективно использовать ресурсы.

Иллюстрация (Рисунок 3.1)

  • Показано выполнение инструкций для нескольких warps на шейдерных процессорах.
  • При возникновении задержки (stall) происходит переключение на другой warp.

GPU и конвейер рендеринга (Рисунок 3.2)

  • Этапы конвейера:
    • Полностью программируемые (зелёные): Vertex Shader, Tessellation, Geometry Shader.
    • Частично программируемые (жёлтые): Merger (слияние).
    • Фиксированные (синие): Clipping, Screen Mapping, Triangle Setup & Traversal, Pixel Shader.

3.2 Обзор конвейера GPU (GPU Pipeline Overview)

  • GPU реализует этапы обработки геометрии, растеризации и обработки пикселей, описанные в главе 2.
  • Эти этапы делятся на аппаратные стадии с разной степенью программируемости (см. Рисунок 3.2):
    • Программируемые: vertex shader, geometry shader, pixel shader.
    • Опциональные: tessellation, geometry shader.
    • Фиксированные: clipping, triangle setup, triangle traversal, screen mapping.
    • Мерджер: не программируемый, но конфигурируемый этап слияния цветов, буфера глубины и других.
  • Логическая модель конвейера — то, что видит программист через API.
  • Физическая модель — реализация аппаратного обеспечения, может отличаться.
  • Программируемые стадии позволяют гибко управлять рендерингом, что важно для современных GPU.
  • Конвейер GPU эволюционировал от жёстко заданных операций к гибким программируемым стадиям.

3.3 Программируемый этап шейдеров (The Programmable Shader Stage)

  • Современные шейдеры используют унифицированный дизайн, где vertex, geometry и tessellation шейдеры имеют общую модель программирования.
  • Процессор, реализующий эту модель, называется common-shader core (например, в DirectX).
  • GPU содержит тысячи таких ядер, которые могут динамически распределять нагрузку между vertex и pixel шейдерами.
  • Шейдеры пишутся на языках высокого уровня (HLSL, GLSL, Cg) и компилируются в промежуточный язык (IL, DXIL).
  • Основные типы данных: 32-битные скаляры и векторы, матрицы, текстурные координаты, цвета и др.
  • Вызов отрисовки (draw call) запускает выполнение шейдера на группе примитивов.
  • Входы шейдера делятся на:
    • Uniform inputs: постоянные значения для всех примитивов.
    • Varying inputs: значения, меняющиеся для каждой вершины или пикселя.
  • Виртуальная машина шейдера управляет регистрами:
    • Временные регистры для вычислений.
    • Регистры для входных и выходных данных.
    • Константные регистры для uniform-переменных.
    • Текстурные регистры для выборки текстур.
  • Поддерживаются операции с плавающей точкой, арифметика, функции, ветвления (flow control).
  • Flow control:
    • Static: одинаковое выполнение для всех потоков.
    • Dynamic: разные пути выполнения в зависимости от входных данных, более гибко, но может снижать производительность.

3.4 Эволюция программируемого шейдинга и API

  • Идея программируемого шейдинга возникла в 1984 году с концепцией shade trees (деревья затенения).
  • RenderMan Shading Language (конец 1980-х) — основа для современных шейдерных языков.
  • Первый успешный GPU с программируемыми шейдерами — 3dfx Voodoo (1996), популярность получил с Quake.
  • В 2001 NVIDIA GeForce 3 — первый GPU с программируемыми vertex шейдерами.
  • DirectX 8.0 и OpenGL расширения ввели поддержку шейдеров.
  • Ранние шейдеры были ограничены, без поддержки ветвлений (flow control).
  • DirectX 9.0 и Shader Model 2.0 добавили полноценные vertex и pixel шейдеры.
  • Shader Model 3.0 (2004) ввёл динамический flow control, увеличил возможности.
  • Shader Model 4.0 (2006) добавил geometry shader и stream output.
  • Появились новые API: OpenGL ES (для мобильных), Vulkan (низкоуровневый, кроссплатформенный), Metal (Apple).
  • WebGL — браузерный API для графики, основанный на OpenGL ES.
  • Современные шейдерные языки: HLSL (Microsoft), GLSL (OpenGL), SPIR-V (Vulkan).
  • Визуальные редакторы шейдеров (например, mental mill) облегчают создание эффектов.

Иллюстрации:


Рисунок 3.4 — пример дерева затенения и соответствующей программы шейдера.


Рисунок 3.5 — временная шкала развития API и графического железа.


Рисунок 3.6 — визуальный редактор шейдеров.

3.5 Vertex Shader (Вершинный шейдер)

  • Роль: Первый программируемый этап в конвейере, обрабатывает входящие вершины.
  • Входные данные: Массивы позиций, цветов, нормалей, текстурных координат и др.
  • Задачи:
    • Преобразование координат из локального пространства модели в однородные координаты клип-пространства.
    • Модификация, создание или игнорирование значений, связанных с вершинами (цвет, нормали, текстуры).
  • Особенности:
    • Вершинный шейдер обрабатывает каждую вершину независимо.
    • Не может создавать или уничтожать вершины.
  • Применение:
    • Генерация объектов и их деформация.
    • Анимация скиннинга и морфинга.
    • Процедурные деформации (флаги, вода, огонь).
    • Создание частиц.
    • Эффекты искажения (линзы, дым, волны).
    • Применение высотных карт для ландшафта.

  • Пример: На рисунке 3.8 показаны эффекты вершинного шейдера — простое смещение и шумовое искажение модели чайника.

3.6 Этап тесселяции (The Tessellation Stage)

  • Позволяет рендерить криволинейные поверхности, разбивая их на треугольники.
  • Опциональный этап, впервые появился в DirectX 11 и поддерживается в OpenGL 4.0+.
  • Позволяет экономить память и вычисления, генерируя больше треугольников только там, где нужно (например, ближе к камере).
  • Состоит из трёх шейдеров:
    • Hull shader: принимает патч (набор контрольных точек), задаёт параметры тесселяции и модифицирует патч.
    • Tessellator: фиксированная функция, генерирует новые вершины по параметрам.
    • Domain shader: вычисляет итоговые позиции новых вершин, нормали, текстурные координаты и др.
  • Позволяет контролировать уровень детализации (tessellation factors).
  • Пример: на рисунке 3.10 показан эффект изменения факторов тесселяции на модели чайника.
  • На рисунке 3.11 — исходная сетка и результат тесселяции с subdivision.