仅对float3的着色器上的“语义”标记正确吗?

时间:2019-02-18 15:51:01

标签: unity3d shader cg

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

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真的可以吗? 通用float3是否有比POSITION更好的东西? (我注意到,如果您只是使用一种颜色,它也可以正常工作。这有关系吗?)

  2. “最后一号”系统实际上正确吗?那么,POSITION1很好吗?我没有融化GPU或类似的东西吗?

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

2 个答案:

答案 0 :(得分:1)

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

2:可供您使用的插值器寄存器数量取决于受支持的着色器模型(您可以使用#pragma target 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
}

答案 1 :(得分:1)

假设您的开发平台是iOS。

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

为了使着色器在iOS上运行,请统一将其从HLSL编译为Metal。 因此,如果我们要编译以下着色器部分:

HLSL:

float4 localPos: POSITION1;

这是编译结果:

金属:

float4 POSITION1 [[ user(POSITION1) ]];

根据Metal Shading Language Specification

  

[[user(name)]]语法也可用于指定   用户定义的变量的属性名称。

Unity3d将您的HLSL语义字段“名称”转换为Metal Language属性[user(name)]。 因此,无论您是否写:[ POSITION1 HelloWorld Fattie ], 只要它是唯一的并且不使用保留关键字。 因此,在编译以下着色器

之后

HLSL:

float4 localPos: Fattie;

这将是结果:

金属:

float4 Fattie0 [[ user(Fattie0) ]];

对于矢量数据类型,矢量类型[float,float2,float3,float4等] 不特定于您的自定义语义名称。 使用float3编译此着色器

HLSL:

float3 localPos: Fattie;

给出以下结果:

金属:

float3 Fattie0 [[ user(Fattie0) ]];