本文为ShaderLab系列学习文章,文中内容为Unity5.X游戏开发技术详解和典型案例,希望对正在学习或者想要学习ShaderLab的人有所帮助,如文章有任何错误还请读者帮忙指正,谢谢!
第一天:ShaderLab基础
1.Shader
什么是Shader:Shader是一个着色器程序的跟命令,每一个着色器程序都必须定义唯一一个Shader,其中定义了材质如何使用这个着色器渲染对象。Shader命令语法如下。
Shader "ShaderName"{
[Properties]
SubShader{......}
[Fallback]
}
2:着色器拥有一个Properties的列表。任何定义在着色器程序中的属性都会显示在属性查看器中,典型的有颜色、纹理或者任何被着色器所使用的数据。
3:着色器程序中包含至少一个子着色器,即SubShader,当加载一个着色器程序时,unity将遍历这个列表,获取第一个能够被用户机器支持的子着色器,如果没有一个着色器被支持,unity将尝试降级着色器,即Fallback操作。
2:着色器的三种形态
1:固定管线着色器
固定管线着色器是在老一代GPU能力有限是,对着色器的约束性比较高的一种形态。为了市场占有率,新一代的显卡仍然对齐有所选择的支持,但是未来将逐渐淘汰。
示例:
Shader "Custom/BaseForm1"{
Properties{ //定义的属性快
_Color ("MainColor", Color) = (1,1,1,0.5) //定义主颜色数值
_SpecColor("Sec Color", Color) = (1,1,1,1) //定义高光颜色数值
_Emission("Emission Color", Color) = (0,0,0,0) //定义自发光颜色数值
_Shininess("Shininess", Range(0.01, 1)) = 0.7 //定义高光系数数值
_MainTex("Base (RGB)", 2D) = "White" {} //定义纹理数值
}
SubShader{
Pass{
Material{ //材质块
Diffuse[_Color] //漫反射
Ambient[_Color] //环境光
Shininess[_Shininess] //高光系数
Specular[_SpecColor] //高光
Emission[_Emission] //自发光
}
Lighting On //开启光照
SeparateSpecular On //允许高光使用不同于主颜色的颜色
SetTexture[_MainTex]{ //处理纹理块
constantColor[_Color] //定义颜色值
Combine texture * primary DOUBLE, texture * constant //计算最终颜色
}
}
}
}
2:顶点片元着色器
顶点片元着色器为可编程着色器,相对于固定管线着色器可以给开发人员更大的发挥空间,但是缺点为不能直接和光照交互。着色器程序用CG或HLSL语言编写,嵌入在着色器的渲染通道块中。Cg程序代码片段被编写在CGPROGRAM和ENDCG之间。
顶点着色器中顶点数据必须以一个结构体的形式提交给Cg/HLSL顶点程序,几个常用的顶点结构体在"UnityCG.cginc"文件中,大多数情况下使用它们就足够了,当然也可以自己定义结构体。
下面以一个水的波纹效果制作来加深对顶点片元着色器的理解。
Shader "Custom/MyWater" { //定义了一个着色器,名称为MyWater
Properties { //属性列表,用来指定这段代码将有哪些输入
_MainTex ("Base (RGB)", 2D) = "white" {}//定义一个2D纹理属性,默认白色
_Aim1("Aim1",Vector) = ( 3, 0, 3, -2.5) //波源位置
_Aim2("Aim2",Vector) = ( 5, 0, -5, 2.0)
_Aim3("Aim3",Vector) = (-3, 0, -3, 1.0)
_Aim4("Aim4",Vector) = (-5, 0, 5, 0.5)
_High("High",Float) = 1
}
SubShader { //子着色器
Pass{ //通道
CGPROGRAM //开始标记
#pragma vertex verf //定义顶点着色器
#pragma fragment frag //定义片元着色器
#include "UnityCG.cginc" //引用Unity自带的函数库
sampler2D _MainTex; //2D纹理属性
float4 _Aim1;
float4 _Aim2;
float4 _Aim3;
float4 _Aim4;
float4 _MainTex_ST;
float _High;
struct v2f { //定义一个结构体
float4 pos:POSITION; //声明顶点位置
float2 uv:TEXCOORD0; //声明纹理
};
v2f verf(appdata_base v) //顶点着色器
{
v2f o; //声明一个结构体对象
//计算当前顶点与_Aim1、_Aim2、_Aim3、_Aim4的距离
float dis1 = distance(v.vertex.xyz,_Aim1.xyz);
float dis2 = distance(v.vertex.xyz,_Aim2.xyz);
float dis3 = distance(v.vertex.xyz,_Aim3.xyz);
float dis4 = distance(v.vertex.xyz,_Aim4.xyz);
//计算当前顶点的高度
float H = sin(dis1*_Aim1.w+_Time.z *_High)/5; //计算正弦波的高度
H += sin(dis2*_Aim2.w + _Time.z*_High)/10; //叠加正弦波的高度
H += sin(dis3*_Aim3.w + _Time.z*_High)/15; //叠加正弦波的高度
H += sin(dis4*_Aim4.w + _Time.z*_High)/10; //叠加正弦波的高度
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
o.pos = mul(_Object2World,v.vertex); //将顶点转换到世界坐标的矩阵
o.pos.y = H; //顶点的Y值赋为H
o.pos = mul(_World2Object,o.pos); //将顶点转换到自身坐标的矩阵
o.pos = mul(UNITY_MATRIX_MVP,o.pos); //计算顶点位置
return o; //返回顶点着色器对象
}
fixed4 frag(v2f i):COLOR
{
float4 texCol = tex2D(_MainTex,i.uv); //获取顶点对应UV的染色
return texCol; //返回顶点染色
}
ENDCG //着色器结束标志
}
}
FallBack "Diffuse" //降级着色器(备用的着色器)
}
3:表面着色器
Shader "Custom/BaseForm2" {
Properties { //定义属性块
_Color ("Color", Color) = (1,1,1,1) //定义主颜色数值
_MainTex ("Albedo (RGB)", 2D) = "white" {} //定义纹理数值
_Glossiness ("Smoothness", Range(0,1)) = 0.5 //定义高光系数数值
_Metallic ("Metallic", Range(0,1)) = 0.0 //定义金属材质系数数值
}
SubShader {
Tags { "RenderType"="Opaque" } //标签
LOD 200 //LOD数值
CGPROGRAM
#pragma surface surf Standard fullforwardshadows //表面着色器编译指令
#pragma target 3.0 //着色器编译目标
sampler2D _MainTex; //2D纹理属性
struct Input { //定义输入参数结构体
float2 uv_MainTex; //纹理UV坐标
};
half _Glossiness; //定义高光系数属性
half _Metallic; //定义金属材质系数属性
fixed4 _Color; //定义主颜色属性
void surf (Input IN, inout SurfaceOutputStandard o) { //表面着色器函数
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; //根据UV坐标从纹理提取颜色
o.Albedo = c.rgb; //设置颜色
o.Metallic = _Metallic; //设置金属材质系数
o.Smoothness = _Glossiness; //设置高光系数
o.Alpha = c.a; //设置透明度
}
ENDCG
}
FallBack "Diffuse" //降级着色器
}