这是一个非常简单的着色器,
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的文档,它们当然没有任何内容,但是有一个指向
的链接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的数字。)
请注意,无论如何,POSITION
是一个float4,对于我的float3真的可以吗? 通用float3是否有比POSITION更好的东西? (我注意到,如果您只是使用一种颜色,它也可以正常工作。这有关系吗?)
“最后一号”系统实际上正确吗?那么,POSITION1很好吗?我没有融化GPU或类似的东西吗?
嗯,我注意到您可以在其中键入任何内容(例如“ abcd1”)。但是可以肯定的是,这实际上不是硬件寄存器吗?
答案 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) ]];