Правильный тег "Semantic" на шейдере для float3? - PullRequest
0 голосов
/ 18 февраля 2019

Вот очень простой шейдер,

float4 vert (float4 vertex :POSITION, out PositionHolder o) :SV_POSITION
{
    UNITY_INITIALIZE_OUTPUT(PositionHolder,o);
    o.localPos = vertex;
    return UnityObjectToClipPos(vertex);
}

fixed4 frag (PositionHolder IN) :SV_Target
{
    if (IN.localPos.y > -.2)
        return _UpperColor;
    else
       return _LowerColor;
}

(Таким образом, если на четырехугольнике он просто рисует верхние 70% одним цветом, а нижнюю полосу - другим цветом).

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

Вот структура для этого

struct PositionHolder
{
    float3 localPos;
};

Однако (в любом случае в Unity) этозахочет семантику для этого float3.

enter image description here

Изучая документацию Unity, у них, конечно, нет, но естьссылка на

https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-semantics

(Кроме того - какой, насколько я понимаю, специально для D3D, но, я полагаю, это синтаксис / семантика в любом случае?)

Мое прочтение ситуации,

предлагает вам использовать, скажем,

struct PositionHolder
{
    float3 localPos :POSITION1;
};

Или действительно, позиция-любое-число, которого вы еще не сделалииспользуя в качестве ресурса.

Как насчет

struct PositionHolder
{
    float3 localPos :POSITION8;
};

на удачу.

(Смущает, что, кажется, они бегут только от пробел до 9 , я незнать, отражает ли это аппаратную реальность, или это просто что-то нехорошее - или что. Но в любом случае, в основном, «любое число от 1 до 9, которое вы еще нигде не используете.)

  1. Примечаниев любом случае, POSITION является float4, действительно ли это нормально для моего float3 ?? Есть ли что-то лучше, чем POSITION для float3 общего назначения? (Я заметил, что если вы просто используете, скажем,ЦВЕТ, он также отлично работает. Имеет ли это значение?? Я не таю gpu или что-то подобное?

  2. Хм, я заметил, что вы можете просто ввести НИЧЕГО там (скажем, "abcd1"). Но, конечно, тогда это не такна самом деле аппаратный регистр чтоли ???

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Допустим, ваша платформа разработки - iOS.

В iOS есть свой собственный язык шейдеров - язык металлических шейдеров.

Чтобы ваши шейдеры работали на iOS, Unity компилирует их из HLSL вМеталл.Так что, если бы мы должны были скомпилировать следующую часть шейдера:

HLSL:

float4 localPos: POSITION1;

это будет результат компиляции:

Металл:

float4 POSITION1 [[ user(POSITION1) ]];

Согласно Спецификация языка затенения металла

Синтаксис атрибута [[user (name)]]также может использоваться для указания имени атрибута для любых пользовательских переменных.

Unity3d преобразует ваше семантическое поле HLSL "имя" в атрибут языка языка [пользователь (имя)].Таким образом, не имеет значения, если вы напишите: [ POSITION1 или HelloWorld или Fattie ], если оно уникально и не использует зарезервированные ключевые слова.Следовательно, после компиляции следующего шейдера

HLSL:

float4 localPos: Fattie;

это будет результат:

Металл:

float4 Fattie0 [[ user(Fattie0) ]];

Что касается векторных типов данных, векторные типы [float, float2, float3, float4 и т. Д.] Не являются специфическими для имени вашей пользовательской семантики.Компиляция этого шейдера с помощью float3

HLSL:

float3 localPos: Fattie;

дает следующий результат:

Металл:

float3 Fattie0 [[ user(Fattie0) ]];
0 голосов
/ 19 февраля 2019

1: регистры графического процессора основаны на аппаратном обеспечении, и они всегда являются векторами размера 4 (float4 и т. Д.), Семантика предназначена только для привязки переменных к именам, чтобы все данные оказались в нужном месте.Все векторные операции на графическом процессоре используют SIMD (один инструктаж, несколько данных), поэтому выполнение вычислений на векторе выполняется почти так же быстро, как и на скаляре.Однако я не уверен насчет POSITION, обычно это имя заполняет функцию только для входных переменных - для ваших собственных произвольных выходных переменных вы должны использовать TEXCOORD0-N.Интерполяторы COLOR имеют 8-битную точность и могут также фиксировать значения в диапазоне 0-1.

2: Количество регистров интерполяции в вашем распоряжении зависит от поддерживаемой модели шейдера (вы можете использовать #pragmaцель 4.0 для поддержки до 32 интерполяторов, при этом требуется минимум Direct3D 10).Но да, вы можете использовать 0 или 8 или 4 или что-то еще.

3: Вы пробовали это?Действительно, семантика просто используется для предоставления подсказок / меток для компилятора относительно того, какие данные мы хотим, где.Тем не менее, для большинства значений не имеет значения, какой регистр мы используем, и явный ввод регистров является просто наследием прошлого.Я никогда не видел, чтобы кто-то писал случайные вещи как семантику шейдеров!

Лично я думаю, что более интуитивно понятно структурировать ваш ввод и вывод так:

struct VertexInput {
    // Here we use POSITION to tell the compiler that we want the vertex coords to be written to this variable.
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct VertexOutput {
    float4 clipPos : SV_POSITION;
    // Here we use TEXCOORD0-1, since these are just variables to be interpolated. 
    float3 localPos : TEXCOORD0; 
    float3 normal : TEXCOORD1;
};

VertexOutput Vert(VertexInput v) {
    VertexOutput o;

    o.clipPos = UnityObjectToClipPos(v.vertex);
    o.localPos = v.vertex;
    o.normal = UnityObjectToWorldNormal(v.normal);

    return o;
}

fixed4 Frag(VertexOutput o) : SV_Target {
    half3 normal = normalize(o.normal); // Interpolated values are not necessarily normalized
    half NdotL = saturate(dot(normal, _WorldSpaceLightPos0.xyz));
    return fixed4((fixed3)NdotL, 1); // Basic lambert lighting as an example
}
...