着色器在 Properties 代码块中声明材质属性。如果要在着色器程序中访问其中一些属性,则需要声明具有相同名称和匹配类型的 Cg/HLSL 变量。着色器教程:顶点和片元程序中提供了一个示例。
例如,以下着色器属性:
_MyColor ("Some Color", Color) = (1,1,1,1)
_MyVector ("Some Vector", Vector) = (0,0,0,0)
_MyFloat ("My float", Float) = 0.5
_MyTexture ("Texture", 2D) = "white" {}
_MyCubemap ("Cubemap", CUBE) = "" {}
可通过如下 Cg/HLSL 代码进行声明以供访问:
fixed4 _MyColor; // 低精度类型对于颜色而言通常已经足够
float4 _MyVector;
float _MyFloat;
sampler2D _MyTexture;
samplerCUBE _MyCubemap;
Cg/HLSL 还可以接受 uniform 关键字,但该关键字并不是必需的:
uniform float4 _MyColor;
ShaderLab 中的属性类型以如下方式映射到 Cg/HLSL 变量类型:
在下列位置中查找着色器属性值并提供给着色器:
优先顺序如上所述:每实例数据覆盖所有内容;然后使用材质数据;最后,如果这两个地方不存在着色器属性,则使用全局属性值。最终,如果在任何地方都没有定义着色器属性值,则将提供“默认值”(浮点数的默认值为零,颜色的默认值为黑色,纹理的默认值为空的白色纹理)。
材质可以同时包含序列化的属性值和运行时设置的属性值。
序列化的数据是在着色器的 Properties 代码块中定义的所有属性。通常,这些是需要存储在材质中的值,并且可由用户在材质检视面板中进行调整。
材质也可以具有着色器使用的一些属性,但不在着色器的 Properties 代码块中声明。通常,这适用于在运行时从脚本代码(例如,通过 Material.SetColor)设置的属性。请注意,矩阵和数组只能作为非序列化的运行时属性存在(因为无法在 Properties 代码块中定义它们)。
对于设置为着色器/材质属性的每个纹理,Unity 还会在其他矢量属性中设置一些额外信息。
材质通常具有其纹理属性的 Tiling 和 Offset 字段。此信息将传递到着色器中的 float4 {TextureName}_ST
属性:
x
包含 X 平铺值y
包含 Y 平铺值z
包含 X 偏移值w
包含 Y 偏移值例如,如果着色器包含名为 _MainTex
的纹理,则平铺信息将位于 _MainTex_ST
矢量中。
{TextureName}_TexelSize
- float4 属性包含纹理大小信息:
x
包含 1.0/宽度y
包含 1.0/高度z
包含宽度w
包含高度{TextureName}_HDR
- 一个 float4 属性,其中包含有关如何根据所使用的颜色空间解码潜在 HDR(例如 RGBM 编码)纹理的信息。请参阅 UnityCG.cginc 着色器 include 文件中的 DecodeHDR
函数。
使用线性颜色空间时,所有材质颜色属性均以 sRGB 颜色提供,但在传递到着色器时会转换为线性值。
例如,如果 Properties 着色器代码块包含名为“MyColor“的 Color
属性,则相应的”MyColor”HLSL 变量将获得线性颜色值。
对于标记为 Float
或 Vector
类型的属性,默认情况下不进行颜色空间转换;而是假设它们包含非颜色数据。可为浮点/矢量属性添加 [Gamma]
特性,以表示它们是以 sRGB 空间指定,就像颜色一样(请参阅属性)。