[U3D] ShaderLab学习笔记(一)
Shader的语法基础
Shader的分类
- Standard Surface Shader
标准表面着色器,是一种基于物理的着色系统(使用了Physically Based Rendering(简称PBR)技术,即基于物理的渲染技术),以模拟现实真实的方式来模拟材质与灯光之间的关系,可以很轻易的表现出各种金属反光效果,同时此种Shader的书写逻辑也更符合人类的思维模式。
- Unlit Shader
Vertex/Fragment Shader, 也就是最基本的顶点片断着色器,不受光照影响的Shader,多用于特效、UI上的效果制作。
- Image Effect Shader
也是顶点片断着色器,只不过是针对后处理而定制的模版,后处理是什么呢?Bloom(也有人叫Glow/泛光/辉光等说法)、调色、景深、模糊等,这些基于最终整个屏幕画面而进行再处理的Shader就是后处理。
- Compute Shader
Compute Shader是运行在图形显卡上的一段程序,独立于常规渲染管线之外的,它可以直接将GPU作为并行处理器加以利用,从而使GPU不仅具有3D渲染能力,还具有其他的运算能力。
- Shader Variant Collection
Shader变体收集器,在上面创建的时候,你会发现Shader Variant Collection与以上四个是被隔开的,就是因为这个与它们不一样,它不是制作Shader的模版,而只是对Shader变体进行打包用的容器。
Shader的代码构成
整体架构
从整体来看的话,大致是这样的一个框架结构:
Shader "[path]name"
{
[Properties] { }
SubShaders { }
[FallBack] { }
[CustomEditor] { }
}
其中[]方括号表示的是可选,意思就是说在Shader中可以没有它,只要不需要的话不加也是没有问题的。
如果我们把路径名称放在Hidden下面的话,比如:
Shader “Hidden/TA/MyFirstShader”
则表示在材质面板中隐藏此Shader,你将无法通过材质下拉列表中找到它。这在做一些不需暴露的Shader时很有用处,可以使Shader下拉列表更精简整洁。
shader路径和名称, 以及代码里的变量等, 允许中文命名, 但众所周知这样的操作并不推荐
代码分区介绍
- Properties
属性
会材质球()面板中显示的贴图和一些参数什么的都是在此Properties中进行定义设置的,内容必须写在Properties后的{ }内。当然,如果你确定不需要属性的话也可以将整个Properties以及它的{}全部删除,因为它是可选项
- SubShaders
渲染管线代码部分
一个shader允许存在多个SubShader, 也就是这个分区单词有复数后缀s的原因
- FallBack
备用方案
有的时候我们写的Shader难免在一些机器上会出现不支持的问题(最终呈现的就是显示成粉红色),而这个时候我们只要添加了FallBack,并且在后面的双引号内写上了其它Shader的有效路径名称,那么在碰到不支持的硬件时这个Shader就会自动切换成FallBack内的备用方案Shader,如果FallBack内的Shader也不支持呢,那就继续从FallBack指定的这个Shader中再找FallBack.
- CustomEditor
自定义界面
也就是说我们可以通过这个功能来自由定义材质面板的显示结果,它可以改写Properties中定义的显示方式。
ShaderLab的变量
基础变量类型
-
Color
颜色
默认值:(1,1,1,1)
颜色属性是个四维分量,也就是由四个数值来组成的,每个数值代表着颜色的一个通道。四个数值依次为RGBA(红,绿,蓝,透明)。
RGB的取值是0-255(2的8次方个值域),而在Shader中被归一化为0-1间。 -
Int
整数
虽然在材质面板中我们可以随意输入数值,比如0.55,但是在Shader内部它却只能被识别为整数。
注意,此值并不是四舍五入,而是直接取整,比如1.999,结果是1 -
Float
浮点数
在Shader中Float是最基本的类型,而Int只是一种伪整型,从Shader精度上来讲并不存在整型。所以在Properties内完全可以用Float替代Int -
half
半精度浮点 -
fixed
低精度浮点 -
Vector
四维数
默认值:0,0,0,0
由四个Float组合而成的Vector,在材质面板中显示的是四个数值输入框
四个分量分别对应XYZW,也可以叫做RGBA
XYZW与RGBA同样都是四个分量组合,只是在用于颜色时我们通常用RGBA来表示,用作坐标时习惯用XYZW来表示而已,同样我们也是可以用Vector来输出颜色,只是不那么方便直观而已 -
2D
2D纹理
默认值有以下几种:
white
black
gray
bump
如果不设置默认值,即=""{},则其实与=“gray”{}相同
当设置了默认值后,Shader内部会自动调用Unity内部准备的一张小图片,white就是纯白色,black就是纯黑色,gray就是灰色图,bump就是法线图 -
3D
3D纹理
主要用在查找表或者体积数据上,默认值与2D的不同,不管如何设置都只会显示为灰色图 -
Cube
立方体纹理
Cubemap是一个由六个独立的正方形纹理组成的集合,它将多个纹理组合起来映射到一个单一纹理
基本上说CubeMap包含6个2D纹理,这每个2D纹理是一个立方体(cube)的一个面,也就是说它是一个有贴图的立方体
想像成一个方形盒子被我们拆开铺平的情景
CubeMap通常被用来作为具有反射属性物体的反射源
结构体struct
属性变量声明语法
声明属性的写法有个通用的格式:
[Attribute] _Name (“Display Name”,Type) = Default Value
[Attribute]
标记 可选标识, 允许有0到多个, 存在通用的和指定类型变量专用的标识符
Color专用标记
- [HDR] 当给颜色添加了HDR后,则在材质面板中的颜色上会显示HDR的字样。同时点击颜色弹出来的取色器面板中也会多出一条Intensity的选项(2018.3版本,2017版本是Brightness)
Float专用标记
- [Range] 很常用的一种属性标记,主要是用来将浮点数限制在一个可以通过滑动条来选择的一个区间 将此属性中原有的Float替换成Range (Min,Max)即可,Min=最小值,Max=最大值
- [PowerSlider]
编写格式: [PowerSlider (Value)] 其中Value的值我们可以自由定义,支持浮点数,值越大会导致滑条的曲度变化越大,值为1时不改变
此属性标记的主要作用,是方便用户滑杆微调属性数值 比如有个属性值是从0-1,但是很大部分情况下所用到的值都是0-0.1左右,同时需要更精细的在这区间进行微调。那么正常情况下,用户在整个滑条上想选择0-0.1之间本身就变的很难了,更不要说在这区间微调了。所以这个时候就可以利用PowerSlider来解决此问题- [IntRange] 加了它之后呢,你在材质面板上拖动时就只能生成整数了 所以说我们完全可以用Float来代替Int
注意,当添加了[IntRange]后,默认值会被自动进行处理,假如默认值你写的是0.1,则在Shader内部会自动向下取整,取值为0- [Toggle]
开关 0代表关,1代表开- [Enum]
格式:[Enum(UnityEngine.Rendering.CullMode)]
枚举 标识后该属性在用户界面可以下拉选择数值2D专用标记
- [NoScaleOffset] 在材质面板中除了显示贴图槽以外默认还会显示两组Float:
Tiling (贴图重复度)
Offset (贴图偏移值) 如需让这两组值产生作用,我们需要在Shader中添加一些代码以支持,在后续文章中会讲解。 如果我们不希望用户去调节此参数,或者为了使性能极致化,我们可以考虑把它们的代码功能移除掉,但一旦如此,材质面板中的参数将不起作用,这时我们就可以使用[NoScaleOffset]属性标记来将它们隐藏掉。- [Normal] 如果我们希望用户指定贴图时选择法线,那我们要怎么办呢,我们并不能控制用户会选择什么类型的贴图 此时我们可以通过添加[Normal],来标记此属性是用来接收法线贴图的,当用户指定了非法线的贴图时会在材质面板上进行警告提示
3D专用标记
Cube专用标记
通用属性标记
[Header] 在材质面板上进行标注,通常用作分类组别用,注意只支持英文、数字、空格以及下划线。
[HideInInspector] 在材质面板中隐藏此条属性,在不希望暴露某条属性时可以快速将其隐藏。
_Name
变量在shader代码内的名称
Display Name
在unity面板中的名称
Type
变量类型
Default Value
默认值