Shader笔记——ShaderLab

在Unity中,所有的Shader程序都是使用名为“ShaderLab”的声明性语言进行编写的。ShaderLab语法不区分大小写。

1.1 Shader的组织结构

Shader的大致结构如下:

Shader "Name"
{
    Properties
    {
        //开放到材质面板的属性
    }
    SubShader
    {
        //顶点-片段着色器或者表面着色器或者固定函数着色器
    }
    SubShader
    {
        //更加精简的版本
        //为了在旧的图形设备上运行
    }
    Fallback "Name"
}
  1. Shader中可以编写多个SubShader,但至少需要一个。在应用程序运行过程中,GPU会先检测第一个SubShader能否正常运行,如果不能正常运行就会在检测第二个,依次类推。
  2. 假如当前GPG的硬件版本太旧,以至于所有的SubShader都无法正常运行,则执行最后的Fallback命令,运行指定的一个基础着色器。
  3. 如果编写的是Vertex-Fragment Shader,每个SubShader还会包含一个或多个Pass。如果某个SubShader能够在当前GPU上运行,那么该SubShader内的所有Pass会依次执行,每个Pass的输出结果会以指定的方式与上一步的结果进行混合,最终输出。
  4. 如果编写的是Surface Shader,着色器的代码也是包含在SubShader中,但是Surface Shader不会在嵌套Pass。系统在编译编译Surface Shader时会自动生成多个对应的Pass,最终编译出来的Shader本质上就是Vertex-Fragment Shader。

1.2 Shader的名称

Shader程序的第一行代码用来声明该Shader的名称以及所在的路径。如:

Shader "Custom/Simple Shader"
Shader选择面板

1.3 Properties

Unity可以通过Properties代码块将不同类型的变量或贴图资源开放给开发者,以便可以在材质面板中调节。
Unity Shader的属性主要分为三大类:数值,颜色和向量,纹理贴图,语法定义如下:

_Name("Display Name",type)=defaultValue[{option}]

(1)_Name:属性的名字。通常在名字的最前加一个下划线,后续在整个Shader中都将使用这个名称来获取该属性。
(2)Display Name:在材质面板中显示出来的名称。
(3)type:属性的类型。
(4)defaultValue:将Shader指定给材质的时候初始化的默认值。

所有类型属性汇总如下:

    Properties
    {
        // 浮点类型 
        _MyFloat ("Float Property", Float) = 1 
        // 范围类型
        _MyRange ("Range Property", Range(0, 1)) = 0.1 
        // 颜色类型   
        // 数值范围是[0,1]
        _MyColor ("Color Property", Color) = (1, 1, 1, 1) 
        //向量类型
        _MyVector ("Vector Property", Vector) = (0, 1, 0, 0) 
        // 2D贴图类型   
        // 默认值可以为空字符串,也可以是表示颜色的字符串如:"white","black","gray","bump"
        // "bump"通常用于法线贴图的默认值
        _MyTex ("Texture Property", 2D) = "white" {} 
        // 立方体贴图类型
        // 默认值使用gray(RGBA:0.5,0.5,0.5,0.5)
        _MyCube ("Cube Property", Cube) = "" {} 
        // 3D贴图类型
        // 默认值使用gray(RGBA:0.5,0.5,0.5,0.5)
        _My3D ("3D Property", 3D) = "" {} 
    }
不同属性类型的显示样式

在Unity5.0之前的版本,纹理属性可以在花括号内添加属性,用于控制固定函数纹理坐标的生成。但是该功能在Unity5.0及以后版本已经移除,所以直接加上一对空的花括号即可。

虽然Properties在参数调节过程中提供了便利,但是这部分代码在Shader中并不是必须的。如果不需要开放参数,完全可以在Shader中省略Properties这部分代码。

1.4 SubShader

SubShader大致结构如下:

    SubShader
    {
        // 标签
        Tags{"TagName1" = "Value1" "TagName2" = "Value2"}
        // 渲染状态
        Cull Back

        pass
        {
            // 第一个Pass
        }
        pass
        {
            // 第二个Pass
        }
    }

每个SubShader都可以设置一个或多个标签(Tags)和渲染状态(States),然后定义至少一个Pass。在SubShader中设置的渲染状态会影响到该SubShader中所有的Pass,如果想要某些状态不影响其他Pass,可以针对某个Pass单独设置渲染状态,不过需要注意,部分渲染状态在Pass中并不支持。

1.4.1 SubShader的标签

SubShader通过标签来确定什么时候以及如何对物体进行渲染,标签通过键值对的形式进行声明,没有数量限制,语法如下:

Tags{"TagName1" = "Value1" "TagName2" = "Value2"}

1. 渲染队列 Queue
在SubShader中可以使用Queue标签确定物体的渲染顺序,如下Unity预先定义的五中渲染队列:

队列名称 描述 队列号
Background 最先执行渲染,一般用来绘制Skybox或者背景 1000
Geometry 非透明的几何体通常使用这个队列,当没有声明渲染队列的时候,Unity会默认使用这个队列 2000
AlphaTest Alpha Test的几何体都是用这个队列,之所以从Geometry队列单独拆分出来,是因为当所有实体都绘制完之后在绘制Alpha Test会更高效 2450
Transparent 在这个队列的几何体按由远及近的顺序进行绘制,所有进行Alpha Blend的几何体都应该使用这个队列,如玻璃材质,粒子特效 3000
Overlay 用于叠加渲染的效果,如镜头光晕,放到最后渲染 4000

也可以自己指定一个队列,如:

Tags { "Queue" =  "Geometry + 1" }

也可以在材质面板中进行设置,如图:

材质设置面板中的渲染队列

2. 渲染类型 RenderType
RenderType标签可以将Shader划分为不同的类别,用于后期进行Shader替换或者产生摄像机的深度纹理。如下:

类别说明 描述
Opaque 用于普通Shader,如:不透明,自发光,反射,地形Shader
Transparent 用于半透明Shader,如:透明,粒子
TransparentCutout 用于透明测试Shader,如:植物叶子
Background 用于Skybox Shader
Overlay 用于GUI纹理,Halo,Flare Shader
TreeOpaque 用于地形系统中的树干
TreeTransparentCutout 用于地形系统中的树叶
TreeBillboard 用于地形系统中的Billboarded树
Grass 用于地形系统中的草
GrassBillboard 用于地形系统中的Billboarded草

3. 禁用批处理 DisableBatching
当使用批处理(Batching)的时候,几何体会被变换到世界空间,模型空间会被丢弃。这会导致某些使用模型空间顶点数据的Shader最终无法实现所希望的效果。而开启DisableBatching(禁用批处理)可以解决这个问题。
禁用批处理标签有三个数值可以使用:
(1)"DisableBatching"="True":总是禁用批处理。
(2)"DisableBatching"="False":不禁用批处理,这是默认值。
(3)"DisableBatching"="LODFading":当LOD效果激活的时候才会禁用批处理,主要用于地形系统上的树。
4. 禁用阴影投射 ForceNoShadowCasting
在游戏中,有很多特效类的物体并不需要对其他物体产生投影,这个时候可以将ForceNoShadowCasting标签设置为True。
5. 忽略投影机 IgnoreProjector
如果不希望物体受到Projector(投影机)的投射,可以将IgnoreProjector标签设置为True。一般半透明的Shader都会开启这个标签。
6. 其他标签
除此之外,Unity还提供了很多不常用的标签,如CanUseSpriteAtlas,PreviewType等。请看Unity官方文档关于SubShader标签这一部分的内容。

1.4.2 Pass的渲染状态

如果想某些Pass的渲染状态不影响到其他Pass,可以在该Pass中单独设置渲染状态。并且这些渲染状态在SubShader中同样被允许使用,但是会影响到该SubShader中所有Pass。

渲染状态 数值 作用
Cull Cull Back|Front|Off 设置多边形的剔除方式,有背面剔除,正面剔除,不剔除,默认为Back
ZTest ZTest LEqual|GEqual|Equal|NotEqual|Less|Greater|Always 设置深度测试的对比方式,默认为LEqual
ZWrite ZWrite On|Off 设置是否写入深度缓存,默认为On
Blend Blend sourceBlendMode destBlendMode 设置渲染图像的混合方式
ColorMask ColorMask RGB|A|0|或者R,G,B,A的任意组合 设置颜色通道的写入蒙版,默认模板为RGBA,当设置为0时,则无法写入任何颜色

其他低频使用的渲染状态请阅读Unity官方文档里关于Pass的渲染状态这一部分内容。

1.5 Fallback

Fallback在所有SubShader之后进行定义。当所有SubShader都不能在当前显卡上运行的时候,就会运行Fallback定义的Shader。语法如下:

Fallback "name"

最常用于Fallback的Shader为Unity内置的Diffuse。
可以使用Fallback Off或者直接什么都不写,来关闭Fallback功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353