Что значит компиляция шейдеров

Компиляция шейдеров

В этом разделе описывается FXC.EXE компилятор, используемый для моделей шейдеров 2 – 5,1. Для Shader Model 6 используется DXC.EXE вместо, который описан в статье Использование dxc.exe и dxcompiler.dll.

Microsoft Visual Studio 2012 теперь может компилировать код шейдера из * файлов. hlsl, включаемых в проект C++.

в рамках процесса сборки Visual Studio 2012 использует компилятор кода fxc.exe HLSL для компиляции HLSL файлов в двоичные файловые файлы шейдеров или в байтовые массивы, определенные в файлах заголовков. Как компилятор кода HLSL компилирует каждый файл HLSL в проекте, зависит от того, как указать свойство файлов выходные данные для этого файла. Дополнительные сведения о страницах свойств HLSL см. в разделе страницы свойств HLSL.

Используемый метод компиляции обычно зависит от размера * файла HLSL. Если включить в заголовок большой объем байтового кода, размер и начальное время загрузки приложения будут увеличены. Кроме того, весь байтовый код должен находиться в памяти даже после создания шейдера, что приведет к потере ресурсов. Но при включении в заголовок байтового кода можно уменьшить сложность кода и упростить создание шейдера.

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

Использование расширений файлов кода шейдера

Чтобы согласовать соглашение с Майкрософт, используйте следующие расширения файлов для кода шейдера:

Компиляция во время сборки в объектные файлы

При компиляции HLSL-файлов в двоичные файловые файлы шейдера приложение должно считывать данные из этих файлов объектов (. cso является расширением по умолчанию для этих объектных файлов), назначать данные байтовые массивы и создавать объекты шейдера из этих массивов байтов. Например, чтобы создать шейдер вершин (ID3D11VertexShader * * ), вызовите метод ID3D11Device:: креатевертексшадер с массивом байтов, который содержит скомпилированный байтовый код шейдера вершин. В примере «учебник по Direct3D » показано, как создавать объекты шейдера из байтовых массивов, полученных из. объектно построителей двоичных файлов шейдера. В этом примере кода из примера учебника по Direct3Dсвойство выходные данные Files для файла симплевертексшадер. HLSL определяет компиляцию в объектный файл симплевертексшадер. cso.

Компиляция во время сборки в файлы заголовков

Компиляция с помощью D3DCompileFromFile

Можно также использовать функцию D3DCompileFromFile во время выполнения для компиляции кода шейдера. Дополнительные сведения о том, как это сделать, см. в разделе инструкции. Компиляция шейдера.

Windows Приложения Магазина поддерживают использование D3DCompileFromFile для разработки, но не для развертывания.

Источник

[Решено] Black Ops Cold War застряла на компиляции шейдеров

Black Ops Cold War Stuck Compiling Shaders

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

В последнее время геймеры сообщают проблема компиляции шейдеров в Black Ops Cold War, что приводит к зависанию или сбою игры. Если вы оказались в одной лодке, не волнуйтесь. Ниже мы собрали последние исправления этой ошибки, попробуйте их и сразу же вернитесь к игре.

Попробуйте эти исправления:

Возможно, вам не придется пробовать их все. Просто спускайтесь вниз, пока не приземлитесь на ту, которая делает трюк.

Исправление 1: отсканируйте и восстановите свою игру

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

Теперь перезапустите Black Ops Cold War и проверьте, можете ли вы пройти компиляцию шейдеров.

Если проблема не исчезнет, ​​попробуйте следующее исправление, указанное ниже.

Исправление 2: перезапустите установку шейдеров.

Вот как перезапустить установку шейдеров:

Если это решение не решает проблему, обратите внимание на следующее ниже.

Исправление 3: обновите графический драйвер

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

Если последняя версия графического драйвера не принесла вам удачи, просто воспользуйтесь следующим методом.

Исправление 4: Удалить папки кеша

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

Исправление 5. Свяжите свои учетные записи Activision и Blizzard.

Возможно, у вас застряла компиляция шейдеров, вы не подключили свою учетную запись Blizzard на веб-странице Activision. Вам необходимо убедиться, что ваши учетные записи Activision и Blizzard связаны, чтобы избежать возможных ошибок.

Надеюсь, это руководство поможет вам решить проблему компиляции шейдеров. Если у вас есть какие-либо вопросы или идеи, не стесняйтесь обращаться к нам в комментариях ниже.

Источник

Шейдеры. Что и как

Расскажу, как в общем случае они работают, что умеют и как их используют

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

Слово «шейдер» в контексте разработки игр очень популярно, слышать его могли и те, кто игры не делает. Само слово изначально появилось от англ. shading (затенение) — первые шейдеры использовались, чтобы передавать глубину с помощью работы со светом, блеском, тенями и прочим. Со временем шейдеры стали использоваться для совершенно разного вида постобработки и вообще отрисовки примерно всего.

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

Теперь разберемся, как это все работает.

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

Процесс отрисовки, если его достаточно упростить (что я и сделаю в рамках этой статьи), можно поделить на несколько шагов:

1. Получение входных данных из памяти.
2. Выполнение шейдера вершин.
3. Растеризация.
4. Выполнение шейдера пикселей (фрагментов).
5. Проведение тестов «глубины».
6. Отрисовка на текстуру для экрана.

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

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

1. Шейдер вершин.
2. Шейдер фрагментов.

Как сказано было ранее, этот шейдер (или группа шейдеров по очереди) занимается переводом координат относительно объекта, в координаты на текстуре.

На картинке начало координат немного не соответствует реальным, что все так же не влияет на понимание процесса 🙂

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

После преобразований вершин и растеризации нужно высчитать цвет каждого фрагмента (помним, что для упрощения это пиксели). Для примера возьмём наш куб: мы помним, что он залит одним цветом. Просто сделаем так, чтобы цвет каждого фрагмента стал цвета куба и все:

Выглядит немного странно, да? Проблема в том, что мы не видим ни теней, ни текстур. Будь на кубе какая-либо текстура, мы бы заметили переход между гранями. Вот возьмем текстуру:

Теперь достаточно в каждом пикселе просто брать цвет из текстуры. Но чтобы это сделать, нужно добавить для каждой точки куба еще информацию: UV канал. Это координат вида (u, v). Отсюда и название, так как x и y были заняты. Она присваивается вершине объекта и обозначает точку на текстуре, которая ей соответствует. Чтобы было понятнее, если мы хотим на каждую грань куба нарисовать знакомое нам лицо, то UV координаты для каждой грани будут выглядеть предельно просто:

Модифицировать их никак не надо. Более того, считать координаты для каждой точки — тоже не нужно. Этим занимается GPU, самостоятельно интерполируя точки из вершин. Тогда достаточно просто сказать для каждой точки что-то вроде

Это очень условный пример, но примерно так в простейшем случае оно и работает:

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

Помимо UV канала в шейдер в зависимости от его вида приходят разные данные. Они зависят от игрового движка и графической библиотеки. Обычно туда входят данные о местоположении точки, нормаль (вектор исходящий от поверхности в точке), UV канал. Но также шейдер вершин может передавать данные в пиксельный шейдер. Если это координата, то она будет проинтеполирована на основе положения фрагмента относительно вершин, между которыми он находится, как, например, UV данные.

Источник

Что значит компиляция шейдеров

Чтобы поместить шейдер, который вы только что написали, в ваш графический движок, вы делаете в основном те же самые вещи, которые FX Composer делает, чтобы показать вам шейдер. Благодаря DirectX или XNA легко загрузить файл шейдерного эффекта и установить все требуемые параметры (вы уже делали это в предыдущей главе для шейдера визуализации линий). В следующей главе вы перейдете к использованию более общего класса, который принимает много различных шейдеров и использует более оптимизированный способ установки всех необходимых шейдерам параметров, а в этой главе мы просто заставим файл SimpleShader.fx работать в вашем движке.

Как обычно, начнем с определения тестового модуля. Создайте новый файл с именем simpleShader.cs в пространстве имен Shaders и напишите следующий код:

Тестовый модуль должен компилироваться, за исключением метода renderModel нового класса SimpleShader, который еще не определен. Давайте быстро определим этот метод:

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

Компиляция шейдеров

Загрузить скомпилированный эффект так же просто, как загрузить текстуру. Просто определите переменную эффекта, а затем загрузите ее в конструкторе SimpleShader:

На платформе Windows вы также можете загружать шейдеры динамически (в этом случае они не будут заранее скомпилированы XNA Framework), что может быть полезно для тестирования и изменения шейдеров во время выполнения вашей игры. Обычно во время разработки для большинства шейдеров я использую некомпилированные файлы шейдеров, а затем помещаю их в конвейер содержимого, когда игра завершена и я больше не собираюсь изменять шейдеры. Для самостоятельной загрузки и компиляции шейдеров используется следующий код:

Использование параметров

Как вы узнали в процессе создания шейдера, мировая матрица, матрица вида и матрица проекции действительно важны для преобразования ваших трехмерных данных и получения корректного результата на экране. Для установки всех этих параметров шейдера вы просто используете метод RenderModel, который вызывается из вашего тестового модуля:

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

Формат вершин

Перед тем, как визуализировать данные из вашей трехмерной модели яблока, вы должны убедиться, что ваше приложение и шейдер знают, какой формат вершин использовать. В DirectX это достигалось путем простой установки одного из предопределенных форматов вершин фиксированного конвейера функций, но эти форматы больше не существуют, и вы не можете установить их. Вместо этого вы должны определить полное объявление вершины, также как делали это в шейдере для структуры VertexInput. Поскольку мы просто используем встроенную структуру VertexPositionNormalTexture, нам не надо ничего определять самостоятельно, но в следующей главе вы узнаете, как сделать это для собственного нестандартного формата TangentVertex.

На самом деле вам не нужно создавать новое объявление вершин каждый раз, когда вы вызываете RenderModel, но чтобы упростить материал я строю новое объявление вершин при каждом вызове. В первом параметре передается графическое устройство, а во втором — массив элементов вершин из структуры XNA VertexPositionNormalTexture. За дополнительной информацией обращайтесь к главе 7.

Визуализация с шейдерами

Чтобы теперь визуализировать яблоко с вашим шейдером необходимо сначала указать, какую технику вы хотите использовать (в любом случае, по умолчанию будет установлена первая техника, но полезно знать, как устанавливать техники). Для визуализации шейдера вы всегда будете использовать свойство CurrentTechnique класса эффекта. Затем вы проходите по технике так же, как это делает FX Composer, — вы рисуете все трехмерные данные для каждого прохода, который есть в технике (как я говорил раньше, обычно у вас будет только один проход). Визуализация самого яблока не то чтобы очень проста, поскольку единственный метод, который XNA предоставдяет вам для этого, это mesh.Draw, который надо вызывать для каждой сетки модели после установки необходимых параметров шейдеров, что вы видели в предыдущей главе, когда писали класс Model.

Другая вещь, отсутствующая в XNA Framework, это вспомогательные методы для создания сеток кубов, сфер или чайников. Вы также заметите, что большинство функциональности пространства имен Direct3DX просто не существует в XNA. Вы только можете получить доступ к некоторым методам, когда пишете собственный обработчик содержимого, но это не поможет вам при написании своего движка, или когда вы захотите проверить модели, сетки или шейдеры. Вы также не можете получить доступ к любым данным вершин или индексов загруженных моделей, потому что все буферы вершин и индексов доступны только для записи, что хорошо с точки зрения производительности, но плохо, если вы захотите что-нибудь модифицировать. В вашем небольшом фрагменте кода вы просто имитируете поведение метода mesh.Draw, только без кода эффектов, поскольку для этой цели у вас здесь используется собственный класс эффектов.

Если подробнее, это означает, что вы перебираете каждый проход (снова у вас только один) и рисуете все сетки (также только одну для вашего яблока), визуализируя все части каждой сетки (представьте себе, и здесь одну), устанавливая буферы вершин и индексов с помощью свойств класса XNA Device. Затем вы вызываете DrawIndexedPrimitives для визуализации всех вершин внутри шейдера. После этого проход и шейдер закрываются и вы наконец видите свое яблоко с текстурой marble.dds на экране (рис. 6.16).

Что значит компиляция шейдеров. Смотреть фото Что значит компиляция шейдеров. Смотреть картинку Что значит компиляция шейдеров. Картинка про Что значит компиляция шейдеров. Фото Что значит компиляция шейдеров

Тестирование шейдера

Теперь все работает, но это не означает, что вы не можете немного поэкспериментировать со своим шейдером и проверить другие параметры материалов, текстуры или режимы визуализации.

Чтобы достичь эффекта проволочного каркаса, который вы видели раньше на рис. 6.5, просто измените значение FillMode перед запуском шейдера:

Или вы можете немного поуправлять материалами шейдера; если хотите, можете загрузить другую текстуру или даже модель. Класс шейдера написан таким образом, что позволяет вам загружать любую модель XNA и текстуру и тестировать их. Простейшим способом модификации результата работы шейдера могло бы быть изменение значений фоновой, рассеиваемой и отражаемой компонент, чтобы получить злое инопланетное яблоко (рис. 6.17).

Что значит компиляция шейдеров. Смотреть фото Что значит компиляция шейдеров. Смотреть картинку Что значит компиляция шейдеров. Картинка про Что значит компиляция шейдеров. Фото Что значит компиляция шейдеров

Пожалуйста, обратите внимание, что вы преобразуете цвета в Vector4, поскольку у SetValue нет перегрузки для цветовых значений (похоже, кто-то был очень ленивый). Когда вы устанавливаете любой параметр эффекта между вызовами Begin и End для шейдера, вы должны также вызвать метод Effect.CommitChanges, чтобы гарантировать, что все ваши изменения будут отправлены GPU. Если вы вызываете Begin после установки параметров, подобно тому, как это делается в классе SimpleShader, можете не беспокоиться об этом.

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

Источник

Компиляция шейдера студией

Почему, когда я компилирую шейдер студией вот так:

Что значит компиляция шейдеров. Смотреть фото Что значит компиляция шейдеров. Смотреть картинку Что значит компиляция шейдеров. Картинка про Что значит компиляция шейдеров. Фото Что значит компиляция шейдеров

То результат отличается от того, как если бы я делал вот так:

Причём размер получаемых файлов и первые 4 байта совпадают, а вот дальше идут отличия.

Всё бы ничего, но использование шейдера, полученного первым способом, приводит к тому, что комп зависает и его можно только перезагрузить, тогда как второй шейдер работает как положено.
Игрался с Disable Optimizations и Enable Debugging Information — не помогло. Но хочется всё-таки сделать, как положено. Идеи?

Alprog
Студия умеет компилировать шейдеры?!

Alprog
Скорее всего используется D3DCompiler другой версии.

-Eugene-
Уже умеет, генерирует бинарники для удобного использования в метровских приложениях. Вроде как неплохо, но теряется очень много возможностей.

Che@ter
> Скорее всего используется D3DCompiler другой версии.
Сейчас не дома. Не подскажешь, в какие настройки заглянуть первым делом?

-Eugene-
> Студия умеет компилировать шейдеры?!
Конечно. 21 век, все дела.

Alprog
> Конечно. 21 век, все дела.

Che@ter
> Скорее всего используется D3DCompiler другой версии
+100500

Alprog
> Сейчас не дома. Не подскажешь, в какие настройки заглянуть первым делом?
Без понятия, я компилирую шейдера по запросу в своем «сервере» и присылаю в клиентскую часть его бинарный код/рефлекшн. С студийной компиляцией дел не имею, так как нет смысле компилировать каждый раз/нельзя создать два бинарника одного шейдера с двумя дефайнами, а тем более если дефайнов много и они динамически выбираются.

Разобрался. В обоих случаях использовался D3DCompiler_46. Файлы были разные из-за того, что в коде добавлялся флаг D3DCOMPILE_ENABLE_STRICTNESS.
Поэтому для идентичного результата нужно было добавить /Ges в Additional Options для каждого файла.

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

Che@ter
> Вроде как неплохо, но теряется очень много возможностей.
Для каждого файла можно индивидуально задать опции командной строки.

Alprog
> Для каждого файла можно индивидуально задать опции командной строки.
А если файл генерировать в нескольких вариантах с разными дефайнами?

Che@ter
> А если файл генерировать в нескольких вариантах с разными дефайнами?
Это уже какой-то нетривиальный случай. Ожидать встроенной поддержки такого было бы самонадеянно.

Alprog
> а из-за того, что я криво копировал байткод.
То есть, чтобы уронить комп с виндой, достаточно скормить ДиректИксу кривой байткод?

Роман Шувалов
> То есть, чтобы уронить комп с виндой, достаточно скормить ДиректИксу кривой байткод?
Ну, наверное, не любой. Но да, достаточно.

Роман Шувалов
> То есть, чтобы уронить комп с виндой, достаточно скормить ДиректИксу кривой байткод?
А что такого?

Wraith
> А что такого?
Что значит «что такого»? Система не должна роняться, тем более таким несложным способом. Вина, скорее всего, драйвера, неумеющего при падении видеокарты корректно её привести в чувство.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *