简要整理了部分常用的UnityShader案例,并编写了相关的代码以供以后编写新shader时作为参考
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

533 lines
16 KiB

# 前言
本编程指南仅尽可能的列出编写一个shader的参考
#
# shader编写结构
## 1.定义Properties(方便在创建材质的时候可以传入贴图等数据)
## 2.编写SubShader主题
## 2.1【Tags】
## 2.2【RenderSetUp】
### 2.2.1【LOD】渲染深度(详情参考Unity LOD 远景渲染部分)
## 2.3【GrabPass】【UsePass】【Pass】【Pass】(第二个或者其他)
----------------------案例Pass--------------------
【RenderSetUp】
CGPROGRAM
//编译顶点着色器
#pragma vertex vert
//编译片元着色器
#pragma fragment frag
### 2.3.1 其他引用以及其它编译指令
### 2.3.2 声明参数
### 2.3.3 设置应用数据->顶点着色器结构体a2v,appdata(a2v为app to vert简写)
### 2.3.4 设置顶点->片源着色器结构体v2f(v2f为vert to fragment简写)
### 2.3.5 编写顶点着色器渲染方法
v2f vert (a2v v){
v2f o;
//着色器内容
return o;
}
### 2.3.5 编写片源着色器渲染方法
fixed4 frag (v2f i) : SV_Target{
fixed4 tex = ...;
//着色器内容
return tex;
}
ENDCG
---------------------------------------------------
## 3.设置Fallback,如果显卡无法运行上面的SubShader,则执行FallBack预设进行渲染
# 1.Properties(参考书籍P30)
--------------------------------------------------------------------------
### 传入数据常用类型
## Int
_Int("Int",Int)=2
## Float
_Float("Float",Float)=1.0
## Range
_Range("Range",Range(0.0,5.0))=1.0
## Color
_Color("Color",Color)=(1,1,1,1)
## Vector
_Vector("Vector",Vector)=(1,1,1,1)
## 2D
_MainTex ("Texture", 2D) = "white" {}
ps:内置纹理名称包含white、black、gray、bump等等
## Cube
_Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}
## 3D
_3D ("3D", 3D) = "black" {}
--------------------------------------------------------------------------
# 2.Tags(参考网站:https://gameinstitute.qq.com/community/detail/121997)
--------------------------------------------------------------------------
### 渲染类型声明(包含渲染顺序)
Tags的书写方法为键值对,可多可少,不需要全部声明,未声明时按默认值
Tags { "RenderType"="Opaque" "Queue"="Transparent" }
# 2.1(SubShader)Tags
## key:Queue
渲染顺序,括号内为优先度,值越小越先被渲染
## value
Background(1000)
Geometry(2000)【默认】
AlphaTest(2450)
Transparent(3000)
Overlay(4000)
可以自定义值例如"Queue"="3100"
## key:RenderType
渲染类型
## value
Opaque-----------------不透明(法线、自发光、反射、地形Shader)
Transparent------------半透明(透明、粒子、字体、地形添加通道Shader)
TransparentCutout------遮罩透明(透明裁切、双通道植物Shader)
Background-------------天空盒Shader
Overlay----------------GUI纹理、光晕、闪光Shader
TreeOpaque-------------地形引擎——树皮
TreeTransparentCutout--地形引擎——树叶
TreeBillboard----------地形引擎——公告牌(始终面向摄像机)式树木
Grass------------------地形引擎——草
GrassBillboard---------地形引擎——公告牌(始终面向摄像机)式草
## key:DisableBatching
是否禁用Batch(打包、合并)
## value
True-------------------禁用
False------------------不禁用(默认)
LODFading--------------当LOD fade开启的时候禁用,一般用在树木上面
## key:ForceNoShadowCasting
是否强制不投射阴影,当这个值为True的时候,使用这个Shader的对象便不会投射阴影。
## key:IgnoreProjector
无视投影器,当这个值为True的时候,对象便不受投射器影响。
## key:CanUseSpriteAtlas
可使用精灵集,当这个值为False的时候,不能使用精灵集。
## key:PreviewType
材质的预览形式,默认显示为球体,可以使用Plane(2D平面)或Skybox(天空盒)
# 2.2(Pass)Tags
## key:LightMode
光照模式
## value
Always------------------总是渲染,不使用光照
ForwardBase-------------用于前向渲染,使用环境光、主平行光、顶点/SH(球谐函数)光照以及光照贴图
ForwardAdd--------------用于前向渲染,额外使用每像素光,每个光照一个通道
Deferred----------------用于延迟着色,渲染G-Buffer
ShadowCaster------------渲染对象的深度到阴影贴图或者深度纹理
PrepassBase-------------用于(旧版)延迟光照,渲染法线和高光指数
PrepassFinal------------用于(旧版)延迟光照,合并贴图、光照和自发光来渲染最终色彩
Vertex------------------当对象不受光照贴图影响的时候,用来渲染(旧版)顶点发光。使用所有的顶点光照
VertexLMRGBM------------当对象接受光照贴图影响的时候,用来渲染(旧版)顶点发光。适用于使用RGBM编码光照贴图的平台(PC&主机)
VertexLM----------------当对象接受光照贴图影响的时候,用来渲染(旧版)顶点发光。适用于使用double-LDR编码光照贴图的平台(移动平台)
## key:PassFlags
标志渲染管线如何传递数据给通道
## value
OnlyDirectional---------只有主平行光、环境光和光照探测器的数据会传递给通道。仅用于LightMode为ForwardBase
## key:RequireOptions
标志通道至于在某些外部条件满足时才会被渲染
SoftVegetation----------当Quality Setting中的Soft Vegetation选项被开启时,才会渲染通道
# 3.RenderSetUp(以下写在CGPROGRAM之前)(参考书籍P31)
--------------------------------------------------------------------------
## 3.1 Cull
Cull Back | Front | Off
设置剔除模式:剔除背面/正面/关闭剔除
## 3.2 ZTest
ZTest Less Greater | LEqual | GEqual | Equal | NotEqual | Always
设置深度测试时使用的函数
## 3.3 ZWrite
ZWrite On | Off
开启/关闭深度写入
## 3.4 Blend
BlendOp (Op)
设置混合操作
Blend (SrcFactor) (DstFactor)
Blend (SrcFactor) (DstFactor),(SrcFactorA) (DstFactorA)
开启并设置混合模式(透明材质用)
例如:Blend SrcAlpha OneMinusSrcAlpha
其中SrcFactor为源颜色乘以的混合因子
DstFactor为目标颜色乘以的混合因子
两者相加存入颜色缓冲区
Blend混合操作表(参考书籍P174)
-----------------------------------------
Add | 源颜色和目标颜色相加
Sub | 源颜色减去目标颜色
RevSub | 目标颜色减去源颜色
Min | 使用目标颜色跟源颜色中较小的值
Max | 使用源颜色跟目标颜色中较大的值
Blend混合因子表(参考书籍P174)
-----------------------------------------
One | 1
Zero | 0
SrcColor | 源颜色值
SrcAlpha | 源颜色的透明度值
DstColor | 目标颜色值
DstAlpha | 目标颜色的透明度值
OneMinusSrcColor | 1-源颜色值
OneMinusSrcAlpha | 1-源颜色的透明值
OneMinusDstColor | 1-目标颜色值
OneMinusDstAlpha | 1-目标颜色的透明度值
常用混合类型
-----------------------------------------
正常--------| Blend SrcAlpha OneMinusSrcAlpha
柔向相加----| Blend OneMinusDstColor One
正片叠底----| Blend DstColor Zero
两倍相乘----| Blend DstColor SrcColor
变暗--------| BlendOp Min
------------| Blend One One
变亮--------| BlendOp Max
------------| Blend One One
滤色--------| Blend OneMinusDstColor One
线性减淡----| Blend One One
# 4.Pass
--------------------------------------------------------------------------
渲染所使用的通道,可以使用抓取屏幕图像的Pass--GrabPass
以及引用其他shader的Pass--UsePass
以及自己编写的Pass
# 5.vert & frag
--------------------------------------------------------------------------
顶点着色器,编写案例如下
需要前置结构体a2v
输出结构体v2f
(应用->顶点坐标->顶点着色器->输出顶点)
v2f vert (a2v v){
v2f o;
//着色器内容
return o;
}
需要前置结构体v2f
输出着色器颜色值fixed4
(顶点->片元着色器->输出颜色)
fixed4 frag (v2f i) : SV_Target{
fixed4 tex = ...;
//着色器内容
return tex;
}
## 5.0 结构体语义(参考书籍P110)
### a2v------从应用阶段传递模型数据给顶点着色器
| 语义 | 描述 | 类型 |
| ----------- | ------------------------------------------ | ------------- |
| POSITION | 模型空间的顶点位置 | float4 |
| NORMAL | 顶点法线 | float3 |
| TANGENT | 顶点切线 | float3 |
| TEXCOORD0-7 | 该顶点的纹理坐标,可以定义TEXCOORD0,TEXCOORD1表示第一组或者第二组 | float2&float4 |
| COLOR | 顶点颜色 | fixed4&float4 |
### v2f------从顶点着色器传递数据给片元着色器
| 语义 | 描述 | 类型 |
| ----------- | ----------------- | ------ |
| SV_POSITION | 裁剪空间中的顶点坐标 | float4 |
| COLOR0 | 通常用于输出第一组顶点颜色,非必需 | fixed4 |
| COLOR1 | 通常用于输出第二组顶点颜色,非必需 | fixed4 |
| TEXCOORD0-7 | 用于输出纹理坐标0-7 | 任意 |
### SV_Target------片元着色器输出时用的语义
输出值将会存储到渲染目标(Render Target)中。
### VPOS/WPOS------片元着色器传递屏幕坐标的语义
类型为float4,xy为屏幕空间中的坐标,z为近裁剪平面处于远裁剪平面处的分量,范围0-1。对于w,如果摄像机投影类型为正交投影,w恒为1,如果使用透视投影,w的取值范围为[1/Near,1/Far],Near为近裁剪平面处于摄像机的距离,Far为远裁剪平面处于摄像机的距离。
## 5.1 变换矩阵(参考书籍P87)
-----------------------------------------
### UNITY_MATRIX_MVP(取模现在被UnityObjectToClipPos(v.vertex)所替代)
当前模型的观察投影矩阵,顶点/方向矢量 模型空间->裁剪空间
### UNITY_MATRIX_MV
当前的模型观察矩阵,顶点/方向矢量 模型空间->观察空间
### UNITY_MATRIX_V
当前的观察矩阵,顶点/方向矢量 世界空间->观察空间
### UNITY_MATRIX_P
当前的投影矩阵,顶点/方向矢量 观察空间->裁剪空间
### UNITY_MATRIX_VP
当前的观察投影矩阵,顶点/方向矢量 世界空间->裁剪空间
### UNITY_MATRIX_T_MV
UNITY_MATRIX_MV的转置矩阵
### UNITY_MATRIX_IT_MV
UNITY_MATRIX_MV的逆转置矩阵,用于将发现从模型空间变换到观察空间,也可用于得到
UNITY_MATRIX_MV的逆矩阵
### unity_ObjectToWorld(原为_Object2World)
当前的模型矩阵,用于将顶点/方向矢量从模型空间变换到世界空间
### unity_WorldToObject(原为_World2Object)
unity_ObjectToWorld的逆矩阵,用于将顶点/方向矢量从世界空间变换到模型空间
## 5.2 Unity内置的摄像机和屏幕参数(参考书籍P88)
-------------------------------------------------
### 【float3】 _WorldSpaceCameraPos
该摄像机在世界空间中的位置
### 【float4】 _ProjectionParams
x = 1.0 & -1.0 | y = Near | z = Far | w = 1.0 + 1.0 / Far
Near = 近裁剪平面到摄像机的距离
Far = 远裁剪平面到摄像机的距离
### 【float4】 _ScreenParams
x = width | y = height | z = 1.0 + 1.0 / width | w = 1.0 + 1.0 / height
width = 该摄像机的渲染目标的像素宽度
height = 该摄像机的渲染目标的像素高度
### 【float4】 _ZBufferParams
x = 1 - Far / Near | y = Far / Near | z = x / Far | w = y / Far
该变量用于线性化Z缓存中的深度值
### 【float4】unity_OrthoParams
x = width | y = height | z = 无定义 | w = 1.0(该摄像机为正交摄像机) & 0.0(该摄像机为透视摄像机)
width = 正交投影摄像机的宽度
height = 正交投影摄像机的高度
### 【float4x4】unity_CameraProjection
该摄像机的投影矩阵
### 【float4x4】unity_CameraInvProjection
该摄像机的投影矩阵的逆矩阵
### 【float4[6]】unity_CameraWorldClipPlanes[6]
该摄像机的6个裁剪平面在世界空间下的等式
按如下顺序:左、右、上、下、近、远裁剪平面
## 5.3 UnityCG.cginc常用的帮助函数(参考书籍P137)
-------------------------------------------------
### 【float3】 WorldSpaceViewDir(float4 v)
输入:模型空间中的顶点位置
返回:世界空间红从该点到摄像机的观察方向。
ps:内部实现使用了UnityWorldSpaceViewDir函数
### 【float3】 UnityWorldSpaceViewDir(float4 v)
输入:世界空间中的顶点位置
返回:世界空间中从该点到摄像机的观察方向。
### 【float3】 ObjectSpaceViewDir(float4 v)
输入:一个模型空间中的顶点位置
返回:模型空间中该点到摄像机的观察方向。
### 【float3】 WorldSpaceLightDir(float4 v)【仅用于前向渲染】【未被归一化】
输入:一个模型空间中的顶点位置
返回:世界空间中从该点到光源的光照方向。
ps:内部实现使用了UnityWorldSpaceLightDir函数
### 【float3】 UnityWorldSpaceLightDir(float4 v)【仅用于前向渲染】【未被归一化】
输入:世界空间中的顶点位置
返回:世界空间中该点到光源的光照方向
### 【float3】 ObjSpaceLightDir(float4 v)【仅用于前向渲染】【未被归一化】
输入:一个模型空间中的顶点位置
返回:模型空间中从该点到光源的光照方向
### 【float3】 UnityObjectToWorldNormal(float3 normal)
把法线方向从模型空间转换到世界空间中
### 【float3】 UnityObjectToWorldDir(float3 dir)
把方向矢量从模型空间变换到世界空间中
### 【float3】 UnityWorldToObjectDir(float3 dir)
把方向矢量从世界空间变换到模型空间中
# 6.关于光照
## 6.1 Unity渲染路径
------------------------------------------------------------
在tag-LightMode里设置,详情见本文2.2
## 6.2 Unity内置光照变量和函数
------------------------------------------------------------
### 【float4】 _LightColor0
该Pass处理的逐像素光源的颜色
### 【float4】 _WorldSpaceLightPos0
该Pass处理的逐像素光源的位置。
如果该光源是平行光,_WorldSpaceLightPos0.w=0
如果是其他类型光,_WorldSpaceLightPos0.w=1
### 【float4x4】 _LightMatrix0
从世界空间到光源空间的变换矩阵。可以用于采样cookie和光照衰减纹理
### 【float4】 unity_4LightPosX0 unity_4LightPosY0 unity_4LightPosZ0
仅用于BasePass
前四个非重要的点光源在世界空间中的位置
### 【float4】 unity_4LightPosX0 unity_4LightPosY0 unity_4LightPosZ0
仅用于BasePass
前四个非重要的点光源在世界空间中的位置
### 【float4】 unity_4LightAtten0
仅用于BasePass
前四个非重要的点光源的衰减因子
### 【half4[4]】 unity_LightColor
仅用于BasePass
前四个非重要的点光源的颜色
## 6.3 Unity前向渲染可以使用的内置光照参数
------------------------------------------------------------
以下函数仅用于前向渲染才可使用。
### 【float3】 WorldSpaceLightDir(float4 v)【未被归一化】
输入:一个模型空间中的顶点位置
返回:世界空间中从该点到光源的光照方向。
ps:内部实现使用了UnityWorldSpaceLightDir函数
### 【float3】 UnityWorldSpaceLightDir(float4 v)【未被归一化】
输入:一个世界空间中的顶点位置
返回:世界空间中从该点到光源的光照方向。
### 【float3】 ObjSpaceLightDir(float4 v)【未被归一化】
输入:一个模型空间中的顶点位置
返回:模型空间中从该点到光源的光照方向。
### 【float3】 Shade4PointLights(...)
输入:已经打包进矢量的光照数据,参考6.2
返回:计算逐顶点光照。