Unity3d “正确”;语义;仅为一个float3标记着色器?

Unity3d “正确”;语义;仅为一个float3标记着色器?,unity3d,shader,cg,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 {

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

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,他们当然没有,但是有一个链接

(旁白——据我所知,这是专门针对D3D的,但是,我想这就是语法/语义?)

我对形势的解读

建议您使用say

struct PositionHolder
{
    float3 localPos :POSITION1;
};
或者,实际上,定位您尚未用作资源的任何号码

那么

struct PositionHolder
{
    float3 localPos :POSITION8;
};
祝你好运

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

  • 请注意,
    POSITION
    是一个float4,对我的float3真的可以吗???有什么比通用float3的位置更好的吗?(我注意到,如果你只使用一种颜色,它也可以工作。这有关系吗?)

  • “最后一个1”系统是否真的正确?那么,位置1很好?我没有融化gpu或类似的东西

  • 嗯,我注意到你可以在里面输入任何东西(比如说,“abcd1”)。但那肯定不是硬件寄存器之类的东西


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

    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
    }
    

    假设您的开发平台是iOS

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

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

    HLSL:

    float4 localPos: POSITION1;
    
    float4 POSITION1 [[ user(POSITION1) ]];
    
    float4 localPos: Fattie;
    
    float3 localPos: Fattie;
    
    float3 Fattie0 [[ user(Fattie0) ]];
    
    这就是编译结果:

    金属:

    float4 localPos: POSITION1;
    
    float4 POSITION1 [[ user(POSITION1) ]];
    
    float4 localPos: Fattie;
    
    float3 localPos: Fattie;
    
    float3 Fattie0 [[ user(Fattie0) ]];
    

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

    Unity3d将HLSL语义字段“名称”转换为金属语言属性[用户(名称)]。 所以,不管你写:[职位1或HelloWorld或Fattie], 只要它是唯一的并且不使用保留关键字。 因此,在编译以下着色器之后

    HLSL:

    float4 localPos: POSITION1;
    
    float4 POSITION1 [[ user(POSITION1) ]];
    
    float4 localPos: Fattie;
    
    float3 localPos: Fattie;
    
    float3 Fattie0 [[ user(Fattie0) ]];
    
    结果是:

    金属:

    float4 Fattie0 [[ user(Fattie0) ]];
    

    对于向量数据类型,向量类型[浮点、浮点2、浮点3、浮点4等] 不特定于您的自定义语义名称。 使用float3编译此着色器

    HLSL:

    float4 localPos: POSITION1;
    
    float4 POSITION1 [[ user(POSITION1) ]];
    
    float4 localPos: Fattie;
    
    float3 localPos: Fattie;
    
    float3 Fattie0 [[ user(Fattie0) ]];
    
    给出以下结果:

    金属:

    float4 localPos: POSITION1;
    
    float4 POSITION1 [[ user(POSITION1) ]];
    
    float4 localPos: Fattie;
    
    float3 localPos: Fattie;
    
    float3 Fattie0 [[ user(Fattie0) ]];
    

    UV是一个很好的自定义数据容器,它被插值,其中有四个位置仅为每个顶点,但UV以插值形式传递给片段着色器,所以你不必使用其他形式的诡计来知道你在第三个问题上的位置-关于一些示例,我不知道答案:这是一个很好的起点大概需要半个小时才能完全理解这里的内容:哦,我肯定已经完成了所有这些工作-不幸的是,它没有解释任何关于语义标记的内容。(什么也解释不了!呵呵。)对于使用hlsl作为后端的平台(如Xbox),这是正确的。对于iOS,Unity shader compiler会标记可能影响性能的重要关键字,因此,如果您尝试更改它们,将导致编译错误。再次感谢;为了清晰起见,我相信在构建简单的Windows(即您的nVidia卡)时,确实会这样做。”这样做”-它们成为GPU上的硬件寄存器?(同样,我可能完全错了。)这取决于语义关键字。例如,如果我们想在顶点着色器中获取顶点位置,我们必须使用位置语义关键字。在这种情况下,GPU将使用特殊寄存器。很高兴提供帮助!此外,如果您想在unity3d中使用金属着色语言,请查看官方存储库。从iPhone 5S开始的所有iOS设备都支持ort metal。如果您在图形API下的Unity3d中只选择了金属,那么unity将使用金属+金属着色器语言,而OpenGL将不会使用。苹果表示,使用OpenGL的游戏和图形密集型应用程序现在应该采用金属,因为OpenGL是一种传统技术,不久将被弃用。