前言
Unity有自己的一套Shader系统,叫ShaderLab,今天主要说一下ShaderLab的语法和Unity中的几种不同种类的Shader的区别及使用场景,并分别做一些例子说明。
什么是ShaderLab
ShaderLab 是Unity3d自己封装的一个调用CG/HLSL/GLSL的接口,如果熟悉CG/HLSL/GLSL中的一种,理解起来会比较容易一些。
ShaderLab语法
首先,看一下ShaderLab的基本结构如下:
Shader "MyShader"{
Properties{
_MyTexture("My Texture",2D) = "white"{}
//other properties like colors or vectors go here as well
}
SubShader{
//here goes the 'meat' of your
//- sureface shader or
//- vertex and program shader or
//- fixed function shader
}
SubShader{
//here goes a simpler version of the SubShader
//above than can run on older graphics cards
}
}
上面代码可以看到,ShaderLab主要由Shader名字,属性和SubShader组成。
抽象语法可以表示成:
Shader "name" {[Properties] Subshaders [Fallback] [CustomEditor]}
Shader “name”{}:
Shader关键字加Shader名称,类似声明类class name{},Shader的名字一般是”xx/xx”,类似命名空间,这样可以避免重名。
Properties
ShaderLab的属性并不是必须的,属性主要用于暴露一些参数显示到材质(Material)球上,可以方便的调整效果,而不必每次都改代码。
属性的格式及支持的类型如下:
- 数字和范围滑条
name(“display name”,Range(min,max))=number
name(“display name”,Float) = number
name(“display name”,Int) = number
- 颜色和向量
name(“display name”,Color) = (number,number,number,number)
name(“display name”,Vector) = (number,number,number,number)
- 贴图
name(“display name”,2D) = “defaulttexture”{}
name(“display name”,Cube)= “defaulttexture”{}
name(“display name”,3D) = “defaulttexture”{}
其中name是属性的名字,在SubShader中会用到,display name是显示在material的inspector中,后面的类型定义,即是类型的修饰,又会在inspector中显示不同的控件(如Range显示滑条,Color显示颜色选择框等),赋值语句之后是默认值。
SubShader
在Unity中每个Shader都由一个或多个subshader组成。语法格式如下:
Subshader{[Tags][CommonState]Passdef[Passdef ..]}
- Tags:主要作用是告诉渲染引擎什么时候渲染和怎么样渲染
具体语法为:Tags{"TagName1" = "Value1" "TabName2"="Value2"}
1. Queue tag: Queue标签决定对象的渲染顺序。有Background(1000),Geometry(2000),AlphaTest(2450),Transparent(3000),Overlay(4000)等预定义的渲染顺序,也可以自己定义(其实就是数值,数值越大,渲染越靠后)
2. RenderType tag:RenderType tag将shader分类到几个预先定义的组,如不透明shader,alpha test shader等,一般用于Shader替换或产生相机深度纹理.稍后再详细解释。
3. DisableBatching Tag:这个标签主要用于禁用Batching,因为当Draw Call Batching后,所有对象都变换到了世界空间,而失去了模型空间信息,有”True”(禁用),”False”(不禁用,默认是这个),”LODFading”(当LOD fading激活,禁用,主要用于树)
4. ForceNoShadowCasting tag:如果为”True”,则使用此subshader渲染将不接收阴影,当在透明对象上使用shader replacement时可以避免从其它的subshader继承阴影。
5. IgnoreProjector Tag:如果为”True”,则物体不受投影影响,主要用于半透明的物体。
6. CanUseSpriteAtlasTag:如果为”False”,则sprite atlas不能使用。
7. PreviewType tag:主要影响material在inspector的显示,默认为球形,可以设置成”Plane”或”Skybox”
- CommonState:主要是设置硬件开关的各种状态。根据渲染管线,设置硬件状态,对渲染的各阶段进行控制。
1. Color,Material,Lighting:
Color color
Material {Material Block}
Lighting On|Off
SeparateSpecular On|Off
ColorMaterial AmbientAndDiffuse|Emission
2. Culling&Depth Testing:
Cull Back|Front|Off
ZWrite On|Off
ZTest Less|Greater|LEqual|GEqual|Equal|NotEqual|Always
3. Texture Combiners:
SetTexture[TextureName]{Texture Block}
SetTexture[_MainTex]{Combine
previous*texture,previous+texture}
4. Fog:
Fog {Fog Commands}
Mode Off|Global|Linear|Exp|Exp2
Color ColorValue
Density FloatValue
Range FloatValue,FloatValue
5. Alpha testing:
AlphaTest Off
AlphaTest comparison AlphaValue
6. Blending:
Blend SrcAlpha OneMinusSrcAlpha //Alpha blending
Blend One One //Additive
Blend OneMinusDstColor One//Soft Additive
Blend DstColor Zero//Multiplicative
Blend DstColor SrcColor//2x Multiplicative
- Passdef:定义渲染通道,一个subShader可以有多个pass,由于pass会产生drawcall, 一般都会用一个pass,但有一些效果可能需要多个pass配合实现。分为regular Pass,Use Pass,和Grab Pass
1. Regular Pass:语法
Pass{[Name and Tags][RenderSetup]}
Name就是指定Pass的名字 Tags和SubShader的Tags
RenderSetup是设置显卡状态
2. UsePass:引用其它Shader中的Pass名字
UsePass "Shader/Name"
3. GrabPass:抓取当前屏幕内容绘制到texture中,用于其它的pass,GrabPass{}或GrabPass{"TextureName"}
Fallback
如果没有subShader可以在当前显卡运行,则尝试调用其它shader
Fallback "name"或Fallback Off
CustomEditor
CustomEditor "name"
定义CustomEditor后,Unity会去找类名是CustomeEditor指定的,并继承ShaderGUI的类。如Unity自带的 Standard.shader 就是用了CustomEditor
Shader的三种写法
Unity中Shader分为surface shaders,vertex and fragment shaders或fxied function shaders
- Surface Shader:表面着色器,Unity中推荐使用的一种写法,Unity默认创建的就是Surface Shader,Surface Shader自身会编译为多个通道,不能添加Pass通道。如果需要受到光线和阴影影响,Surface Shader是最好的选择。如果不需对光线处理,不要用这个,因为会生成更多的代码。有点大材小用的感觉。
例子:
Shader "Example/Diffuse Texture"{
Properties{
_MainTex("Texture",2D) = "white"{}
}
SubShader{
Tags{"RenderType" = "Opaque"}
CGPROGRAM
#pragma surface surf Lambert
struct Input{
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf(Input IN,inout SurfaceOutput o){
o.Albedo = tex2D(_MainTex,IN.uv_MainTex).rgb;
}
ENDCG
}
}
- vertex and fragment shader:顶点和片段着色器,功能最强大,最自由的形态,自己编写的代码会多,在Pass里放CGPROGRAM和ENDCG块。
例子:
Shader "Custom/Simple"{
Properties{
_Color("BaseColor",Color) = (1,1,1,1)
_MainTex("Base(RGB)",2D) = "white"{}
}
SubShader{
tags{"Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}
Blend SrcAlpha OneMinusSrcAlpha
Pass{
Name "Simple"
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 _Color;
sampler2D _MainTex;
struct v2f{
float4 post:POSITION;
float4 uv:TEXCOORD0;
};
v2f vert(appdata_base v){
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv = v.texcoord;
return o;
}
half4 frag(v2f i):COLOR{
float2 uv = i.uv.xy;
half4 = tex2D(_MainTex.uv)*_Color;
return c;
}
ENDCG
}
}
}
- fixed function shader:固定功能着色器,写法简单,功能少,Unity官方不建议用这个写法。除非是用于比较古老的硬件,其它Shader功能不支持时才考虑用fixed function.例子:
Shader "ShaderLab/TestShader"{
Properties{
_Color("My Color",Color)= (.34,.85,.92,1)
}
SubShader{
Pass{
Material{
Diffuse[_Color]
Ambient[_Color]
}
Lighting On
}
}
}
Shader相关文件(扩展名):
- shader: 着色器的主要文件
- cg/cginc: 着色器的公用文件,可以在cg/shader/cginc文件中被”include”(包含),一般用来写全局方法和全局变量,方便多个shader文件调用。
ShaderLab的一些疑问补充
- 多个Subshader的情况下,会按顺序优先选择当前第一个可用的Shader.如果都不能用就执行FallBack(如果指定的话)
- Subshader中的pass是按顺序依次执行的。多个pass会导致多次drawcall.
- CG块中包含的是CG语言,是编写逻辑和效果的地方,CG块可以在SubShader内,也可以在Pass内。当多个Pass的CG块相同则可以提到Subshader中,或surface Shader中CG块也是在SubShader中。
Category:Category解决了当多个SubShader中Tags或Common State相同时,可以提取这些到Category中,例子:
Shader "Custom/Test"{ Properties{ _Color("Main Color",Color) = (1,1,1,1) } Category{ Tags{"Queue" = "Transparent"} ZWrite Off Blend SrcAlpha OneMinusSrcAlpha SubShader{ ... } SubShader{ ... } } }总结
本文主要大概总结了一下Unity中的ShaderLab语法,ShaderLab其实主要是提供了一个统一的框架,具体实现主要是用CG语言来写,关于CG语言,以后会写一篇专门针对CG语言的文章
本文介绍了Unity的ShaderLab系统,讲解了ShaderLab的基本结构、属性、SubShader以及三种Shader写法。ShaderLab用于调用CG/HLSL/GLSL接口,通过Properties暴露参数到材质球。SubShader由多个Pass组成,按顺序执行。Unity推荐使用Surface Shader,但更自由的Vertex and Fragment Shader在需要更多定制时更为适用。
2566

被折叠的 条评论
为什么被折叠?



