Directx 11 что это такое
Обновлено: 21.11.2024
Новый графический API содержит новые модные словечки. Мы расскажем вам, что они означают и какое значение они имеют для вашего игрового процесса.
Как только вы думаете, что поняли весь жаргон, связанный с 3D-графикой, на рынок хлынут новые термины и технологии.
AMD активно поставляет графические процессоры DirectX 11 практически во всех ценовых категориях, а карты на базе новых компонентов GTX 470 и GTX 480 DX11 от Nvidia наконец-то стали доступны. Между тем, рост продаж Windows 7 был необычайным — самой быстро продаваемой операционной системой Microsoft в истории. Учитывая, что Windows 7 — это то, чем должна была быть Vista, также можно утверждать, что DirectX 11 — это то, чем должна была быть DX10.
Когда игры DirectX 10 вышли на улицы, новый API дал пользователям незначительные улучшения качества изображения при значительном снижении производительности. Крошечное улучшение визуальной точности не компенсировало снижение производительности. С другой стороны, DirectX 11 предлагает пользователям несколько очень интересных потенциальных улучшений, но также обещает более высокую производительность, даже если у вас нет графического процессора DirectX 11.
Помимо новой графики, в API появились новые модные словечки: тесселяция, SSAO, HDAO и постобработка. Это последнее модное слово является крылатой фразой для многих небольших, но крутых эффектов, которые стали возможными с помощью современных программируемых графических чипов.
Камера Logitech StreamCam
Эта веб-камера выдает изображение 1080p со скоростью 60 кадров в секунду.
Она оптимизирована для всех популярных программ для потоковой передачи (OBS, Xsplt, Streamlabs и т. д.).
Мы подробнее рассмотрим эти модные словечки, чтобы понять, что они на самом деле дают, а также обсудим влияние на производительность использования высокопроизводительных графических процессоров AMD и Nvidia.
Тесселяция
Тесселяция, по сути, создает что-то из ничего, или, точнее, большее из меньшего. Аппаратная тесселяция, необходимая для DirectX 11, означает, что графический процессор может генерировать больше треугольников из существующей геометрии с помощью механизма аппаратной тесселяции, который является частью графического чипа. Теперь генерировать больше треугольников для плоской поверхности бессмысленно — в конце концов, плоский квадрат выглядит как плоский квадрат, будь то два треугольника или 2000. Что более интересно, так это создание большего количества треугольников для реальной 3D-модели. Давайте рассмотрим простой пример — булыжную поверхность из комплекта разработчика DirectX от Microsoft.
Нанесение рельефа
Карта смещения
Модуль тесселяции в аппаратном обеспечении DX11 способен генерировать гораздо больше треугольников из существующей геометрии, как показано на экране в левом нижнем углу, чтобы создавать объекты, которые на самом деле являются трехмерными.
В правом верхнем углу экрана у нас есть плоская поверхность, которая выглядит несколько более реалистично благодаря применению карты рельефа. Рельефные карты заставляют вас думать, что плоский многоугольник имеет глубину, моделируя то, как свет падает на неровный объект (например, булыжник). плоская поверхность. Если геометрия мозаична, булыжники на самом деле трехмерные, как показано на нижнем правом экране.
Тесселяция в изображении булыжника выполняется с помощью метода, известного как картирование смещения. Карта смещения — это просто специальная карта текстуры в градациях серого, в которой различные оттенки серого определяют степень смещения геометрии.
Брусчатка — это хорошо, но увидим ли мы когда-нибудь отличия в реальных играх? Давайте посмотрим на недавно вышедший Metro 2033 (ниже). Левое изображение — игра с отключенной тесселяцией; тесселяция включена на правом изображении. Обратите внимание, что на втором плане объект более округлый. Эффект здесь несколько тонкий, но суть остается неизменной: это начало конца многоугольных головок. Тесселяция означает, что когда-нибудь головы персонажей станут круглее.
Без тесселяции
С тесселяцией
В этом кадре из Metro 2033 вы можете увидеть, как тесселяция позволяет создавать изогнутые края.
Еще один пример тесселяции из DirectX SDK демонстрирует технику, известную как поверхности подразделения (ниже). Ключевая идея этой техники состоит в том, чтобы начать с базового набора полигонов, а затем разделить их таким образом, чтобы это имело смысл для рассматриваемого объекта. В этой модели персонажа мы накладываем текстуры поверх видимого каркаса. Вы можете увидеть дополнительную геометрию, добавленную на правом экране, а также более натуралистичные закругленные элементы.
Другое использование тесселяции
Тесселяция отлично подходит для создания более круглых голов и более реалистичных булыжников. Но у него есть и другие применения. Возьмем, к примеру, воду. Вместо того, чтобы использовать пиксельные шейдеры для создания более красивой воды, просто добавьте больше треугольников… намного больше треугольников, как в случае с демонстрацией Nvidia Island.
Без тесселяции
С тесселяцией
Тесселяция делает воду более реальной в демоверсии Nvidia Island.
В новой гоночной игре Dirt 2 автомобили, едущие по воде, будут создавать волны в версии игры DirectX 11, используя аппаратную тесселяцию для создания сотен треугольников для создания эффекта. В режиме DX9 вы видите брызги, но не волны, а сама лужа может состоять всего из двух треугольников.
Без тесселяции
С тесселяцией
Тесселяция добавляет волны и рябь в сцену в Dirt 2.
Развитие тесселяции
Тесселяция обещает улучшить реалистичность трехмерных объектов, но это не панацея. Как и в случае с любой новой техникой, разработчикам придется подходить к ее реализации с умом. Мозаику легко использовать для создания объектов, которые выглядят неправильно. Кроме того, есть проблема с производительностью. Хотя современные графические процессоры DirectX 11 имеют аппаратные механизмы тесселяции, ресурсы не безграничны. Включите слишком сильно тесселяцию, и вы увидите серьезный удар по производительности. Разработчики игр, скорее всего, будут использовать эту технологию как часть сложных схем LoD (уровень детализации), в которых крупные важные объекты (персонажи) мозаичны, а удаленные или неважные объекты мозаичны меньше или вообще не мозаичны.
Сглаживание прозрачности больше не такое уж особенное
Всего пару лет назад как Nvidia, так и AMD активно рекламировали более качественное сглаживание с прозрачными текстурами. Nvidia назвала это сглаживанием прозрачности, а термин AMD — адаптивным сглаживанием. Это классический пример функции, улучшающей качество изображения в то время, но в наши дни не считающейся передовой.
Проблема заключается в том, как прозрачность обрабатывается во многих играх. Прозрачные объекты — это многоугольники с примененными текстурными картами, где часть текстуры прозрачна. Примерами этого являются сетчатые заборы, голые ветки деревьев и воздушные провода.
Адаптивное сглаживание существенно сглаживает края, граничащие с прозрачными областями в этих текстурах. Думайте об этом как о AA внутри полигона.
Без сглаживания прозрачности
Со сглаживанием прозрачности
Прозрачное, или адаптивное, сглаживание работает хорошо, когда игра его поддерживает (как видно на скриншоте выше), но тесселяция может стать универсальной заменой.
Чтобы прозрачное сглаживание работало, игра должна проверять альфа-канал (прозрачная часть), а также отключать альфа-смешивание (где прозрачная текстура комбинируется с фоновым цветом для создания нового цвета. Иногда это используется для создания полупрозрачных (частично прозрачные) объекты.
Игровой движок Valve Source делает это, поэтому, если вы включите адаптивное сглаживание (AMD) или прозрачное сглаживание (Nvidia) в панели управления графикой, вы увидите эффект, как на снимке экрана Left 4 Dead здесь.
Однако используются альфа-смешивание и другие методы, которые мешают этим методам работать. Например, включение этой функции никак не влияет на большинство игр, использующих игровой движок Unreal. Кроме того, такие технологии, как тесселяция, могут в конечном итоге сделать прозрачность AA устаревшей. Если эти голые ветки деревьев можно построить с помощью полигонов, представляющих сами ветки, эти полигоны можно сгладить с помощью стандартного сглаживания с множественной выборкой, и вам не нужно возиться с адаптивным сглаживанием.
Окружающая окклюзия
Достижение высокой реалистичности с помощью света и теней
Все дело в свете. Без света вы не можете видеть. В 3D-играх все освещение создается с помощью математических читов — аппроксимаций того, как ведет себя освещение в реальном мире. Некоторые из самых интересных световых эффектов связаны с отсутствием света: темнота и тени.
Тени эволюционировали от упрощенных карт теней, где все тени выглядели одинаково под любым углом, до более сложных методов, используемых в современных играх.
Вариации с фоновой окклюзией становятся все более популярными. Окружающая окклюзия учитывает, как свет падает на объекты для создания теней, и то, что свойства света и теней меняются с расстоянием. Crysis была одной из первых игр, в которых была предпринята попытка использовать форму окружающего затенения, известную как окружающее затенение экранного пространства (SSAO). Методы SSAO пытаются определить, где находится точка в сцене относительно других точек, а также влияние света, падающего на эту точку, на другие части сцены. Объекты обладают отражающими свойствами и, в свою очередь, могут отражать свет в другие части сцены, даже те, которые заблокированы от прямого источника света.
На реальных объектах обычно есть щели, морщины и впадины, которые могут не освещаться напрямую источником света (например, солнцем). Но они и не темные — они улавливают свет, отражающийся от других частей окружающей среды или даже от близлежащей поверхности того же объекта, находящегося под прямым светом. В предыдущих играх это часто игнорировалось, поэтому щели и впадины были либо полностью темными, либо выглядели так же ярко освещенными, как и другие части объекта.
Другие типы объемного затенения, встречающиеся в новых играх, включают объемное затенение высокого разрешения (HDAO) и объемное затенение на основе горизонта (HBAO). Это по-прежнему вариации одной и той же идеи: положение пикселя по отношению к другим пикселям определяет, как свет падает на него, как он отражает этот свет и какой это тип света (прямой или отраженный).
Без Ambient Occlusion
С Ambient Occlusion
Области, обведенные кружками, в этом примере DirectX 11 SDK показывают, как окружающее затенение высокого разрешения (HDAO) создает более реалистичные детали. Обратите внимание на увеличенную глубину, более четкие линии и большее затенение.
Выше приведен пример HDAO из DirectX SDK. Обратите внимание на внутреннее затенение, которое стало возможным на нижнем экране с помощью этой техники окружающего затенения. Это относительно тонко, но общая сцена кажется более реалистичной, когда вы запускаете приложение в полноэкранном режиме. На верхнем снимке HDAO отключен; на нижнем включен HDAO.
В DirectX 11 появилась новая технология, называемая усилением контактов. Если вы подумаете о том, как ведут себя тени в реальном мире, вы поймете, что тень не выглядит одинаково по всей своей длине. Вблизи предмета, скажем, у основания фонарного столба или дерева, грань между тенью и светом резко очерчена («жесткая» в контактном отверждении). Чем дальше от предмета, тем тень более размыта. Это потому, что дальше свет просачивается в теневую область из окружающей среды. Контактное упрочнение теней с использованием графики Direct 11 имитирует этот вид. На данный момент единственной игрой, в которой используются тени с контактным усилением, является STALKER: Call of Pripyat (ниже).
В этом образце DirectX 11 SDK тени имеют более четкие края вблизи объекта и более мягкие края вдали, как и в реальной жизни.
Эффекты постобработки
Создание графической магии после рендеринга изображения
Постобработка — это применение эффектов к 3D-изображению после рендеринга кадра. Термин «постобработка» пришел из киноиндустрии, где эффекты добавляются к фильмам уже после того, как фильм фактически снят.
Постобработка — это универсальное средство для специальных эффектов, которые создаются, как правило, с помощью шейдерных программ и не обязательно являются частью существующего графического API. Конечно, сам графический процессор должен быть программируемым.
Добавление эффектов к обработанным кадрам впервые появилось в играх для DX9. Мы наблюдаем растущее использование эффектов постобработки в DX10, а теперь и в заголовках DX11. Возможен широкий спектр эффектов постобработки; примеры включают глубину резкости, тепловые искажения, влажные искажения, боке, динамическое размытие и зернистость пленки.
Некоторые из этих эффектов можно использовать для придания сцене реалистичности. Хорошим примером этого является тепловое искажение над огнем или горячим песком пустыни. Другие эффекты на самом деле делают игру менее реалистичной, но более кинематографичной. Примеры этого включают глубину резкости, зернистость пленки и эффекты боке. (Боке – это размытие, которое вы видите в областях фотографии, находящихся не в фокусе. Качество боке — один из параметров, используемых для оценки качества объектива камеры.)
Без боке
С боке
В Just Cause 2 вы увидите эффекты боке при использовании видеокарты Nvidia.
Мы все видели эти эффекты в кино и на телевидении, но редко сталкиваемся с ними в реальной жизни. Разработчики игр добавляют эти эффекты, чтобы их игры больше походили на фильмы на большом экране. Это имеет смысл в некоторых играх, таких как чрезмерное действие недавно вышедшей Just Cause 2, которая имитирует высокобюджетные боевики по своему общему ощущению. Если у вас есть видеокарта на базе Nvidia с компьютерной версией Just Cause 2, вы увидите эффекты боке в действии.
Использование боке помогает сосредоточить внимание игрока на том, что находится поблизости. Грамотное написание шейдерной программы может дать разработчикам детальный контроль над эффектом, как мы видим в демонстрации глубины резкости AMD Ladybug (ее можно загрузить с веб-сайта разработчиков AMD). Эта демонстрация дает пользователю контроль над настройками диафрагмы, как если бы они были съемка камерой. Остановка камеры вниз приводит к мягкому размытию фона позади резко сфокусированного изображения. Открытие диафрагмы позволяет лучше сфокусировать фон.
В демоверсии божьей коровки от AMD вы можете управлять настройками диафрагмы, чтобы изменить фокус фона.
В игре Borderlands (ниже) используется глубина резкости, чтобы сосредоточить ваше внимание на том, во что вы целитесь из своего оружия.
Программируемые шейдеры сделали большой шаг вперед благодаря DirectX 11. Раньше, если программисту нужно было добавить в сцену несколько эффектов, программа шейдера становилась большой и громоздкой. Теперь они могут вызывать процедуры шейдеров по мере необходимости, что позволяет более эффективно писать программы шейдеров и более эффективно использовать эффекты.
Borderlands использует глубину резкости, чтобы сфокусировать взгляд на объекте, на который вы наводите взгляд.На верхнем экране все в фокусе, но когда игрок прицеливается, в фокусе оказывается только цель на переднем плане, как показано на нижнем экране.
Влияние на производительность
Как все это графическое совершенство влияет на частоту кадров?
Если бы мы установили путевую машину на пару лет назад, мы бы снова пережили разочарование, которое мы все испытали с первыми играми DirectX 10. Визуальные эффекты лишь незначительно повысили качество изображения, но удар по производительности был огромным. Каково влияние этих элегантных новых функций DirectX 11? Кроме того, каково влияние эффектов постобработки? Очевидно, что добавление дополнительных шейдерных программ может повлиять на производительность, но насколько сильно?
Мы проверили производительность аппаратной тесселяции с помощью синтетического бенчмарка Unigine Heaven 2.0 (использующего реальный игровой движок) и STALKER: Зов Припяти. Call of Pripyat также использовался для тестирования производительности с SSAO, HBAO и HDAO.
Производительность движка тесселяции Nvidia GTX 480 выглядит довольно впечатляюще по сравнению с результатами AMD в таком тесте, как Heaven, но, как видно из Call of Pripyat, влияние тесселяции на реальные игры менее очевидно. Просто еще недостаточно игр, которые активно используют аппаратную тесселяцию, чтобы определить, какой графический процессор лучше. Субъективные переживания различаются; Производительность Metro 2033, например, кажется, дает преимущество Nvidia, хотя у нас нет точных цифр, подтверждающих это. С другой стороны, Aliens vs. Predator отлично работает как на новейших видеокартах AMD, так и на новейших видеокартах Nvidia.
Just Cause 2 поддерживает две интересные функции постобработки GPU, если вы используете карту на базе Nvidia: боке и симуляцию воды. Таким образом, мы протестировали производительность GTX 480 с этими функциями и без них, используя встроенный в игру тест Concrete Jungle.
Как видите, включение этих функций снижает производительность. Но эта стоимость составляет несколько процентных пунктов, а не снижение на 75–80%, которое мы наблюдали при переходе с DX9 на DX10.
Заключительные мысли
В прошлом сравнение производительности и визуальных характеристик сводилось к сглаживанию и анизотропной фильтрации. DirectX 10 добавил в арсенал разработчика игр несколько новых приемов, но привел к серьезным потерям производительности. Новые функции DirectX 11 могут повлиять на производительность, но графические карты нового поколения позволяют работать с гораздо лучшей визуальной точностью при сохранении приемлемой производительности.
Разработчикам требуется время, чтобы воспользоваться преимуществами новых функций. Хорошей новостью является то, что использование графических процессоров с поддержкой DirectX 11 было одним из самых быстрых в новейшей истории. Мы начинаем видеть все более широкое использование возможностей, которые впервые появились в DirectX 9, наконец. Например, трудно найти игру текущего поколения, в которой не использовались бы эффекты постобработки, обеспечиваемые программируемыми шейдерами. Разработчики продолжают экспериментировать с эффектами постобработки, как мы видели с настройкой боке в Just Cause 2. И такие функции, как зернистость пленки и глубина резкости, стали обычным явлением. Новые игры содержат новые эффекты, такие как имитация цветовых фильтров, которые можно увидеть в высокобюджетных фильмах и телешоу.
Хорошие инструменты станут ключом к внедрению новых функций. Одна из причин, по которой постобработка стала настолько распространенной, заключается в том, что программисты графики разработали инструменты, похожие по концепции на фильтры Photoshop, что позволяет художникам легко внедрять их в художественный конвейер. Пройдет некоторое время, прежде чем аналогичные инструменты станут доступны для более нового оборудования с поддержкой DX11.
Тогда есть вопрос о мультиплатформенности. Крупные издатели игр с подозрением относятся к продвижению высококлассных эксклюзивных функций для ПК, если они выпускают крупнобюджетные игры для нескольких платформ, включая игровые консоли, которые могут не поддерживать тесселяцию или другие функции. Несмотря на то, что ПК в какой-то степени вернулись на игровую арену, вкладывать дополнительные ресурсы разработчиков в эксклюзивные для ПК возможности по-прежнему не принято.
Тем не менее, мы наблюдаем появление новых игр, в которых в полной мере используются новые графические возможности. Восточная Европа, похоже, становится раем для передовой разработки игр для ПК, если судить по серии STALKER, Cryostasis и Metro 2033. И даже игры для консолей, такие как Dirt 2, могут быть спроектированы так, чтобы использовать преимущества новых API на ПК.
Поэтому, если у вас есть карта DirectX 11 нового поколения, включите ее и поэкспериментируйте. Ваши игры могут выглядеть лучше, чем когда-либо.
Лучшие результаты выделены жирным шрифтом. Наш тестовый стенд представляет собой Core i7-975 Extreme Edition с тактовой частотой 3,33 ГГц на материнской плате Asus P6X58D Premium с 6 ГБ памяти DDR3/1333 и блоком питания Corsair 850TX. ОС — 64-битная Windows 7 Ultimate. Тесты проводились в разрешении 1920x1200. Для этих тестов сглаживание было отключено. Для «Зова Припяти» было установлено высокое качество SSAO.
Тесты выполняются в бенчмарке Concrete Jungle.Другие графические функции были установлены на максимальные настройки, а тест выполнялся на разрешении 1920 x 1200.
Ранее вы рассмотрели, как создать окно, которое можно использовать для рисования, в разделе Работа с ресурсами устройства DirectX. Теперь вы узнаете, как создать графический конвейер и где к нему можно подключиться.
Вы помните, что существует два интерфейса Direct3D, которые определяют графический конвейер: ID3D11Device, обеспечивающий виртуальное представление графического процессора и его ресурсов; и ID3D11DeviceContext, который представляет обработку графики для конвейера. Как правило, вы используете экземпляр ID3D11Device для настройки и получения ресурсов графического процессора, необходимых для начала обработки графики в сцене, и вы используете ID3D11DeviceContext для обработки этих ресурсов на каждом соответствующем этапе шейдера в графическом конвейере. Обычно методы ID3D11Device вызываются нечасто, то есть только при настройке сцены или изменении устройства. С другой стороны, вы будете вызывать ID3D11DeviceContext каждый раз, когда обрабатываете кадр для отображения.
В этом примере создается и настраивается минимальный графический конвейер, подходящий для отображения простого вращающегося куба с затенением вершин. Он демонстрирует примерно наименьший набор ресурсов, необходимый для отображения. Когда вы читаете информацию здесь, обратите внимание на ограничения данного примера, где вам, возможно, придется расширить его для поддержки сцены, которую вы хотите визуализировать.
В этом примере рассматриваются два класса C++ для графики: класс диспетчера ресурсов устройства и класс средства визуализации 3D-сцены. В этом разделе особое внимание уделяется средству визуализации 3D-сцен.
Что делает визуализатор куба?
Графический конвейер определяется классом средства визуализации 3D-сцены. Визуализатор сцены может:
- Определите константные буферы для хранения юниформ-данных.
- Определите буферы вершин для хранения данных вершин вашего объекта и соответствующие буферы индексов, чтобы позволить вершинному шейдеру правильно обходить треугольники.
- Создайте ресурсы текстур и представления ресурсов.
- Загрузите объекты шейдера.
- Обновите графические данные для отображения каждого кадра.
- Визуализировать (рисовать) графику в цепочке обмена.
Первые четыре процесса обычно используют методы интерфейса ID3D11Device для инициализации графических ресурсов и управления ими, а последние два используют методы интерфейса ID3D11DeviceContext для управления и выполнения графического конвейера.
Экземпляр класса Renderer создается и управляется как переменная-член в основном классе проекта. Экземпляр DeviceResources управляется как общий указатель для нескольких классов, включая класс основного проекта, класс поставщика представления приложения и средство визуализации. Если вы замените Renderer своим собственным классом, рассмотрите возможность объявления и назначения экземпляра DeviceResources в качестве члена общего указателя:
Просто передайте указатель в конструктор класса (или другой метод инициализации) после создания экземпляра DeviceResources в методе Initialize класса App. Вы также можете передать ссылку weak_ptr, если хотите, чтобы ваш основной класс полностью владел экземпляром DeviceResources.
Создайте визуализатор куба
В этом примере мы организуем класс визуализатора сцены с помощью следующих методов:
- CreateDeviceDependentResources: вызывается всякий раз, когда сцена должна быть инициализирована или перезапущена. Этот метод загружает исходные данные вершин, текстуры, шейдеры и другие ресурсы и создает исходные буферы констант и вершин. Как правило, большая часть работы здесь выполняется с помощью методов ID3D11Device, а не методов ID3D11DeviceContext.
- CreateWindowSizeDependentResources: вызывается при каждом изменении состояния окна, например при изменении размера или ориентации. Этот метод перестраивает матрицы преобразования, например, для вашей камеры.
- Обновление: обычно вызывается из той части программы, которая управляет текущим состоянием игры; в этом примере мы просто вызываем его из класса Main. Этот метод считывает любую информацию о состоянии игры, влияющую на рендеринг, например обновления положения объекта или кадры анимации, а также любые глобальные игровые данные, такие как уровни освещения или изменения в игровой физике. Эти входные данные используются для обновления буферов констант для каждого кадра и данных объекта.
- Визуализация: обычно вызывается из той части программы, которая управляет игровым циклом. в этом случае он вызывается из класса Main. Этот метод строит графический конвейер: он привязывает шейдеры, привязывает буферы и ресурсы к этапам шейдеров и вызывает отрисовку для текущего кадра.
Эти методы включают набор вариантов поведения для рендеринга сцены в Direct3D с использованием ваших ресурсов. Если вы расширите этот пример новым классом рендеринга, объявите его в основном классе проекта. Итак:
Опять же обратите внимание, что в этом примере предполагается, что методы имеют одинаковые сигнатуры в вашей реализации. Если подписи изменились, проверьте основной цикл и внесите соответствующие изменения.
Давайте рассмотрим методы рендеринга сцены более подробно.
Создание ресурсов, зависящих от устройства
CreateDeviceDependentResources объединяет все операции по инициализации сцены и ее ресурсов с использованием вызовов ID3D11Device. Этот метод предполагает, что устройство Direct3D только что было инициализировано (или создано заново) для сцены. Он воссоздает или перезагружает все графические ресурсы, относящиеся к сцене, такие как вершинные и пиксельные шейдеры, буферы вершин и индексов для объектов и любые другие ресурсы (например, текстуры и соответствующие им виды).
Вот пример кода для CreateDeviceDependentResources:
Каждый раз, когда вы загружаете ресурсы с диска — например, файлы скомпилированных объектов шейдера (CSO или .cso) или текстуры — делайте это асинхронно. Это позволяет вам одновременно выполнять другую работу (например, другие задачи настройки), а поскольку основной цикл не заблокирован, вы можете продолжать отображать что-то визуально интересное для пользователя (например, анимацию загрузки для вашей игры). В этом примере используется API Concurrency::Tasks, доступный начиная с Windows 8; обратите внимание на синтаксис лямбда, используемый для инкапсуляции задач асинхронной загрузки. Эти лямбда-выражения представляют функции, вызываемые вне потока, поэтому указатель на текущий объект класса (this) захватывается явно.
Вот пример того, как вы можете загрузить байт-код шейдера:
Вот пример создания буферов вершин и индексов:
В этом примере не загружаются сетки или текстуры. Вы должны создать методы для загрузки мешей и типов текстур, специфичных для вашей игры, и вызывать их асинхронно.
Здесь также заполните начальные значения для буферов констант для каждой сцены. Примеры постоянного буфера для каждой сцены включают фиксированные источники света или другие статические элементы и данные сцены.
Реализовать метод CreateWindowSizeDependentResources
Методы CreateWindowSizeDependentResources вызываются каждый раз при изменении размера, ориентации или разрешения окна.
Ресурсы размера окна обновляются следующим образом: Процесс статического сообщения получает одно из нескольких возможных событий, указывающих на изменение состояния окна. Затем ваш основной цикл получает информацию о событии и вызывает CreateWindowSizeDependentResources для экземпляра основного класса, который затем вызывает реализацию CreateWindowSizeDependentResources для класса рендерера сцены.
Основная задача этого метода — убедиться, что визуальные элементы не перепутаны или недействительны из-за изменения свойств окна. В этом примере мы обновляем матрицы проекта с новым полем зрения (FOV) для окна с измененным размером или переориентацией.
Мы уже видели код для создания оконных ресурсов в DeviceResources — это была цепочка подкачки (с задним буфером) и целевое представление рендеринга. Вот как средство визуализации создает преобразования, зависящие от соотношения сторон:
Если ваша сцена имеет определенное расположение компонентов, которое зависит от соотношения сторон, это место, где можно изменить их расположение, чтобы оно соответствовало этому соотношению сторон. Вы также можете изменить конфигурацию поведения постобработки здесь.
Реализовать метод Update
Метод Update вызывается один раз за игровой цикл — в этом примере он вызывается одноименным методом основного класса. У него простая цель: обновить геометрию сцены и состояние игры на основе количества прошедшего времени (или прошедших временных шагов) с момента предыдущего кадра. В этом примере мы просто поворачиваем куб один раз за кадр. В реальной игровой сцене этот метод содержит гораздо больше кода для проверки состояния игры, обновления буферов констант для каждого кадра (или других динамических), буферов геометрии и других ресурсов в памяти соответственно. Поскольку связь между ЦП и ГП влечет за собой накладные расходы, убедитесь, что вы обновляете только те буферы, которые фактически изменились с момента последнего кадра — ваши постоянные буферы могут быть сгруппированы или разделены по мере необходимости, чтобы сделать это более эффективным.
В этом случае Rotate обновляет буфер констант новой матрицей преобразования для куба. Матрица будет умножаться для каждой вершины на этапе вершинного шейдера. Поскольку этот метод вызывается с каждым кадром, это хорошее место для объединения любых методов, которые обновляют ваши динамические константы и буферы вершин, или для выполнения любых других операций, которые подготавливают объекты в сцене к преобразованию графическим конвейером.
Реализовать метод Render
Этот метод вызывается один раз за игровой цикл после вызова Update. Как и Update, метод Render также вызывается из основного класса. Это метод, в котором графический конвейер создается и обрабатывается для кадра с использованием методов экземпляра ID3D11DeviceContext. Это завершается последним вызовом ID3D11DeviceContext::DrawIndexed. Важно понимать, что этот вызов (или другие подобные вызовы Draw*, определенные в ID3D11DeviceContext) фактически выполняет конвейер.В частности, это когда Direct3D взаимодействует с графическим процессором для установки состояния отрисовки, запускает каждую стадию конвейера и записывает результаты пикселей в ресурс буфера цели рендеринга для отображения цепочкой обмена. Поскольку обмен данными между ЦП и ГП сопряжен с накладными расходами, по возможности объедините несколько вызовов отрисовки в один, особенно если в вашей сцене много визуализируемых объектов.
Рекомендуется устанавливать различные этапы графического конвейера в контексте по порядку. Обычно порядок такой:
- Обновлять ресурсы постоянного буфера новыми данными по мере необходимости (используя данные из обновления).
- Входная сборка (IA): сюда мы присоединяем буферы вершин и индексов, которые определяют геометрию сцены. Вам нужно прикрепить каждую вершину и индексный буфер для каждого объекта в сцене. Поскольку в этом примере есть только куб, это довольно просто.
- Вершинный шейдер (VS): прикрепите любые вершинные шейдеры, которые будут преобразовывать данные в вершинных буферах, и присоедините константные буферы для вершинного шейдера.
- Пиксельный шейдер (PS): подключите любые пиксельные шейдеры, которые будут выполнять попиксельные операции в растровой сцене, и подключите ресурсы устройства для пиксельного шейдера (постоянные буферы, текстуры и т. д.).
- Выходное слияние (ОМ). Это этап, на котором пиксели смешиваются после завершения шейдеров. Это исключение из правила, потому что вы прикрепляете свои трафареты глубины и цели рендеринга до установки любого из других этапов. У вас может быть несколько трафаретов и целей, если у вас есть дополнительные вершинные и пиксельные шейдеры, которые генерируют текстуры, такие как карты теней, карты высот или другие методы выборки — в этом случае для каждого прохода рисования потребуется установить соответствующие цели перед вызовом функция рисования.
Далее, в заключительном разделе (Работа с шейдерами и ресурсами шейдеров), мы рассмотрим шейдеры и обсудим, как Direct3D их выполняет.
DirectX 12 дебютировал два года назад, обещая значительное повышение производительности и эффективности по всем направлениям. Это включает в себя более эффективное использование ЦП, более близкий доступ к металлу, а также множество новых функций, в первую очередь трассировку лучей или DXR (DirectX Ray-tracing). Но что такое DirectX 12 и чем он отличается от DirectX 11. Давайте посмотрим.
Что такое DirectX: это API
Подобно Vulkan и OpenGL, DirectX — это API, позволяющий запускать видеоигры на компьютере. Однако, в отличие от своих аналогов, DX является проприетарной платформой Microsoft и изначально работает только в Windows. С другой стороны, OpenGL и Vulkan работают как на Mac, так и на Linux.
Что делает графический API, такой как DirectX? Он действует как промежуточное звено между игровым движком и графическими драйверами, которые, в свою очередь, взаимодействуют с ядром ОС. Графический API — это платформа, на которой разрабатываются реальный дизайн и механика игры. Думайте об этом как о MS Paint, где игра — это рисование, а приложение для рисования — это API. Однако, в отличие от Paint, программа вывода графического API доступна для чтения только API, используемому для ее разработки. Как правило, API предназначен для конкретной ОС. Вот почему игры для PS4 не работают на Xbox One и наоборот.
DirectX 12 Ultimate — первый графический API, нарушающий это правило. Он будет использоваться как на Windows, так и на Xbox Series X следующего поколения. С помощью DX12 Ultimate MS фактически интегрирует две платформы.
DirectX 11 и DirectX 12: что это значит для геймеров на ПК
Есть три основных преимущества API DirectX 12 для геймеров на ПК:
Лучшее масштабирование с многоядерными процессорами
Одним из основных преимуществ низкоуровневых API, таких как DirectX 12 и Vulkan, является более эффективное использование ЦП. Традиционно с играми на основе DirectX 9 и 11 большинство игр использовали только 2-4 ядра для различных механик: физики, ИИ, вызовов отрисовки и т. д. Некоторые игры даже ограничивались одним. С DirectX 12 все изменилось. Нагрузка более равномерно распределяется между всеми ядрами, что делает многоядерные процессоры более актуальными для геймеров.
Максимальное использование оборудования
Многие из вас могли заметить, что вначале графические процессоры AMD отдавали предпочтение играм с DirectX 12 больше, чем конкурирующим компонентам NVIDIA. Почему это?
Причина в лучшем использовании. Традиционно у NVIDIA была гораздо лучшая поддержка драйверов, в то время как аппаратное обеспечение AMD всегда страдало от ее отсутствия.DirectX 12 добавляет множество технологий для улучшения использования, таких как асинхронные вычисления, которые позволяют одновременно выполнять несколько этапов конвейера (читай: вычисления и графика). Это делает плохую поддержку водителей менее актуальной проблемой.
Ближе к металлической поддержке
Еще одно важное преимущество DirectX 12 заключается в том, что разработчики имеют больший контроль над тем, как их игра использует аппаратное обеспечение. Раньше это было более абстрактно и в основном заботилось о драйверах и API (хотя некоторые движки, такие как Frostbyte и Unreal, также предоставляли низкоуровневые инструменты).
Теперь задача ложится на разработчиков. Они имеют более близкий доступ к металлу, а это означает, что большая часть обязанностей по рендерингу и распределению ресурсов выполняется игровыми движками с некоторой помощью графических драйверов.
Это палка о двух концах, так как в дикой природе существует несколько архитектур графических процессоров, и независимые разработчики не могут оптимизировать свою игру для всех них. К счастью, сторонние движки, такие как Unreal, CryEngine и Unity, делают это за них, и им нужно сосредоточиться только на дизайне.
Как DirectX 12 повышает производительность за счет оптимизации использования оборудования
Опять же, есть несколько основных усовершенствований API, которые способствуют этому:
Контекст API для каждого вызова
Как и любое приложение, графические API, такие как DirectX, также имеют основной поток, который отслеживает внутреннее состояние API (ресурсы, их распределение и доступность). В DirectX 9 и 11 есть глобальное состояние (или контекст). Игры, которые вы запускаете на своем ПК, изменяют это состояние с помощью вызовов отрисовки в API, после чего оно передается графическому процессору для выполнения. Поскольку существует одно глобальное состояние/контекст (и один основной поток, в котором он выполняется), это затрудняет многопоточность, поскольку несколько одновременных вызовов отрисовки могут вызвать ошибки. Кроме того, изменение глобального состояния с помощью вызовов состояния является относительно более медленным процессом, что еще больше усложняет весь процесс.
В DirectX 12 вызовы отрисовки стали более гибкими. Вместо единого глобального состояния (контекста) каждый вызов отрисовки из приложения имеет собственное меньшее состояние (дополнительные сведения см. в PSO ниже). Эти вызовы отрисовки содержат необходимые данные и связанные с ними указатели внутри и не зависят от других вызовов и их состояний. Это позволяет использовать несколько потоков для разных вызовов отрисовки.
Объекты состояния конвейера
В DirectX 11 объекты в конвейере графического процессора существуют в широком диапазоне состояний, таких как вершинный шейдер, шейдер корпуса, шейдер геометрии и т. д. Эти состояния часто взаимозависимы друг от друга, и следующее за ним состояние не может быть изменено. если предыдущая стадия не определена. Когда геометрия из сцены отправляется в графический процессор для рендеринга, требуемые ресурсы и оборудование могут варьироваться в зависимости от состояния растеризатора, состояния наложения, состояния трафарета глубины, отбраковки и т. д.
Каждый из объектов в DirectX 11 должен быть определен отдельно (во время выполнения), а следующее состояние не может быть выполнено до тех пор, пока не будет завершено предыдущее, поскольку для них требуются разные аппаратные устройства (шейдеры и ROP, TMU и т. д.) . Это приводит к недостаточному использованию оборудования, что приводит к увеличению накладных расходов и сокращению числа вызовов отрисовки.
В приведенном выше сравнении аппаратное состояние 1 представляет код шейдера, а 2 — комбинацию растеризатора и потока управления, связывающего растеризатор с шейдерами. Состояние 3 — это связь между наложением и пиксельным шейдером. Вершинный шейдер влияет на состояния аппаратного обеспечения 1 и 2, состояние растеризатора 2, состояния пиксельного шейдера 1-3 и так далее. Как уже объяснялось в предыдущем разделе, это приводит к дополнительной нагрузке на ЦП, поскольку драйвер обычно предпочитает дождаться разрешения зависимостей.
DirectX 12 заменяет различные состояния объектами состояния конвейера (PSO), которые завершаются при самом создании. Простыми словами PSO — это объект, описывающий состояние вызова отрисовки, который он представляет. Приложение может создавать столько PSO, сколько требуется, и может переключаться между ними по мере необходимости. Эти PSO включают байт-код для всех шейдеров, включая вершинный, пиксельный, доменный, корпусный и геометрический шейдеры, и могут быть преобразованы в любое состояние в соответствии с требованиями, независимо от какого-либо другого объекта или состояния.
В новейших графических процессорах NVIDIA и AMD с помощью DirectX 12 представлены шейдеры задач и шейдеры сетки. Эти два новых шейдера заменяют различные громоздкие этапы шейдеров, используемые в конвейере DX11, для более гибкого подхода.
Шейдер сетки выполняет ту же задачу, что и шейдеры предметной области и геометрии, но внутри он использует многопоточную модель вместо однопоточной. Шейдер задач работает аналогично. Основное отличие здесь состоит в том, что в то время как входные данные шейдера корпуса представляют собой патчи, а выходные данные мозаичного объекта, входные и выходные данные шейдера задач определяются пользователем.
В приведенной ниже сцене есть тысячи объекты, которые необходимо отобразить. В традиционной модели для каждого из них потребовался бы уникальный вызов отрисовки от ЦП. Однако с помощью шейдера задач список объектов отправляется с помощью одного вызова отрисовки. Затем шейдер задач обрабатывает этот список параллельно и назначает работу шейдеру сетки (который также работает синхронно), после чего сцена отправляется в растеризатор для преобразования 3D в 2D.
Этот подход помогает уменьшить количество вызовов отрисовки ЦП на сцену значительно, тем самым повышая уровень детализации.
Сетчатые шейдеры также облегчают отбраковку неиспользуемых треугольников. Это делается с помощью шейдера усиления. Он запускается перед шейдером сетки и определяет необходимое количество групп потоков шейдера сетки. Они проверяют различные мешлеты на возможные пересечения и видимость на экране, а затем выполняют требуемую отбраковку. Отбор геометрии на этом раннем этапе рендеринга значительно повышает производительность. Вы можете прочитать больше здесь...
NVIDIA Mesh Shaders и Hull Shaders также используют DX12
Очередь команд
В DirectX 11 к графическому процессору направляется только одна очередь. Это приводит к неравномерному распределению нагрузки между различными ядрами ЦП, что существенно снижает эффективность многопоточных ЦП.
Ранее вы рассмотрели, как создать окно, которое можно использовать для рисования, в разделе Работа с ресурсами устройства DirectX. Теперь вы узнаете, как создать графический конвейер и где к нему можно подключиться.
Вы помните, что существует два интерфейса Direct3D, которые определяют графический конвейер: ID3D11Device, обеспечивающий виртуальное представление графического процессора и его ресурсов; и ID3D11DeviceContext, который представляет обработку графики для конвейера. Как правило, вы используете экземпляр ID3D11Device для настройки и получения ресурсов графического процессора, необходимых для начала обработки графики в сцене, и вы используете ID3D11DeviceContext для обработки этих ресурсов на каждом соответствующем этапе шейдера в графическом конвейере. Обычно методы ID3D11Device вызываются нечасто, то есть только при настройке сцены или изменении устройства. С другой стороны, вы будете вызывать ID3D11DeviceContext каждый раз, когда обрабатываете кадр для отображения.
В этом примере создается и настраивается минимальный графический конвейер, подходящий для отображения простого вращающегося куба с затенением вершин. Он демонстрирует примерно наименьший набор ресурсов, необходимый для отображения. Когда вы читаете информацию здесь, обратите внимание на ограничения данного примера, где вам, возможно, придется расширить его для поддержки сцены, которую вы хотите визуализировать.
В этом примере рассматриваются два класса C++ для графики: класс диспетчера ресурсов устройства и класс средства визуализации 3D-сцены. В этом разделе особое внимание уделяется средству визуализации 3D-сцен.
Что делает визуализатор куба?
Графический конвейер определяется классом средства визуализации 3D-сцены. Визуализатор сцены может:
- Определите константные буферы для хранения юниформ-данных.
- Определите буферы вершин для хранения данных вершин вашего объекта и соответствующие буферы индексов, чтобы позволить вершинному шейдеру правильно обходить треугольники.
- Создайте ресурсы текстур и представления ресурсов.
- Загрузите объекты шейдера.
- Обновите графические данные для отображения каждого кадра.
- Визуализировать (рисовать) графику в цепочке обмена.
Первые четыре процесса обычно используют методы интерфейса ID3D11Device для инициализации графических ресурсов и управления ими, а последние два используют методы интерфейса ID3D11DeviceContext для управления и выполнения графического конвейера.
Экземпляр класса Renderer создается и управляется как переменная-член в основном классе проекта. Экземпляр DeviceResources управляется как общий указатель для нескольких классов, включая класс основного проекта, класс поставщика представления приложения и средство визуализации.Если вы замените Renderer своим собственным классом, рассмотрите возможность объявления и назначения экземпляра DeviceResources в качестве члена общего указателя:
Просто передайте указатель в конструктор класса (или другой метод инициализации) после создания экземпляра DeviceResources в методе Initialize класса App. Вы также можете передать ссылку weak_ptr, если хотите, чтобы ваш основной класс полностью владел экземпляром DeviceResources.
Создайте визуализатор куба
В этом примере мы организуем класс визуализатора сцены с помощью следующих методов:
- CreateDeviceDependentResources: вызывается всякий раз, когда сцена должна быть инициализирована или перезапущена. Этот метод загружает исходные данные вершин, текстуры, шейдеры и другие ресурсы и создает исходные буферы констант и вершин. Как правило, большая часть работы здесь выполняется с помощью методов ID3D11Device, а не методов ID3D11DeviceContext.
- CreateWindowSizeDependentResources: вызывается при каждом изменении состояния окна, например при изменении размера или ориентации. Этот метод перестраивает матрицы преобразования, например, для вашей камеры.
- Обновление: обычно вызывается из той части программы, которая управляет текущим состоянием игры; в этом примере мы просто вызываем его из класса Main. Этот метод считывает любую информацию о состоянии игры, влияющую на рендеринг, например обновления положения объекта или кадры анимации, а также любые глобальные игровые данные, такие как уровни освещения или изменения в игровой физике. Эти входные данные используются для обновления буферов констант для каждого кадра и данных объекта.
- Визуализация: обычно вызывается из той части программы, которая управляет игровым циклом. в этом случае он вызывается из класса Main. Этот метод строит графический конвейер: он привязывает шейдеры, привязывает буферы и ресурсы к этапам шейдеров и вызывает отрисовку для текущего кадра.
Эти методы включают набор вариантов поведения для рендеринга сцены в Direct3D с использованием ваших ресурсов. Если вы расширите этот пример новым классом рендеринга, объявите его в основном классе проекта. Итак:
Опять же обратите внимание, что в этом примере предполагается, что методы имеют одинаковые сигнатуры в вашей реализации. Если подписи изменились, проверьте основной цикл и внесите соответствующие изменения.
Давайте рассмотрим методы рендеринга сцены более подробно.
Создание ресурсов, зависящих от устройства
CreateDeviceDependentResources объединяет все операции по инициализации сцены и ее ресурсов с использованием вызовов ID3D11Device. Этот метод предполагает, что устройство Direct3D только что было инициализировано (или создано заново) для сцены. Он воссоздает или перезагружает все графические ресурсы, относящиеся к сцене, такие как вершинные и пиксельные шейдеры, буферы вершин и индексов для объектов и любые другие ресурсы (например, текстуры и соответствующие им виды).
Вот пример кода для CreateDeviceDependentResources:
Каждый раз, когда вы загружаете ресурсы с диска — например, файлы скомпилированных объектов шейдера (CSO или .cso) или текстуры — делайте это асинхронно. Это позволяет вам одновременно выполнять другую работу (например, другие задачи настройки), а поскольку основной цикл не заблокирован, вы можете продолжать отображать что-то визуально интересное для пользователя (например, анимацию загрузки для вашей игры). В этом примере используется API Concurrency::Tasks, доступный начиная с Windows 8; обратите внимание на синтаксис лямбда, используемый для инкапсуляции задач асинхронной загрузки. Эти лямбда-выражения представляют функции, вызываемые вне потока, поэтому указатель на текущий объект класса (this) захватывается явно.
Вот пример того, как вы можете загрузить байт-код шейдера:
Вот пример создания буферов вершин и индексов:
В этом примере не загружаются сетки или текстуры. Вы должны создать методы для загрузки мешей и типов текстур, специфичных для вашей игры, и вызывать их асинхронно.
Здесь также заполните начальные значения для буферов констант для каждой сцены. Примеры постоянного буфера для каждой сцены включают фиксированные источники света или другие статические элементы и данные сцены.
Реализовать метод CreateWindowSizeDependentResources
Методы CreateWindowSizeDependentResources вызываются каждый раз при изменении размера, ориентации или разрешения окна.
Ресурсы размера окна обновляются следующим образом: Процесс статического сообщения получает одно из нескольких возможных событий, указывающих на изменение состояния окна. Затем ваш основной цикл получает информацию о событии и вызывает CreateWindowSizeDependentResources для экземпляра основного класса, который затем вызывает реализацию CreateWindowSizeDependentResources для класса рендерера сцены.
Основная задача этого метода — убедиться, что визуальные элементы не перепутаны или недействительны из-за изменения свойств окна. В этом примере мы обновляем матрицы проекта с новым полем зрения (FOV) для окна с измененным размером или переориентацией.
Мы уже видели код для создания оконных ресурсов в DeviceResources — это была цепочка подкачки (с задним буфером) и целевое представление рендеринга. Вот как средство визуализации создает преобразования, зависящие от соотношения сторон:
Если ваша сцена имеет определенное расположение компонентов, которое зависит от соотношения сторон, это место, где можно изменить их расположение, чтобы оно соответствовало этому соотношению сторон. Вы также можете изменить конфигурацию поведения постобработки здесь.
Реализовать метод Update
Метод Update вызывается один раз за игровой цикл — в этом примере он вызывается одноименным методом основного класса. У него простая цель: обновить геометрию сцены и состояние игры на основе количества прошедшего времени (или прошедших временных шагов) с момента предыдущего кадра. В этом примере мы просто поворачиваем куб один раз за кадр. В реальной игровой сцене этот метод содержит гораздо больше кода для проверки состояния игры, обновления буферов констант для каждого кадра (или других динамических), буферов геометрии и других ресурсов в памяти соответственно. Поскольку связь между ЦП и ГП влечет за собой накладные расходы, убедитесь, что вы обновляете только те буферы, которые фактически изменились с момента последнего кадра — ваши постоянные буферы могут быть сгруппированы или разделены по мере необходимости, чтобы сделать это более эффективным.
В этом случае Rotate обновляет буфер констант новой матрицей преобразования для куба. Матрица будет умножаться для каждой вершины на этапе вершинного шейдера. Поскольку этот метод вызывается с каждым кадром, это хорошее место для объединения любых методов, которые обновляют ваши динамические константы и буферы вершин, или для выполнения любых других операций, которые подготавливают объекты в сцене к преобразованию графическим конвейером.
Реализовать метод Render
Этот метод вызывается один раз за игровой цикл после вызова Update. Как и Update, метод Render также вызывается из основного класса. Это метод, в котором графический конвейер создается и обрабатывается для кадра с использованием методов экземпляра ID3D11DeviceContext. Это завершается последним вызовом ID3D11DeviceContext::DrawIndexed. Важно понимать, что этот вызов (или другие подобные вызовы Draw*, определенные в ID3D11DeviceContext) фактически выполняет конвейер. В частности, это когда Direct3D взаимодействует с графическим процессором для установки состояния отрисовки, запускает каждую стадию конвейера и записывает результаты пикселей в ресурс буфера цели рендеринга для отображения цепочкой обмена. Поскольку обмен данными между ЦП и ГП сопряжен с накладными расходами, по возможности объедините несколько вызовов отрисовки в один, особенно если в вашей сцене много визуализируемых объектов.
Рекомендуется устанавливать различные этапы графического конвейера в контексте по порядку. Обычно порядок такой:
- Обновлять ресурсы постоянного буфера новыми данными по мере необходимости (используя данные из обновления).
- Входная сборка (IA): сюда мы присоединяем буферы вершин и индексов, которые определяют геометрию сцены. Вам нужно прикрепить каждую вершину и индексный буфер для каждого объекта в сцене. Поскольку в этом примере есть только куб, это довольно просто.
- Вершинный шейдер (VS): прикрепите любые вершинные шейдеры, которые будут преобразовывать данные в вершинных буферах, и присоедините константные буферы для вершинного шейдера.
- Пиксельный шейдер (PS): подключите любые пиксельные шейдеры, которые будут выполнять попиксельные операции в растровой сцене, и подключите ресурсы устройства для пиксельного шейдера (постоянные буферы, текстуры и т. д.).
- Выходное слияние (ОМ). Это этап, на котором пиксели смешиваются после завершения шейдеров. Это исключение из правила, потому что вы прикрепляете свои трафареты глубины и цели рендеринга до установки любого из других этапов. У вас может быть несколько трафаретов и целей, если у вас есть дополнительные вершинные и пиксельные шейдеры, которые генерируют текстуры, такие как карты теней, карты высот или другие методы выборки — в этом случае для каждого прохода рисования потребуется установить соответствующие цели перед вызовом функция рисования.
Далее, в заключительном разделе (Работа с шейдерами и ресурсами шейдеров), мы рассмотрим шейдеры и обсудим, как Direct3D их выполняет.
Читайте также: