Unity Shader 学习笔记(3)Unity Shader模板、结构、形式
参考书籍:《Unity Shader 入门精要》
【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质
【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 & 纹理混合
Unity Sahder的模板
模板名 | 功能 |
---|---|
Standard Surface Shader | 包含标准光照模型的表面着色器模板。 |
Unlit Shader | 产生一个不包含光照(但包含雾效)的基本的顶点/片元着色器。 |
ImageEffect Shader | 实现各种屏幕后处理效果的基本模版。 |
Compute Shader | 特殊的Shader,利用GPU的并行性来进行一些与常规渲染流水线无关的计算。 |
标准着色器模板信息
标签名 | 功能 |
---|---|
Default Maps | 默认纹理。 |
Surface shader | 点击‘Show generated code’,可以看到Unity在背后为表明着色器生成的顶点/片元着色器)。 |
Fixed function | 固定函数着色器(用于旧设备)。如果使用了同样会有一个按钮,用来查看生成的顶点/片元着色器。 |
Compiled code | 选择不同图像编程接口,编译成对应Shader代码。可以查看生成的底层汇编指令。 |
Cast shadows | 是否捕获阴影。 |
Render queue | 渲染队列优先级。 |
LOD | Level of Detail,着色器的细节层次效果。 |
Ignore projector | 是否忽视投影(常用于半透明物体)。 |
Disable batching | 是否不使用批处理。 |
Properties | 属性列表。 |
Unity Sahder的结构
// 着色器名称
Shader "ShaderName" {
// 属性
Properties {
Name ("display name", PrpertyType) = DefaultValue
}
// 子着色器
SubShader {
// 可选的,标签(告诉Unity如何、何时渲染对象)k
[Tags]
// 可选的,状态设置(开关混合、深度测试,剔除模式,设置深度测试使用函数)
[RenderSetup]
// 完整渲染流程
Pass {
[Name]
[Tags]
[RanderSetup]
}
}
//SubShader不能运行时执行(同时渲染阴影)
Fallback "VertexLit"
}
Properties
属性。不一定要在Properties语义块中声明,也可以在Cg中定义变量(可通过脚本向Shader传递)。
作用:只是为了让这些属性显示在材质面板中。
定义:Name ("display name", PrpertyType) = DefaultValue
- Name:名字。在Shader中访问该变量时,要声明这个名字。
- display name:显示的名字。即面板显示的标签名字。
- PropertyType:属性类型。
- DefaultValue:默认值。
样例
Properties {
// Numbers and Sliders
_Int ("Int", Int) = 2
_Float ("Float", Float) = 1.5
_Range("Range", Range(0.0, 5.0)) = 3.0
// Colors and Vectors
_Color ("Color", Color) = (1,1,1,1)
_Vector ("Vector", Vector) = (2, 3, 6, 1)
// Textures
_2D ("2D", 2D) = "" {}
_Cube ("Cube", Cube) = "white" {}
_3D ("3D", 3D) = "black" {}
}
SubShader
子着色器。每一个Unity Shader文件可以包含多个SubShader语义块,但最少要有一个。Unity会扫描所有SubShader语义块,然后选择第一个能够在目标平台上运行的,如果都不支持,则会使用Fallback指定的Shader。
定义:
- Tags:标签,可选。
- RenderSetup:状态,可选。
- Pass:一次完整的渲染流程。可以在里面声明标签和状态。
状态设置(RenderSetup)
设置显卡的各种状态。如果需要应用到所有Pass块中,则在SubShader中设置。否则如双面渲染,第一个Pass剔除正面(Cull Front)来渲染背面,第二个Pass剔除背面(Cull Back)来渲染正面。
标签(Tags)
是键值对,都为字符串类型。用于告诉Unity:SubShader要怎么样以及合适渲染这个对象。
结构:Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
注意:下面这些标签都只可以在SubShafer中声明,不可以在Pass块中声明。
Pass语义块
Pass {
[Name] // 如 Name "MyPassName"
[Tags]
[RenderSetup]
// Other code
}
- Name:名称。
- RenderSetup:同SubShader,还可以使用固定管线的着色器命令。
- Tags:不同与Subshader的标签。
Pass块中的Tags
其他标签:
- UsePass:直接使用别的Shader的Pass块。在使用时必须使用大写形式如:
UsePass "MyShader/MYPASSNAME"
。 - GrabPass:抓取屏幕,并将结果存储到一张纹理中,用于后序的Pass处理。
Fallback
如果以上的SubShader都不能用,就用这个最低级的Shader(Fallback "name"
),或者直接丢弃(Fallback Off
)。还会影响阴影的投射,内置Shader包含一个通用的Pass来处理。
Unity Sahder的形式
表面着色器(Surface Shader)
这是Unity自己创造的一种着色器代码类型,在背后会转换成对应的顶点/片元着色器,相当于再对顶点/片元着色器的抽象。定义在CGPROGRAM
和ENDCG
之间,而不是在Pass中。
#pragma surface surf Lambert // 使用surf函数作为表面着色器,用Lambert光照模型
struct Input {
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o){
o.Albedo = 1;
}
顶点/片元着色器(Vertex/Fragment Shader)
相比表面着色器更复杂,但更灵活。可以控制渲染的实现细节。同样定义在CGPROGRAM
和ENDCG
之间。
#pragma vertex vert // 使用vert函数作为顶点着色器
#pragma fragment frag // 使用frag函数作为片元着色器
固定函数着色器(Fixed Function Shader)
以上两种都是可编程管线,而对于一些旧设备,就不支持了,这时就要用固定函数着色器完成渲染,也只能完成一些简单的效果。定义在Pass块中。
Pass {
Material {
Diffuse [_Color]
}
Lighting On
}