Мои Уведомления
Привет, !
Мой Аккаунт Мои Финансы Мои Подписки Мои Настройки Выход
Руководство API скрипты

При написании HLSL шейдерных программ, входные и выходные переменные должны иметь свое «намерение», указанное через семантику. Это стандартная концепция языка шейдеров HLSL; дополнительные сведения см. в документации по семантике в MSDN.

Семантика ввода вершинного шейдера

Главная вершина шейдерПрограмма, работающая на графическом процессоре. Подробнее
See in Словарь
(обозначается #вершина прагмы директива) должна иметь семантику для всех входных параметров. Они соответствуют отдельным Meshосновному графическому примитиву Unity. Меши составляют большую часть ваших 3D-миров. Unity поддерживает триангулированные или четырехугольные полигональные сетки. Поверхности Nurbs, Nurms, Subdiv должны быть преобразованы в полигоны. Подробнее
Просмотр в Словарь
элементов данных, таких как положение вершины, сетка нормалей и координаты текстуры . Дополнительные сведения см. в разделе входные данные вершинной программы.

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

Shader "Unlit/Show UVs" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; }; v2f vert ( float4 vertex : POSITION, // vertex position input float2 uv : TEXCOORD0 // first texture coordinate input ) { v2f o; o.pos = UnityObjectToClipPos(vertex); o.uv = uv; return o; } fixed4 frag (v2f i) : SV_Target { return fixed4(i.uv, 0, 0); } ENDCG } } }

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

Семантика вывода фрагментного шейдера

Чаще всего фрагментный (пиксельный) шейдер выводит цвет и имеет семантику SV_Target. Фрагментный шейдер в приведенном выше примере делает именно это:

fixed4 frag (v2f i) : SV_Target

Функция frag имеет возвращаемый тип fixed4 (цвет RGBA низкой точности). Поскольку она возвращает только одно значение, семантика указана в самой функции, : SV_Target.

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

struct fragOutput { fixed4 color : SV_Target; }; fragOutput frag (v2f i) { fragOutput o; o.color = fixed4(i.uv, 0, 0); return o; }

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

SV_TargetN: Несколько целей рендеринга

SV_Target1, SV_Target2 и т. д.: это дополнительные цвета, записываемые шейдером. Используется при рендерингепроцессе вывода графики на экран (или в текстуру рендеринга). По умолчанию основная камера в Unity отображает изображение на экране. Подробнее
Просмотр в Словарь
одновременно в нескольких целевых объектах рендеринга (известный как Множественный Метод рендеринга Render Targets, или MRT). SV_Target0 совпадает с SV_Target.

SV_Depth: вывод глубины пиксельного шейдера

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

Обратите внимание, что на многих графических процессорах это отключает некоторый буфер глубиныхранилище памяти, в котором хранится глубина z-значения каждого пикселя. в изображении, где z-значение — это глубина каждого отображаемого пикселя от плоскости проекции. Подробнее
См. Словарь
оптимизации, поэтому не переопределяйте значение буфера Z без уважительной причины. . Стоимость SV_Depth варьируется в зависимости от архитектуры графического процессора, но в целом она довольно похожа на стоимость альфа-тестирования (с использованием встроенного clip () в HLSL). Отрисовывайте шейдеры, изменяющие глубину, после всех обычных непрозрачных шейдеров (например, с помощью AlphaTest очереди рендеринга).

Выходное значение глубины должно быть одним числом с плавающей запятой.

Выходные данные вершинного шейдера и входные данные фрагментного шейдера

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

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

Многим современным графическим процессорам на самом деле все равно, какая семантика у этих переменных; однако в некоторых старых системах (особенно в графических процессорах шейдерной модели 2 на Direct3D 9) были особые правила в отношении семантики:

  • TEXCOORD0, TEXCOORD1 и т. д. используются для указания произвольных высокоточных данных, таких как координаты и положения текстур.
  • Семантика COLOR0 и COLOR1 для выходных данных вершин и входных данных фрагментов предназначена для низкоточных данных диапазона 0–1 (например, простых значений цвета). ).

Для лучшей межплатформенной поддержки пометьте выходные данные вершин и входные данные фрагментов как семантику TEXCOORDn.

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

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

  • До 8 интерполяторов: OpenGL ES 2.0 (Android), уровень Direct3D 11 9.x (Windows Phone) и модель шейдеров Direct3D 9 версии 2.0 (старые ПК). Поскольку количество интерполяторов ограничено, но каждый интерполятор может быть 4-компонентным вектором, некоторые шейдеры упаковывают все вместе, чтобы оставаться в пределах ограничений. Например, в одной переменной float4 можно передать две координаты текстуры (.xy для одной координаты, .zw для второй координаты).
  • До 10 интерполяторов: модель шейдеров Direct3D 9 версии 3.0 (#pragma target 3.0).
  • До 16 интерполяторов: OpenGL ES 3.0 (Android), Metal (iOS).
  • До 32 интерполяторов: модель шейдеров Direct3D 10 4.0 (#pragma target 4.0).

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

Другая специальная семантика

Позиция пикселя на экране: VPOS

Фрагментный шейдер может получать положение визуализируемого пикселя в виде специальной семантики VPOS. Эта функция существует только начиная с модели шейдера 3.0, поэтому шейдер должен иметь директиву компиляции #pragma target 3.0.

На разных платформах базовый тип ввода положения на экране различается, поэтому для максимальной переносимости используйте для него тип UNITY_VPOS_TYPE (это будет float4 на большинстве платформ и float2 на Direct3D 9).

Кроме того, использование семантики положения пикселя затрудняет использование положения пространства отсечения (SV_POSITION) и VPOS в одной и той же структуре вершин-фрагментов. Таким образом, вершинный шейдер должен выводить позицию отсечения в пространстве как отдельную переменную «out». См. пример шейдера ниже:

Shader "Unlit/Screen Position" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 // note: no SV_POSITION in this struct struct v2f { float2 uv : TEXCOORD0; }; v2f vert ( float4 vertex : POSITION, // vertex position input float2 uv : TEXCOORD0, // texture coordinate input out float4 outpos : SV_POSITION // clip space position output ) { v2f o; o.uv = uv; outpos = UnityObjectToClipPos(vertex); return o; } sampler2D _MainTex; fixed4 frag (v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target { // screenPos.xy will contain pixel integer coordinates. // use them to implement a checkerboard pattern that skips rendering // 4x4 blocks of pixels // checker value will be negative for 4x4 blocks of pixels // in a checkerboard pattern screenPos.xy = floor(screenPos.xy * 0.25) * 0.5; float checker = -frac(screenPos.r + screenPos.g); // clip HLSL instruction stops rendering a pixel if value is negative clip(checker); // for pixels that were kept, read the texture and output it fixed4 c = tex2D (_MainTex, i.uv); return c; } ENDCG } } }

Ориентация лица: VFACE

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

Эта функция доступна только начиная с модели шейдера 3.0 и выше, поэтому шейдер должен иметь директиву компиляции #pragma target 3.0.

Shader "Unlit/Face Orientation" { Properties { _ColorFront ("Front Color", Color) = (1,0.7,0.7,1) _ColorBack ("Back Color", Color) = (0.7,1,0.7,1) } SubShader { Pass { Cull Off // turn off backface culling CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 float4 vert (float4 vertex : POSITION) : SV_POSITION { return UnityObjectToClipPos(vertex); } fixed4 _ColorFront; fixed4 _ColorBack; fixed4 frag (fixed facing : VFACE) : SV_Target { // VFACE input positive for frontbaces, // negative for backfaces. Output one // of the two colors depending on that. return facing > 0 ? _ColorFront : _ColorBack; } ENDCG } } }

Приведенный выше шейдер использует состояние Cull, чтобы отключить отсечение обратной стороны (по умолчанию обращенные назад треугольники вообще не отображаются). Вот шейдер, примененный к набору Quadпримитивного объекта, который напоминает плоскость, но его края имеют длину всего одну единицу. использует только 4 вершины, а поверхность ориентирована в плоскости XY локального координатного пространства. Подробнее
См. в Словарь
сетки, повернутые в разные стороны:

Идентификатор вершины: SV_VertexID

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

Эта функция существует только в DX10 (модель шейдера 4.0) и GLCore/OpenGL ES 3, поэтому шейдер должен иметь директиву компиляции #pragma target 3.5.

Shader "Unlit/VertexID" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.5 struct v2f { fixed4 color : TEXCOORD0; float4 pos : SV_POSITION; }; v2f vert ( float4 vertex : POSITION, // vertex position input uint vid : SV_VertexID // vertex ID, needs to be uint ) { v2f o; o.pos = UnityObjectToClipPos(vertex); // output funky colors based on vertex ID float f = (float)vid; o.color = half4(sin(f/10),sin(f/100),sin(f/1000),0) * 0.5 + 0.5; return o; } fixed4 frag (v2f i) : SV_Target { return i.color; } ENDCG } } }
Вы можете отблагодарить автора, за перевод документации на русский язык. ₽ Спасибо
Руководство Unity 2021.3