一.Shader
1.Shader即着色器,是一款运行在GPU上的程序。Shader有顶点Shader和片段Shader两个基本类型,顶点Shader有着可以处理、 变换,最终会渲染到屏幕上的网格物体的顶点位置的功能,但它不能生成新的顶点。 顶点Shader的输出会传递给流水线的下— 步。 几何体的网格经过硬件的栅格化后,处于流水线上的片段Shader会被执行,片段Shader会对— 个片段(预备像素)进行各种测试。 Z深度测试、Alpha比较测试,能够通过各种测试的片段,最终会被写入渲染的输出帧中,从而成为显示器屏幕上的— 个可见像素。
2.
面向GPU的编程有3种高级图像语言可供选择:微软(Direct3D)的HLSL,OpenGL的GLSL,和NVIDIA的Cg。而Unity对Shader编程语言的支持重点是Cg。对于要适应不同GPU的Shader来说,Unity使用自定义ShaderLab来组织Shader的内容,并将针对不同的平台进行编译。
3.
微软公司根据自己所开发的图形软件库DirectX系列,定义了—系列的SM(Shader Model,Shader模型),用来描述Shader的特性和能力。SM1.0对应于DirectX8.0,SM2.0对应于 DirectX9.0b,SM3.0对应于DirectX9.0c,SM4.0对应于DirectX10.0,SM5.0对应于DirectX11.0。其中,SM4.0相当于OpenGL的3.3标准,SM5.0相当于OpenGL的4.3标准。 二.ShaderLab
0.在编写ShaderLab时,如果要使用Cg语言,则这些代码必须位于CGPROGRAM和ENDCG之间。
1.一个shader中可以写多个SubShader,unity在运行时会根据运行环境选择最优的SubShader;一个SubShader中可以写多个Pass,这些Pass会依次执行。对于一个shader,我们大致分为三部分:Properties、SubShader和Pass
2.Properties
通过脚本去使用属性:
通过Cg代码去使用属性:
除了上面提到的,还可以使用half4、fixed4和half、fixed,这两种类型在空间上分别是float4、float的二分之一、四分之一,可以通过合理的使用来提高性能。
Ps:矩阵目前是不能在Properties块中定义的,我们必须首先在shader中声明它,然后通过脚本来进行读取和写入:
3.SubShader
3.1.Tags标签
使用标签告诉渲染引擎应该什么时候、怎样去渲染它们,记住下面的这些标签只能在SubShader内不能在Pass内(Pass也有其特有标签)
a.Queue:渲染队列,表示希望unity什么时候渲染自己。例如透明物体要在不透明物体之后绘制。
有5个可选值(数字越小越先渲染):
Background:对应数字1000,在所有物体之前渲染
Geometry(默认值):对应数字2000,不透明的几何体使用这个队列
AlphaTest:对应数字2450,需要进行透明度测试的几何体使用这个队列
Transparent:对应数字3000,任何进行透明度混合的物体(不写入深度缓冲)使用这个队列
Overlay:对应数字4000,任何最后渲染的使用这个队列,例如lens flares
自定义队列可以这样写(例如天空盒、透明的水在不透明体后,透明体前渲染):
b.RenderType:这个标签在替代渲染时很重要;有时候会用于制作相机的深度纹理。unity可以运行时替换符合特定RenderType的所有shader,与Camera.RenderWithShader或者Camera.SetReplacementShader配合使用。常用的内置值:
Opaque、Transparent、TransparentCutout、Background和Overlay
c.IgnoreProjector:当值为True时,表示当前物体忽略投影的影响,对于渲染半透明物体很有用。
d.可以添加自定义标签:
其他:
a.GrabPass{ }:捕捉屏幕的内容,可供后面的Pass使用
b.UsePass "Shader/Name":可以使用其他shader的Pass
4.Pass
4.1.Tags标签
使用标签告诉渲染引擎应该什么时候、怎样去渲染它们,记住下面的这些标签只能在Pass内不能在SubShader内(SubShader也有其特有标签)
a.LightMode,需要跟灯光交互时使用
渲染路径:
unity支持3种Rendering Path,分别是VertexLit、Forward和Deferred Lighting,为此又定义了在Pass中使用的LightMode标签Vertex、ForwardBase、ForwardAdd、PrepassBase、PrepassFinal等,分别表示当前Pass是为在哪一个RenderingPath下设计使用的。
渲染优先级:Deferred > Forward > VertexLit
unity在Deferred渲染路径下,会寻找在Deferred渲染模式下的Pass然后返回,并不会执行其他渲染路径下的Pass,但是如果找不到Deferred状态下的Pass,
则会寻找Forward,如此类推。在同一时间只会执行一个渲染路径下的Pass,渲染路径在相机组件可以进行设置。
4.2.Name(由于unity的原因,命名时必须使用大写)
一般用来引用此Pass。这种引用意味着你可以定义一个Pass块,然后在其他Shader的Pass块中多次引用它。
4.3 Culling & Depth Testing
Cull:控制多边形的那一面会被剔除(不绘制)。可取的值:
Back(默认值):不绘制后面
Front:不绘制前面 Off:禁用剔除,所有面都会被绘制
ZWrite:控制像素是否写到深度缓冲。可取的值:
On(默认值):如果要绘制不透明的物体,选择On Off:如果要绘制半透明的物体,选择Off
ZTest:控制深度测试如何进行。可取的值:
Less、Greater、LEqual(默认值)、GEqual、Equal、NotEqual、Always
以默认值为例,即表示如果该点的深度小于等于深度缓存区的对应深度,则更新颜色缓存区(帧缓存区)的值,即起到覆盖的效果。
(离摄像机越远,深度越大)
Offset
4.4 Blending
Src(源):指生成的颜色 Dst(目标):已经在屏幕的颜色
语句:
Blend Off(默认值):关掉Blending。
Blend SrcFactor DstFactor:输出的颜色乘上SrcFactor,已经在屏幕上的颜色乘上DstFactor,然后两者相加。
Blend SrcFactor DstFactor, SrcFactorA DstFactorA:同上面的类似,但使用SrcFactorA DstFactorA去混合alpha。
BlendOp BlendOp:默认是相加的操作,通过该语句可以定义其他操作。
BlendOp OpColor, OpAlpha: 同上面的类似,但可以为color(rgb)和alpha(a)定义其他操作
AlphaToMask On:Turns on alpha-to-coverage. When MSAA is used, alpha to coverage modifies multisample coverage mask proportionally to the pixel shader result alpha value. This is typically used for less aliased outlines than regular alpha-test; useful for vegetation and other alpha tested shaders.
操作符(主要的):
Add: 源 + 目标 Sub: 源 - 目标
RevSub: 目标 - 源
Min: 取最小值 Max: 取最大值
因子(factor):
常用的几个语句:
Alpha Blending,Alpha Testing,Alpha To Coverage
Alpha Blending:
// inside SubShader
Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
// inside Pass
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Alpha Testing / Cutout:
// inside SubShader
Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" "IgnoreProjector"="True" }
// inside CGPROGRAM in the fragment shader:
clip(textureColor.a - alphaCutoffValue);
Alpha To Coverage:
// inside SubShader
Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" "IgnoreProjector"="True" }
// inside Pass
AlphaToMask On
FallBack "Diffuse" //如果以上SubShader渲染失败则回滚采用Diffuse