简要整理了部分常用的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.
 

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 返回:计算逐顶点光照。