仅针对 float3 更正着色器上的 "Semantic" 标记?

Correct "Semantic" tag on a shader for just a float3?

这是一个非常简单的着色器,

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 的语义。

查看 Unity 的 doco,他们当然没有,但是有 link 到

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

(除此之外 - 据我了解,它专门用于 D3D,但是,我想这就是 syntax/semantic 可以使用的吗?)

我的阅读情况,

建议你应该使用 say,

struct PositionHolder
{
    float3 localPos :POSITION1;
};

或者实际上,您还没有将位置任意数字用作资源。

怎么样,

struct PositionHolder
{
    float3 localPos :POSITION8;
};

祝你好运。

(令人困惑的是,它们似乎 运行 仅从 空白到 9,我不知道这是否反映了硬件现实,或者只是某处的劣质产品- 或什么。但无论如何,基本上是“您尚未在其他地方使用的任何数字 1 到 9。)

  1. 请注意,无论如何,POSITION 是一个 float4,真的适合我的 float3 吗? 对于通用的 float3,有没有比 POSITION 更好的东西? (我注意到如果你只使用,比如说,一种颜色,它也能正常工作。这有关系吗?)

  2. “1 on the end”系统实际上正确吗?那么,POSITION1 可以开始了吗?我没有融化 gpu 或类似的东西?

  3. 嗯,我注意到您可以在其中输入任何内容(例如,"abcd1")。但是可以肯定的是,它实际上不是硬件寄存器吗???

1:GPU 寄存器是基于硬件的,它们总是大小为 4 的向量(float4 等),语义只是为了将变量绑定到名称,以便所有数据最终都在正确的位置。 GPU 上的所有矢量运算都使用 SIMD(单指令,多数据),因此对矢量执行计算几乎与标量一样快。但是,我不确定 POSITION,通常这个名称只填充输入变量的函数 - 对于您自己的任意输出变量,您应该使用 TEXCOORD0-N。 COLOR 插值器具有 8 位精度,也可能将值限制在 0-1 的范围内。

2:您可以使用的插值器寄存器的数量取决于支持的着色器模型(您可以使用#pragma target 4.0 来支持最多 32 个插值器,代价是至少需要 Direct3D 10)。但是,是的,您可以使用 0 或 8 或 4 或其他任何值。

3:你试过了吗?实际上,语义只是用来为编译器提供 hints/labels 我们想要什么数据在哪里。但是对于大多数值,我们使用哪个寄存器并不重要,显式输入寄存器实际上只是过去的遗留问题。不过,我从未见过有人将随机的东西写成着色器语义!

就个人而言,我认为像这样构建输入和输出更直观:

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
}

假设您的开发平台是iOS。

iOS有自己的着色器语言——金属着色语言。

为了让您的着色器在 iOS 上工作,unity 将它们从 HLSL 编译为 Metal。 因此,如果我们要编译以下着色器部分:

HLSL:

float4 localPos: POSITION1;

编译结果如下:

金属:

float4 POSITION1 [[ user(POSITION1) ]];

根据Metal Shading Language Specification

The attribute [[user(name)]] syntax can also be used to specify an attribute name for any user-defined variables.

Unity3d 将您的 HLSL 语义字段 "name" 转换为 Metal Language 属性 [user(name)]。 所以,写成:[POSITION1HelloWorldFattie] 都没关系, 只要它是唯一的并且不使用保留关键字。 因此,编译以下着色器后

HLSL:

float4 localPos: Fattie;

这将是结果:

金属:

float4 Fattie0 [[ user(Fattie0) ]];

关于向量数据类型,向量类型[float, float2, float3, float4, etc] 不特定于您的自定义语义名称。 使用 float3

编译此着色器

HLSL:

float3 localPos: Fattie;

给出以下结果:

金属:

float3 Fattie0 [[ user(Fattie0) ]];