Как узнать пиксель шейдеры и вертел шейдеры

Обновлено: 04.07.2024

Вершинные шейдеры (также: вершинные шейдеры ., Сокращенно VS ) - это разновидности шейдеров . Они выполняются в ходе графического конвейера , то есть обработки трехмерного объекта на видеокарте . В этом контексте вершинные шейдеры отвечают за обработку всех угловых точек 3D-модели (так называемых вершин ). Вот почему вершинный шейдер обычно вызывается один раз для каждой вершины, отсюда и происходит название.

содержание

функция

Вершинный шейдер используется для управления геометрией сцены. Для этого преобразуются координаты вершин (угловые точки трехмерных объектов) поверхностей (что может включать в себя как сдвиг, так и поворот или масштабирование, возможно, также комбинации). Таким образом можно влиять на форму объектов, что, в свою очередь, также отражается на их освещении. Типичная модификация модели, выполняемая в вершинном шейдере, касается систем координат . Вершинный шейдер сначала преобразует положение вершин из системы координат 3D-модели в глобальную систему координат, общую для всех 3D-объектов. Затем он также может преобразовать вершины в систему координат камеры. Однако, поскольку вершинный шейдер вызывается для каждой вершины, вершинный шейдер не может добавлять новые точки в 3D-модель. Однако эту задачу выполняет шейдер геометрии , который обычно вызывается после шейдера вершин. Современные видеокарты также могут иметь шейдеры тесселяции для добавления новых вершин. С точки зрения функциональности, вершинный шейдер заменяет более старый и менее гибкий Transform & Lighting (T&L).

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

Дополнительную информацию о цепочке обработки и программировании шейдеров можно найти в статье Shader .

совместимость

аппаратное обеспечение

В следующей таблице представлен обзор того, какие видеокарты или графические чипы с какой версией DirectX поддерживают какую версию вершинного шейдера. Для полноты картины также был включен T&L, предшественник вершинных шейдеров. Следует отметить, что графические чипы обычно также поддерживают более старые версии, например чипы вершинных шейдеров 3.0 также могут работать с вершинными шейдерами версии 2.0. Эта обратная совместимость в основном обеспечивается драйвером видеокарты, а не графическим процессором.

програмное обеспечение

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

  • Обойтись полностью без вершинных шейдеров и все рассчитать с помощью CPU. Этот подход уже не является распространенным сегодня, потому что почти каждое 3D-приложение сегодня имеет требования к производительности, которые требуют достаточно быстрых видеокарт, которые, в свою очередь, настолько актуальны, что уже содержат блоки вершинных шейдеров.
  • для поддержки многих версий вершинных шейдеров путем написания собственного оптимизированного шейдера для каждой поддерживаемой версии (так называемые пути рендеринга ). Поддерживаются все видеокарты, совместимые с целевыми версиями шейдеров.
  • поддерживают только версии вершинных шейдеров, начиная с определенной версии.

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

Пора научиться работать с шейдерами и источниками текстур при разработке игры Microsoft DirectX для Windows 8. Мы рассмотрели, как настроить графическое устройство и ресурсы, и, возможно, вы даже начали изменять его конвейер. Теперь давайте взглянем на шейдеры пикселей и вершин.

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

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

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

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

В Direct3D шейдеры не компилируются во время выполнения. они компилируются при компиляции остальной части программы. при компиляции приложения с Microsoft Visual Studio 2013 файлы HLSL компилируются в файлы cso (. CSO), которые приложение должно загрузить и поместить в память GPU перед прорисовкой. Убедитесь, что вы включили эти файлы CSO в свое приложение при упаковке. они представляют собой ресурсы, такие как сетки и текстуры.

Общие сведения о семантике HLSL

Прежде чем продолжить, важно обсудить семантику HLSL, так как они часто являются предметом путаницы для новых разработчиков Direct3D. Семантика HLSL — это строки, которые определяют значение, передаваемое между приложением и программой шейдера. Хотя они могут быть любыми различными возможными строками, рекомендуется использовать такую строку, как POSITION или COLOR , которая указывает на использование. Вы назначаете эту семантику при построении буфера констант или макета ввода. Можно также добавлять к семантике цифру от 0 до 7, чтобы использовать отдельные регистры для сходных значений. Например: COLOR0, COLOR1, COLOR2.

Семантика с префиксом «SV _ » — это семантика системных значений , записываемая программой шейдера; сама игра (работающая на ЦП) не может изменить их. Как правило, эти семантики содержат значения, которые являются входными или выходными данными из другого этапа шейдера в графическом конвейере или полностью созданы графическим процессором.

Кроме того, SV_ семантика имеет различные поведения, когда они используются для указания входных данных или выходных данных на этапе шейдера. Например, SV_POSITION (Output) содержит данные вершин, преобразованные на этапе шейдера вершин, а SV_POSITION (входные данные) содержат значения точек в пикселях, которые были интерполяции GPU во время этапа растрирования.

Ниже приведена общая семантика HLSL:

  • POSITION (n) для данных в буфере вершин. SV_POSITION Задает точку в пикселе шейдера пикселей и не может быть записана в игре.
  • NORMAL (n) для обычных данных, предоставляемых буфером вершин.
  • TEXCOORD (n) для данных текстуры UV-координат, предоставляемых шейдеру.
  • COLOR (n) для цветовых данных RGBA, предоставляемых шейдеру. Обратите внимание, что он обрабатывается одинаково для координации данных, включая интерполяцию значения во время растрирования. семантика просто помогает понять, что это данные цвета.
  • SV_Target [n ] для записи из шейдера пикселей в целевую текстуру или другой буфер пикселей.

Мы рассмотрим некоторые примеры семантики HLSL, как мы рассмотрим пример.

Чтение из буферов констант

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

Буфер константы объявляется в двух местах: в коде C++ и в соответствующих файлах HLSL, которые будут обращаться к нему.

Вот как объявляется структура буфера констант в коде C++.

При объявлении структуры для буфера констант в коде C++ Убедитесь, что все данные правильно выводятся по 16-байтным границам. Самый простой способ сделать это — использовать типы директксмас , такие как XMFLOAT4 или XMFLOAT4X4, как показано в примере кода. Можно также защититься от несогласованных буферов путем объявления статического утверждения:

Эта строка кода вызовет ошибку во время компиляции, если константбуфферструкт не является 16-байтовым. Дополнительные сведения о выравнивании и упаковке буфера констант см. в разделе правила упаковки для переменных констант.

Теперь вот как объявляется буфер констант в шейдере вершин HLSL.

Все буферы — константы, текстуры, образцы или другие — должны иметь определенный регистр, чтобы GPU мог получить к ним доступ. Каждый этап шейдера поддерживает до 15 буферов констант, и каждый буфер может содержать до 4 096 переменных констант. Синтаксис объявления использования регистра выглядит следующим образом:

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

Вы можете назначать постоянные буферы для регистрации — при настройке конвейера вы подключаете буфер константы к тому же слоту, в котором он был назначен в файле HLSL. Например, в предыдущем разделе вызов вссетконстантбуфферс указывает "0" для первого параметра. Это указывает Direct3D подключить ресурс буфера константы для регистрации 0, который соответствует назначению буфера для регистрации (B0) в файле HLSL.

Чтение из буферов вершин

Буфер вершин предоставляет данные треугольника для объектов сцены в шейдер вершин. Как и в случае с буфером констант, структура буфера вершин объявляется в коде C++ с использованием аналогичных правил упаковки.

В Direct3D 11 нет стандартного формата для данных вершин. Вместо этого мы определяем собственный макет данных вершин с помощью дескриптора. поля данных определяются с помощью массива структур D3D11 _ _ элемента _ input . Здесь показан простой макет ввода, описывающий тот же формат вершин, что и в предыдущей структуре:

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

В этом случае необходимо изменить определение макета ввода следующим образом.

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

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

Передача данных между шейдерами

Шейдеры принимают входные типы и возвращают выходные типы из своих основных функций при выполнении. Для шейдера вершин, определенного в предыдущем разделе, тип входных данных был _ структурой ввода VS, и мы определили соответствующий макет входных данных и структуру C++. Массив этой структуры используется для создания буфера вершин в методе CreateCube .

Шейдер вершин возвращает _ входную структуру PS, которая должна быть минимально содержать конечную точку вершины 4 компонента (float4). Значение этой должности должно иметь семантику системного значения, SV_POSITION , объявленную для нее, чтобы GPU имел данные, необходимые для выполнения следующего шага рисования. Обратите внимание, что отсутствует соответствие 1:1 между выходным шейдером вершин и входными данными шейдера пикселей. Шейдер вершин возвращает одну структуру для каждой указанной вершины, но шейдер пикселей выполняется один раз для каждого пикселя. Это обусловлено тем, что данные на вершине сначала проходят через этап растрирования. Этот этап определяет, на каких пикселях размещается геометрическая геометрия, вычисление интерполяции данных на вершину для каждого пикселя, а затем вызывает шейдер пикселей один раз для каждого из этих пикселов. Интерполяция является поведением по умолчанию при растрировании выходных значений и является обязательным в частности для правильной обработки данных вектора вывода (светлое векторы, нормали к вершинам, касательные и др.).

Проверка шейдера вершин

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

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

Проверка построителя текстуры

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

Важной частью является SV_TARGET семантика системного значения для возвращаемого значения. Он указывает, что выходные данные должны быть записаны в основной целевой объект отрисовки, который является буфером текстуры, переданным в цепочку подкачки для отображения. Это требуется для шейдеров пикселей — без цветовых данных из шейдера пикселей в Direct3D ничего не отображается!

Пример более сложного шейдера пикселей для выполнения заливки по методу Фонга может выглядеть следующим образом. Так как векторы и нормали были интерполируются, нам не нужно вычислять их на основе каждого пикселя. Однако нам придется повторно нормализовать их из-за того, как работает интерполяция. по сути, нам нужно постепенно «прокрутить» вектор от направления к концу а к направлению на вершину B, сохранив его длину — вхерас интерполяцию, а не горизонтальную линию между двумя конечными точками вектора.

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

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

Дальнейшие действия

Надеюсь, вы уже знакомы с DirectX 11at на этом этапе и готовы приступить к работе над проектом. Ниже приведены ссылки на другие вопросы, которые могут возникнуть при разработке с помощью DirectX и C++.

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

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

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

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

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

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

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

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

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

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

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

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

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

Из занимательного — итоговые вершины располагаются на так называемой плоскости Clip Space и находятся в диапазоне от -1.0 до 1.0. Именно с такими координатами потом и работает видеокарта.

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

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

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

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

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

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

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

Шейдеры. Как их ковырять и что означает каждый пункт.


Немного теории:
Несомненно шейдеры - лучший графический мод для minecraft, но называть их шейдерами - тоже неверно, так как шейдер это

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


То, что мы имеем - скрпиты для работы непосредственно самих шейдеров в видеокарте. Но для удобства будем называть их шейдерами, хоть это и неверно. Если у вас видеокарта не тянет OpenGL той версии на которой сделаны шейдеры - вы их не увидите.
Как связаны OpenGL и GLSL? А вот так:

GLSL (OpenGL Shading Language) — язык высокого уровня для программирования шейдеров.


Даже "GLSL Shaders" - обозначение того, что скрипты сделаны на языке GLSL, не более. Но теперь это название всех шейдеров SEUS, пусть будет так.
Причем тут вообще OpenGL? Почему не DirectX?
Потому что гладиолус
Потому что Java мультиплатформенная. платформа. И для мультиплатформенной платформы нужна мультиплатформенная графическая составляющая, которая будет отображать твои труды, быдлокодер, коей является OpenGL(есть еще OpenCL, но это уже другая история), потому что DirectX заточен под винду и вообще это библиотеки майкрософта, поэтому кроме Винды они нигде работать не будут, ну и еще XBOX, там тоже DirectX! Да да! И в XBOX One тоже.
Мы ознакомимся со всеми файлами шейдера и возможными настройками внутри них.
Редактор который я рекомендую - notepad++, бесплатный и хороший. Только нет подсветки синтаксиса.
Можно извертеться и скачать GPU Shader Analyzer от AMD, но он помуторнее и нельзя находу практически менять значения, как это делал я в видеоролике, зато есть подсветка синтаксиса.
Сам код шейдера я не стал трогать, так как без знаний GLSL там нечего почти делать. Максимум - копировать коды из других шейдеров. Так в RC7 v8 Ultra появилось

Читайте также: