用于记录 Unity3D 的 Shader 关键字、或内置函数、变量等,便于查询,视情况修改。

# Properties

[Attribute]_Name ("Display Name",Type) = Default Value

# 类型 (Type)

  • Color 颜色
  • Int 整数
  • Float、[Range (Min,Max)] 浮点数
  • Vector 四维向量
  • 2D 纹理(默认值:white、black、grey、bump)
  • 3D 纹理
  • Cube 立方体纹理

# 属性 (Attribute)

  • HDR:用于 Color 类型,将颜色取色器设置为支持 HDR 类型
  • PowerSlider (Value):用于 Int 或 Float 类型,调整材质面板上滑杆拉动效果,对拉动值区间微调
  • IntRange:当标记给 Range (Min,Max) 类型时,会导致材质面板只能拖动整数值
  • Toggle:开关,用于 Int 或 Float 类型,0 代表关,1 代表开
  • Enum (C# 中的枚举类型):枚举,用于 Int 或 Float 类型
  • NoScaleOffset:用于纹理类型,取消面板 Tiling 、Offset 的设置选项
  • Normal:用于 2D 纹理类型,标记图片必须为法线贴图
  • HideInInspector:在面板隐藏
  • MainTexture: 表示一个属性 (property) 是材质的主纹理。默认情况下,Unity 将属性 (property) 名称为 _MainTex 的纹理视为主纹理。
  • MainColor:表示一个属性 (property) 是材质的主色。默认情况下,Unity 将属性 (property) 名称为 _Color 的颜色视为主色。
  • Gamma:用于 Float 或 Vector,因为:如果是普通的 Color 属性,使用线性颜色空间时,所有材质颜色属性均以 sRGB 颜色提供,但在传递到着色器时会转换为线性值,该标记会使得 Float 或 Vector 也进行颜色空间转换。

# 纹理特殊说明

# 纹理平铺和偏移

材质通常具有其纹理属性的 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 包含高度

# 纹理 HDR 参数

{TextureName}_HDR - 一个 float4 属性,其中包含有关如何根据所使用的颜色空间解码潜在 HDR(例如 RGBM 编码)纹理的信息。

# 基础示例

c
Shader "TA/NewUnlitShader"
{
	Properties
	{
		[HDR]_Color("Color",COLOR) = (1,1,0,1)
		[IntRange]_Int("It's Int",Range(0,5)) = 1
		_Float("It's Float",Float) = 1
		_Vector("It's Vector",Vector)=(1,1,1,1)
		[NoScaleOffset]_Texture2D("2D Texture",2D) = "white"{}
		[NoScaleOffset]_Texture3D("3D Texture",3D) = ""{}
		[NoScaleOffset]_TextureCube("Cube Texture",Cube) = ""{}
    }
    SubShader
    {
		Pass{}
    }
	
    Fallback "Diffuse"
    CustomEditor "EditorName"
}

# 结构

# Shader 变量

  • float:32 位浮点数,完整的 float 精度通常用于世界空间位置、纹理坐标或涉及复杂函数(如三角函数或幂 / 取幂)的标量计算。

  • half:16 位浮点数,范围为 –60000 至 +60000,精度约为 3 位小数;一般用于短矢量、方向、对象空间位置、高动态范围颜色。

  • fixed:11 位定点数,范围从 –2.0 到 +2.0,精度为 1/256;一般用于常规颜色(通常存储在常规纹理中)以及对它们执行简单运算。

  • int:32 位整型;通常用作循环计数器或数组索引。

  • float4、float4x4:复合矢量 / 矩阵类型 (half 亦同)

  • sampler2D、sampler3D、samplerCUBE:纹理使用 (亦有 sampler2D_half、sampler2D_float)
    若使用默认纹理,在移动平台纹理会被自动转换成低精度的纹理类型,如果需要半精度的或者高精度的便需要用以下方式来声明:

    sampler2D_half、
    sampler2D_float、
    sampler3D_half、
    sampler3D_float、
    samplerCUBE_halft、
    samplerCUBE_float

一般的经验法则是全部都从半精度开始(但位置和纹理坐标除外)。仅当半精度对于计算的某些部分不足时,才增加精度。

# 向顶点程序提供的顶点数据

  • POSITION 是顶点位置,通常为 float3 或 float4。
  • NORMAL 是顶点法线,通常为 float3。
  • TEXCOORD0 是第一个 UV 坐标,通常为 float2、float3 或 float4。
  • TEXCOORD1、TEXCOORD2 和 TEXCOORD3 分别是第 2、第 3 和第 4 个 UV 坐标。
  • TANGENT 是切线矢量(用于法线贴图),通常为 float4。
  • COLOR 顶点颜色,通常为 float4。
c
struct appdata_full {
    float4 vertex : POSITION;
    float4 tangent : TANGENT;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
    float4 texcoord1 : TEXCOORD1;
    float4 texcoord2 : TEXCOORD2;
    float4 texcoord3 : TEXCOORD3;
    fixed4 color : COLOR;
    UNITY_VERTEX_INPUT_INSTANCE_ID
};

若如下所示 引用 了 UnityCG.cginc,则具有四个 Unity3D 预定义的结构体:

  • appdata_base: vertex, normal, texcoord.
  • appdata_tan: vertex, tangent, normal, texcoord.
  • appdata_full: vertex, tangent, normal, texcoord, texcoord1, texcoord2, texcoord3, color.
  • appdata_img: vertex, texcoord.
c
CGPROGRAM
// ...
#include"UnityCG.cginc"
// ...
ENDCG

# 标签(SubShader Tags)

ex: Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
标签参数
Queue预定义:Background (1000)、Geometry (2000)、AlphaTest (2450)、Transparent (3000)、Overlay (4000);亦可选择直接填写数值,或类似 『Geometry+500』
RenderType使用替换的着色器进行渲染,脚本可使用函数 Camera.RenderWithShader 或 Camera.SetReplacementShader 来实现着色器替换 (ResetReplacementShader 重置,有同标签 shader 物体则替换渲染,无的物体则不再被渲染)。
DisableBatching"true" or "false" ,是否禁用批处理;or "LODFading"(当 LOD 淡化处于激活状态时禁用批处理;主要用于树)
ForceNoShadowCasting"true" or "false",该子着色器渲染的对象是否投射阴影
IgnoreProjector若值为 “True”,则使用此着色器的对象不会受到投影器 (Projector [Unity 组件]) 的影响。
PreviewType指示材质检视面板预览应如何显示材质。默认情况下,材质显示为球体,但也可以将 PreviewType 设置为 “Plane”(将显示为 2D)或 “Skybox”(将显示为天空盒)。
CanUseSpriteAtlas如果着色器用于精灵,请将 CanUseSpriteAtlas 标签设置为 “False”,这样在精灵打包到图集内时,该标签将不起作用。

# 渲染状态设置

# Cull

Cull Back | Front | Off 设置多边形剔除模式。

# ZTest

ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) 设置深度缓冲区测试模式。默认值为 LEqual(将前方或远处的对象作为现有对象绘制;隐藏其后面的对象)。

# ZWrite

ZWrite On | Off 设置深度缓冲区写入模式(默认值为 On)。

# Offset

Offset Factor, Units 设置 Z 缓冲区深度偏移。允许使用两个参数指定深度偏移:factor 和 units。Factor 相对于多边形的 X 或 Y 缩放最大 Z 斜率,而 units 缩放最小可分辨深度缓冲区值。因此可强制将一个多边形绘制在另一个多边形上,尽管它们实际上位于相同位置。例如,Offset 0, -1 将多边形拉近摄像机并忽略多边形的斜率,而 Offset -1, -1 在观察掠射角时进一步拉近多边形。

# ColorMask

ColorMask RGB | A | 0 | R、G、B、A 的任意组合 设置颜色通道写入遮罩。

# 混合(Blend)

设置 Alpha 混合、Alpha 操作和 alpha-to-coverage 模式。

# 混合运算
操作说明
Add将源和目标相加。
Sub从源减去目标。
RevSub从目标减去源。
Min使用源和目标中的较小者。
Max使用源和目标中的较大者。
# 混合系数
操作说明
One值为 1 - 让源或目标颜色通过。
Zero值为 0 - 删除源或目标值。
SrcColor此阶段的值乘以源颜色值。
SrcAlpha此阶段的值乘以源 Alpha 值。
DstColor此阶段的值乘以帧缓冲区源颜色值。
DstAlpha此阶段的值乘以帧缓冲区源 Alpha 值。
OneMinusSrcColor此阶段的值乘以(1 - 源颜色)。
OneMinusSrcAlpha此阶段的值乘以(1 - 源 Alpha)。
OneMinusDstColor此阶段的值乘以(1 - 目标颜色)。
OneMinusDstAlpha此阶段的值乘以(1 - 目标 Alpha)。
# 常用
Blend SrcAlpha OneMinusSrcAlpha // 传统透明度
Blend One OneMinusSrcAlpha // 预乘透明度
Blend One One // 加法
Blend OneMinusDstColor One // 软加法
Blend DstColor Zero // 乘法
Blend DstColor SrcColor // 2x 乘法

# 语义

  • SV_POSITION:顶点着色器输出顶点的最终裁剪空间位置
  • SV_Target:片段着色器输出语义(SV_TargetN [SV_Target1、SV_Target2 等])
  • SV_Depth:片段着色器深度输出
  • VPOS:(UNITY_VPOS_TYPE) 屏幕空间像素位置。[需求 #pragma target 3.0]
  • VFACE:正面的 VFACE 输入为正,背面的为负。[需求 #pragma target 3.0]
  • SV_VertexID:(uint) 顶点 ID [需求 #pragma target 3.5]

# 内置函数

# UnityCG.cginc

# 通用

函数说明
float4 UnityObjectToClipPos(float3 pos)将对象空间中的点变换到齐次坐标中的摄像机裁剪空间。这等效于 mul (UNITY_MATRIX_MVP, float4 (pos, 1.0)),应该在适当的位置使用
float3 UnityObjectToViewPos(float3 pos)将对象空间中的点变换到视图空间。这等效于 mul(UNITY_MATRIX_MV, float4(pos, 1.0)).xyz,应该在适当的位置使用
float3 WorldSpaceViewDir(float4 v)返回从给定对象空间顶点位置朝向摄像机的世界空间方向(未标准化)
float3 ObjSpaceViewDir(float4 v)返回从给定对象空间顶点位置朝向摄像机的对象空间方向(未标准化)
float2 ParallaxOffset(half h, half height, half3 viewDir)计算视差法线贴图的 UV 偏移
fixed Luminance(fixed3 c)将颜色转换为亮度(灰阶)
fixed3 DecodeLightmap(fixed4 color)从 Unity 光照贴图(RGBM 或 dLDR,具体取决于平台)解码颜色
float4 EncodeFloatRGBA(float v)将 [0..1) 范围浮点数编码为 RGBA 颜色,用于存储在低精度渲染目标中
float DecodeFloatRGBA(float4 enc)将 RGBA 颜色解码为浮点数
float2 EncodeFloatRG(float v)将 [0..1) 范围浮点数编码为 float2
float DecodeFloatRG(float2 enc)解码先前编码的 RG 浮点数
float2 EncodeViewNormalStereo(float3 n)将视图空间法线编码为 0 到 1 范围内的两个数字
float3 DecodeViewNormalStereo(float4 enc4)从 enc4.xy 解码视图空间法线
float4 ComputeScreenPos(float4 clipPos)计算用于执行屏幕空间贴图纹理采样的纹理坐标。输入是裁剪空间位置
float4 ComputeGrabScreenPos(float4 clipPos)计算用于 GrabPass 纹理采样的纹理坐标。输入是裁剪空间位置
float3 UnityWorldSpaceViewDir(float3 worldPos)给定世界坐标,计算视线方向向量,返回值并未归一化
float3 WorldSpaceViewDir(float4 localPos)给定物体空间坐标,计算视线方向向量,返回值并未归一化
float3 UnityObjectToWorldNormal(float3 norm)将法线从物体空间变换至世界空间

# 特定渲染下的辅助函数

仅当使用前向渲染(ForwardBase 或 ForwardAdd 通道类型)时,这些函数才有用。

函数说明
float3 WorldSpaceLightDir(float4 v)根据给定的对象空间顶点位置计算朝向光源的世界空间方向(未标准化)。
float3 ObjSpaceLightDir(float4 v)根据给定对象空间顶点位置计算朝向光源的对象空间方向(未标准化)。
float3 Shade4PointLights(...)计算四个点光源的光照,将光源数据紧密打包到矢量中。前向渲染使用它来计算每顶点光照。

仅当使用每顶点光照着色器(“Vertex” 通道类型)时,这些函数才有用。

| 函数 | 说明 |
float3 ShadeVertexLights (float4 vertex, float3 normal)| 根据给定的对象空间位置和法线计算四个每顶点光源和环境光的光照。

# 内置着色器变量

# 变换

名称说明
UNITY_MATRIX_MVP当前模型 * 视图 * 投影矩阵。
UNITY_MATRIX_MV当前模型 * 视图矩阵。
UNITY_MATRIX_V当前视图矩阵。
UNITY_MATRIX_P当前投影矩阵。
UNITY_MATRIX_VP当前视图 * 投影矩阵。
UNITY_MATRIX_T_MV模型转置 * 视图矩阵。
UNITY_MATRIX_IT_MV模型逆转置 * 视图矩阵。用于将法线从模型转换至相机空间。
unity_ObjectToWorld当前模型矩阵。
unity_WorldToObject当前世界矩阵的逆矩阵。

# 摄像机和屏幕

名称类型说明
_WorldSpaceCameraPosfloat3摄像机的世界空间位置。
_ProjectionParamsfloat4x 是 1.0(如果当前使用翻转投影矩阵进行渲染,则为 –1.0),y 是摄像机的近平面,z 是摄像机的远平面,w 是远平面的倒数。
_ScreenParamsfloat4x 是摄像机目标纹理的宽度(以像素为单位),y 是摄像机目标纹理的高度(以像素为单位),z 是 1.0 + 1.0 / 宽度,w 为 1.0 + 1.0 / 高度。
_ZBufferParamsfloat4用于线性化 Z 缓冲区值。x 是 (1 - 远 / 近),y 是 (远 / 近),z 是 (x / 远),w 是 (y / 远)。
unity_OrthoParamsfloat4x 是正交摄像机的宽度,y 是正交摄像机的高度,z 未使用,w 在摄像机为正交模式时是 1.0,而在摄像机为透视模式时是 0.0。
unity_CameraProjectionfloat4x4摄像机的投影矩阵。
unity_CameraInvProjectionfloat4x4摄像机投影矩阵的逆矩阵。
unity_CameraWorldClipPlanes[6]float4摄像机视锥体平面世界空间方程,按以下顺序:左、右、底、顶、近、远。

# 时间

名称类型说明
_Timefloat4自关卡加载以来的时间 (t/20, t, t2, t3),用于将着色器中的内容动画化。
_SinTimefloat4时间正弦:(t/8, t/4, t/2, t)。
_CosTimefloat4时间余弦:(t/8, t/4, t/2, t)。
unity_DeltaTimefloat4增量时间:(dt, 1/dt, smoothDt, 1/smoothDt)。

# 光照

前向渲染(ForwardBase 和 ForwardAdd 通道类型):

名称类型说明
_LightColor0fixed4光源颜色(在 UnityLightingCommon.cginc 中声明)。
_WorldSpaceLightPos0float4方向光:(世界空间方向,0)。其他光源:(世界空间位置,1)。
unity_WorldToLightfloat4x4世界 / 光源矩阵。用于对剪影和衰减纹理进行采样(在 AutoLight.cginc 中声明)。
unity_4LightPosX0、unity_4LightPosY0、unity_4LightPosZ0float4(仅限 ForwardBase 通道)前四个非重要点光源的世界空间位置。
unity_4LightAtten0float4(仅限 ForwardBase 通道)前四个非重要点光源的衰减因子。
unity_LightColorhalf4[4](仅限 ForwardBase 通道)前四个非重要点光源的颜色。
unity_WorldToShadowfloat4x4[4]世界 / 阴影矩阵。聚光灯的一个矩阵,方向光级联最多有四个矩阵。

# 光照贴图

名称类型说明
unity_LightmapTexture2D包含光照贴图信息。
unity_LightmapSTfloat4[8]缩放 UV 信息并转换到正确的范围以对光照贴图纹理进行采样。

# 雾效和环境光

unity_AmbientSky| fixed4| 梯度环境光照情况下的天空环境光照颜色。
unity_AmbientEquator| fixed4| 梯度环境光照情况下的赤道环境光照颜色。
unity_AmbientGround| fixed4| 梯度环境光照情况下的地面环境光照颜色。
UNITY_LIGHTMODEL_AMBIENT| fixed4| 环境光照颜色(梯度环境情况下的天空颜色)。旧版变量。
unity_FogColor| fixed4| 雾效颜色。
unity_FogParams| float4| 用于雾效计算的参数:(density /sqrt (ln (2))、density /ln (2)、–1/(end-start) 和 end/(end-start))。x 对于 Exp2 雾模式很有用;y 对于 Exp 模式很有用,z 和 w 对于 Linear 模式很有用。

# 特殊

# GrabPass

一般以使用:

GrabPass { "TextureName" } 
sampler2D TextureName

# 摄像机的深度纹理

通过声明 sampler2D _CameraDepthTexture 可直接引用;非线性值,存在 x 中,范围 [0,1]

(注:另外还有 _LastCameraDepthTexture 纹理)

可使用帮助函数:

名 | 说明
Linear01Depth (i)| 通过深度纹理 i 给出高精度值时,返回相应的线性深度,范围在 0 到 1 之间
LinearEyeDepth (i)| 通过深度纹理 i 计算,返回相应的视空间线性深度
COMPUTE_EYEDEPTH (float3 o)| 顶点函数中使用,返回当前顶点视空间深度,一般用于不会被记录深度值的透明物体自身

  • 获取当前物体当前深度:
c
vert:COMPUTE_EYEDEPTH(o.screenPos.z);// 返回的为该物体处于视空间的深度值
frag:fixed depth=LinearEyeDepth(tex2Dproj(_CameraDepthTexture,i.screenPos))// 获取该片元之前位于视空间的深度值,并将其转化为线性值

若通过 depth.x-(i.screenPos.z) 直接返回为颜色值,则会有如图结果:

地形混合贴图

注:仅 “不透明” 对象(这些对象的材质和着色器设置为使用小于等于 2500 的渲染队列)会自动被渲染到深度纹理中

# 透明物体

分为 透明度测试 (无效像素直接丢弃)、 透明度混合两类。
需要着重注意渲染顺序问题,Queue 标签对队列进行标识

若使用透明度混合,为解决透明物体渲染问题,可使用一个 Pass 开启深度测试,第二个 Pass 进行正常处理:

Tags {"Queue"="Transparent" "RenderType"="Transparent"}
Pass{
	ZWrite On
	ColorMask 0
}
Pass{
	ZWrite Off
	Cull Off
	Blend XXX XXX
	//TODO:...
}

关于此详细可参考 Dragons blog:Unity Shader: 透明效果

# UsePass

复用指定 Shader 的 Pass:

UsePass "Shader/NAME"

注:指定 Shader 的 Pass 需使用 Name "MyPassName" 命名,且在内部,所有通道名称均大写,因此 UsePass 必须引用大写名称。


注:测试环境为 Unity3D 2019.2.4f1
参考:

  • 知乎专栏
  • Unity3D 官方文档