Shader 的中文意思是着色器,是给模型上色的一个工具
在 Unity 中往往需要配合使用材质和 Unity Shader 才能达到理想的效果
常见的流程:
创建一个新的材质
创建一个 Unity Shader,并把它赋所创建的材质
把这个关联了 Shader 的材质赋给需要渲染的游戏对象
在材质面板中调整 Unity Shader 的属性,以得到满意的效果
Shader 是什么
Shader 其实就是专门用来渲染图形的一种技术
通过 Shader,我们可以自定义显卡渲染画面的算法
小到每一个像素点,大到整个屏幕,从而让画面达到我们想要的效果
比如下面这两个游戏中比较常见的效果:
Shader 分为两类:
-
顶点 Shader:3D图形都是由一个个三角面片组成的,顶点 Shader 就是计算每个三角面片上的顶点,并为最终像素渲染做准备
-
像素 Shader:顾名思义,就是以像素为单位,计算光照、颜色的一系列算法
几个不同的图形 API 都有各自的 Shader 语言:
-
在 DirectX 中,顶点 Shader 叫做 Vertex Shader,像素 Shader 叫做 Pixel Shader
-
在 OpenGL 中,顶点 Shader 也叫做 Vertex Shader,但像素 Shader 叫做 Fragment Shader
所以说,Shader 其实就是一段代码
而这段代码的作用就是告诉 GPU 具体怎样去绘制模型的每一个顶点的颜色以及最终每一个像素点的颜色
Shader 编程语言
既然 Shader 是一段代码,那必然要使用一种语言来书写它
目前主流的有三种语言:
-
基于 OpenGL 的 OpenGL Shading Language,简称 GLSL
-
基于 DirectX 的 High Level Shading Language,简称 HLSL
-
还有 NVIDIA 公司的 C for Graphic,简称 Cg 语言
GLSL 与 HLSL 分别是基于 OpenGL 和 Direct3D 的接口,两者不能混用
而 Cg 语言是用于图形的 C 语言,初衷就是让基于图形硬件的编程变得和 C 语言变成一样方便、*
Cg 语言是 Microsoft 和 NVIDIA 相互协作,在标准光照语言的语法和语义上达成一致,所以,HLSL 和 Cg 其实是同一种语言
Unity Shader
在 Unity 中,Shader 的编程反而会变得简单起来
我们不需要在众多显卡、图形 API 以及 Shader 编程语言中进行选择
我们只需关心如何去实现我们想要的效果就可以了,其余的事情 Unity 会自动进行处理
这是因为我们在 Unity 中编写的 Shader 最终会根据不同的平台来编译成不同的着色器语言
Unity Shader 严格来说并不是传统意义上的 Shader,而是 Unity 自身封装后的一种便于书写的 Shader,又称为 ShaderLab
在 Unity 中有三种 Shader(三种不同的写法):
-
Surface Shaders:表面着色器
-
Vertex/Fragment Shaders:顶点/片断着色器
-
Fixed Function Shaders:固定管线着色器
其中 Fixed Function Shaders 已经被淘汰,完全没有学习的必要了
Surface Shaders 其实就是 Unity 对 Vertex/Fragment Shaders 的又一层包装
以使 Shader 的制作方式更符合人类的思维模式,同时可以以极少的代码来完成不同的光照模型与不同平台下需要考虑的事情
但是 Surface Shaders 也有它的局限性
就是 Vertex/Fragment Shaders 能实现的效果,Surface Shaders 不一定能实现
反过来则成立,Surface Shaders 能实现的 Vertex/Fragment Shaders 则一定可以实现
并且在 Unity 2018 后的版本中推出了 Unity 官方自己的可视化 Shader 工具:Shader Graph
Unity Shader 模板
在 Unity Project 面板中点击创建 Shader,你会发现这几个选项:
其中:
Standard Surface Shader
标准表面着色器,是一种基于物理的着色系统(使用了 Physically Based Rendering(简称PBR)技术,即基于物理的渲染技术),
以模拟现实真实的方式来模拟材质与灯光之间的关系,可以很轻易的表现出各种金属反光效果,同时此种 Shader 的书写逻辑也更符合人类的思维模式
Unlit Shader
Vertex/Fragment Shader,也就是最基本的顶点片断着色器,不受光照影响的 Shader,多用于特效、UI 上的效果制作
Image Effect Shader
也是顶点片断着色器,只不过是针对后处理而定制的模版
Compute Effect Shader
Compute Shader 是运行在图形显卡上的一段程序,独立于常规渲染管线之外的,
它可以直接将 GPU 作为并行处理器加以利用,从而使 GPU 不仅具有 3D 渲染能力,还具有其他的运算能力
Shader Variant Collection
Shader 变体收集器,在创建的时候,你会发现 Shader Variant Collection 与以上四个是被隔开的
就是因为这个与它们不一样,它不是制作 Shader 的模版,而只是对 Shader 变体进行打包用的容器
Unity Shader 框架
打开创建的 Shader 后,删除其余代码只留框架:
剩下的框架结构可以拆分成以下几个大部分:
-
Shader "name"
-
Properties
-
SubShaders
-
FallBack
-
CustomEditor
Shader 名称路径
第一行的内容是 Shader "Unlit/NewUnlitShader"
这一行中的 Shader 字眼是一个关键字,后面 "" 双引号中的内容就是具体的路径与名称,其中双引号中的 / 表示的是创建子层级
如果我们把路径名称放在 Hidden 下面的话
则表示在材质面板中隐藏此 Shader,你将无法通过材质下拉列表中找到它
这在做一些不需暴露的 Shader 时很有用处,可以使 Shader 下拉列表更精简整洁
Properties 属性
材质球面板中显示的贴图和一些参数什么的都是在这个 Properties 中进行定义设置的
当然,如果你确定不需要属性的话也可以将整个 Properties 以及它的 {} 全部删除,因为 Properties 是可选项
SubShaders
我们都知道不同的硬件性能是不一样的,游戏内通常把机器配置分为高、中、低三种
假如我们做了一个效果很好的 Shader,但是却只能在高配机上才有较好的性能表现,中低端就会显的太费性能
这时 SubShader 就可以派上用场了:我们可以在这个 Shader 内做三个 SubShader,分别对应于高、中、低不同的配置
FallBack 备用
有的时候我们写的 Shader 难免在一些机器上会出现不支持的问题(最终呈现的就是显示成粉红色)
而这个时候我们只要添加了 FallBack,并且在后面的双引号内写上了其它 Shader 的有效路径名称
那么在碰到不支持的硬件时这个 Shader 就会自动切换成 FallBack 内的 Shader
如果 FallBack 内的 Shader 也不支持呢,那就继续从 FallBack 内的 Shader 中再找 FallBack ... ...
CustomEditor 自定义界面
我们可以通过这个功能来*定义材质面板的显示结果,它可以改写 Properties 中定义的显示方式
Unity Shader Properties 语法格式
属性的写法有个通用的格式:
[Attribute]_Name ("Display Name",Type) = Default Value
其中:
Attribute
属性标记,也就是 Unity 内置的几个属性标记关键字,用于对当前这条属性进行一些特殊的处理
_Name
属性的名称,也就是变量名,在 Shader 的 CG 代码中就是通过这个名称来调用此属性内容的,在外部利用脚本调用时也是这个名称
Display Name
显示在材质面板上的名称,主要起到说明解释的作用
Type
属性的类型,常用的有以下几种:
-
Color(类型:颜色)
-
Int(类型:整型)
-
Float(类型:浮点数)
-
Vector(类型:四维向量)
-
2D(类型:2D纹理)
-
3D(类型:3D纹理)
-
Cube(类型:立方体纹理)
Default Value
默认值,当第一次指定此 Shader 时,或者在材质面板上执行 Reset 时,属性的值会自动恢复到默认值
通用属性标记
-
[Header]
在材质面板上进行标注,通常用作分类组别用,注意只支持英文、数字、空格以及下划线
-
[HideInInspector]
在材质面板中隐藏此条属性,在不希望暴露某条属性时可以快速将其隐藏