【问题标题】:Correct "Semantic" tag on a shader for just a float3?为 float3 正确着色器上的“语义”标签?
【发布时间】:2019-02-18 15:51:01
【问题描述】:

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

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

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

(除此之外 - 据我所知,它是专门针对 D3D 的,但是,我想这就是要使用的语法/语义吗?)

我对情况的解读,

建议你应该使用say,

struct PositionHolder
{
    float3 localPos :POSITION1;
};

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

怎么样,

struct PositionHolder
{
    float3 localPos :POSITION8;
};

祝你好运。

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

  1. 请注意,无论如何,POSITION 是一个 float4,我的 float3 真的可以吗? 对于通用 float3,有什么比 POSITION 更好的方法吗? (我注意到如果你只使用一种颜色,它也可以正常工作。这有关系吗?)

  2. “1 on the end”系统真的正确吗?那么,POSITION1 好走吗?我没有融化 gpu 之类的?

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

【问题讨论】:

  • UV 是一个很好的自定义数据容器,被插值并且有四个
  • 位置仅针对每个顶点,但 UV 以插值形式传递给片段着色器,因此您不必使用其他形式的诡计来知道您在哪里
  • 关于您的第三个问题 - 关于一些示例,我不知道答案:一个很好的起点,可能需要半小时才能完全遵循:docs.unity3d.com/Manual/SL-SurfaceShaderExamples.html
  • 哦,我确实已经完成了所有这些工作 - 不幸的是,它没有解释任何有关语义标签的内容。 (什么都没有!呵呵。)

标签: unity3d shader cg


【解决方案1】:

假设您的开发平台是 iOS。

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

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

HLSL:

float4 localPos: POSITION1;

编译结果如下:

金属:

float4 POSITION1 [[ user(POSITION1) ]];

根据Metal Shading Language Specification

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

Unity3d 将您的 HLSL 语义字段“名称”翻译为金属语言属性 [用户(名称)]。 所以,如果你写:[POSITION1 或 HelloWorld 或 Fattie] 也没关系, 只要它是唯一的并且不使用保留关键字。 因此,在编译了以下着色器之后

HLSL:

float4 localPos: Fattie;

这将是结果:

金属:

float4 Fattie0 [[ user(Fattie0) ]];

关于向量数据类型,向量类型[float, float2, float3, float4, etc] 不特定于您的自定义语义名称。 用 float3 编译这个着色器

HLSL:

float3 localPos: Fattie;

给出以下结果:

金属:

float3 Fattie0 [[ user(Fattie0) ]];

【讨论】:

  • 这适用于使用 hlsl 作为后端的平台,例如 Xbox。对于 iOS,Unity 着色器编译器会标记可能影响性能的重要关键字,因此如果您尝试更改它们,则会导致编译错误。
  • 再次感谢;为了清楚起见,我相信在构建到简单的 Windows(所以,你的 nVidia 卡)时,它确实“这样做”——它们成为 GPU 上的硬件寄存器? (再一次,我可能都错了。)
  • 这取决于语义关键字。例如,如果我们想在顶点着色器中获取顶点位置,我们必须使用 POSITION 语义关键字。在这种情况下,GPU 将使用特殊寄存器。
  • 很高兴为您提供帮助!另外,如果你想在unity3d中使用Metal Shading Language,请查看this官方仓库。
  • 从 iPhone 5S 开始的所有 iOS 设备都支持金属。如果您在 Unity3d 中的 Graphics APIs 下仅选择了 Metal,则 unity 将使用 Metal + Metal Shader Language,而不会使用 OpenGL。 Apple 声明使用 OpenGL 的游戏和图形密集型应用现在应该采用 Metal,因为 OpenGL 是一项传统技术,很快就会被弃用。
【解决方案2】:

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:你试过吗?真的,语义只是用来为编译器提供关于我们想要什么数据在哪里的提示/标签。然而,对于大多数值来说,我们使用哪个寄存器并不重要,明确地输入寄存器实际上只是过去的遗产。不过,我从未见过有人将随机的东西写成着色器语义!

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

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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 2020-05-30
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多