新建一个shader,名为MyShader1内容如下:
1、_MainTex 为变量名
2、“Base (RGB)”表示在unity编辑面板中显示的名字,可以定义为中文
3、2D 表示变量的类型
4、white 表示初始值(默认值),默认为白色
变量名建议下划线开头
我们也来定义几个变量试试:
_My2D ("Base (RGB)", 2D) = "white" {}
_myfloat("浮点数",float)=0.3
_myRange("数值范围",Range(1,10))=3
_MyVector("向量",Vector)=(1,1,1,1)
_MyColor("颜色",Color)=(22,55,66,1)
_MyRect("矩形",Rect)="red" {}
Shader数值类型:
大家尽可能使用占内存小的fixed类型,优化性能,但是某些显卡,特别是手机上对fixed的支持不太好,所以要根据具体的情况来使用!
shader的三种形式,也就是shader的三种写法
Unity中所有渲染都使用着色器完成
unity的shaderlab对cg的程序进行了一个封装,封装的目的是让我们编写脚本的人能够更快的上手,更简单的去编写,用更简洁的代码去实现一个功能,
这里分为三种写法,如下:
1、顶点和片段着色器
2、表面着色器
3、固定功能着色器
固定功能着色器
此着色器写法是非常简单的,但是功能少,Unity官方是不建议大家用这个写法的
优势是能够用在比较陈旧古老的硬件上,在其他着色器的功能不支持之后,才去考虑用固定着色器。
顶点和片段着色器
功能最强大、最*的形态,但是要编写的代码自然就会增多
特征是在Pass里出现CGPROGRAM和ENDCG块
Pass:通道 Name为通道名称
float2:相当于一个数组,包含两个float值,
float3:包含三个float值,同理float4......
pos为变量名
POSITION为语义,通俗来讲,因为cg里面有很多东西,比如一个颜色color,它是rgba,所以他是float4类型的数值,表示四个数,还有比如说向量,一个坐标(x,y,z),另外再加上一个方向向量,那么它也是一个float4类型的数值,float4不仅可以表示为颜色color,还可以表示为向量,以及UV等,那么为了表明我们声明的这个float4类型的变量是干嘛的,是用来表示颜色的还是向量的?为了说明它的作用,所以采用了语义来描述
显卡会首先调用顶点函数,通过计算得到一个v2f类型的值,这个值再交给片段函数,片段函数返回的是一个语义为Color的half4类型的值
appdata_base是来自于我们引入的包UnityCG.cginc里面定义的!UnityCG.cginc路径大概在Unity\Editor\Data\CGIncludes\下
表面着色器
Unity推荐使用的一种写法,当我们在unity里面create一个shader的时候,unity默认给我们创建的就是表面着色器
因为表面着色器自身会编译为多个通道,所以我们不能为它添加Pass通道,手动添加就会报错!
subshader、fallback、Pass LOD
一个subshader里面至少要包含一个通道Pass(表面着色器除外,因为它自身会编译为多个通道)
由于显卡兼容性存在偏差,如果存在多个subshader,默认情况下,是先执行第一个subshader,如果可以执行的话就执行它
如果第一个sunshader由于兼容性或者其他的问题不可以执行的话,那么会按顺序执行下面的subshader,如果一直到最后一个subshader也不能执行,
那么就使用Fallback指定的shader(diffuse)来执行
Pass的意义在于多次渲染,如果你有一个pass,那么着色器只会被调用一次,
如果你有多个Pass的话,那么就相当于执行多次subshader了,这就叫双通道或者多通道
在编写shader的时候,Pass要尽量的少,每多一个pass,那么dc就会多一次!
但是在实际运用的有些情况当中,是有可能要用到多个pass的,等具体情况具体分析
如果LOD设置为250的话,那么小于等于250的值对应的效果会被显示,而大于250的效果可能就不显示了!
tags
渲染序列Queue:
在场景里面,摄像头看到的物体是有先后关系的,那么它的渲染也是有个顺序的,它是有一个值可以设置的,值越小越先绘制,越大越后绘制(显示在最前面)
可以理解为权重越大,离摄像机越近!
这里定义了一些默认值,例如Background为1000,Geometry为2000等
自己可以定义任意值,但是表达式必须要包含某个默认值,例如"Queue"="1200"直接赋值为一个数字是错误的,会报错的!
只能这样:"Queue"="Geometry+5"
我们来做一个例子:场景中放一个cube盒子,和一个sphere球,把球放在盒子的后面,我们通过操作两者的shader来让盒子后面的球显示在最前面,
根据上面对渲染序列的介绍,那么正确的做法应该就是把球的Queue的值设的比盒子的大就可以了,可是并没有达到预期的效果,如下,盒子还是在最前面显示:
这里就涉及到了一个知识点了:深度缓存,我们只要关闭盒子的深度缓存就可以了(球的深度缓存关不关不受影响)!
默认绘制优先级是以深度缓存进行处理的,
深度缓存可以理解为,摆放物体距摄像机的远近,距离摄像机近的物体越后渲染,权重越大,显示越靠前,反之,显示越靠后!
Zwrite off:关闭深度缓存, 在渲染时,每个模型都有一个深度的,现在有可能球的深度是1,盒子是2,深度越大,绘制在越前面,
所以造成这种情况,只要关闭深度缓存,就会应用我们指定的渲染序列了!
Tags { Queue="Geometry+5" RenderType=Opaque }
LOD
Zwrite off
效果图:
如果有这样一个需求:即使被其他物体遮住,也要显示在这些物体的最前面,那么除了调整自己的渲染序列Queue值
大于那些在它前面的物体的Queue值,还要把遮住它的那些物体的深度缓存给关闭就可以了!
如果你不把那么遮挡你的物体的深度缓存给关闭了,那么即使你的渲染序列大于他们,也是没有用的!
关闭深度缓存的目的就是把被自己挡住的并且渲染序列大于自己的那些物体给去除遮挡