Shader分为三种着色器:1.固定管线着色器,2.表面着色器,顶点和片元着色器
1.固定管线着色器:
//固定管线着色器:从语法上将是最简单的着色器,虽然功能有限
//但是在三种着色器中试运行最快的,在所有硬件设备上都可以运行
//组件构成,Properties,SubShader,FallBack
Shader "CustomLearn/First" {
//表示属性的格式:_Name(“DisplayName”,type)= defaultValue(选项{options})
//_Name:是属性的名字,简单来说就是变量的名字,在以后的整个shader代码中使用的这个名字获取属性的值
//DisplayName:表示要显示在Unity材质编辑器中作为编辑器Shader的使用者的可读的内容
//Type:属性的类型:有以下几种
// 1.Color-颜色,有RGBA四个变量开控制,以0~1来取值
// 2.2D- 一个2的幂次方大小的贴图,这张贴图将在采样后被转为对应于基于模型的UV坐标的每个像素的颜色,最终被显示出来
// 3.Rect:一个非2次幂大小的贴图
// 4.Cube:Cube map Texture(立方体纹理),简单俩说就是使用6张有联系的2D贴图的组合,主要用来做发射效果(天空盒子)
// 5.Range:一个介于最大值和最小值之间的浮点数,其值可以在材质编辑面板中进行设置,一般用于调节shader某些特定的参数,比如透明度(0~1)
// 6.Float:表示任意一个浮点数
// 7.Vector:——一个四维数,格式(x,y,z,w)
// 8.defaultValue:默认值,表示一个符合类型格式的值
Properties{
_Color("Main Color",Color) = (1,0.5,0.5,1)
_Alpha("Alpha",Range(0,1)) = 0.5
}
//是子着色器,可以有一个或多个,在实际运行当中选择哪一个着色器运行是由运行平台来决定的
//子着色器是代码的主体,每一个着色器中包含一个或者多个Pass,每个pass都会渲染一次对象
//在计算着色时,平台会优先选用着色器,然依次选择其中的Pass运行,会得到一个输出的结果最后渲染出来
//pass通道:通过控制渲染的对象的一个几何体,除了表面着色器以外,其他两种着色器SubShader中多要包含,主要作用就是渲染材质所在的游戏对象
//pass语法:{{Name and Tags}[RenderSetUp][TextureSetUp]}
//一,Name and Tags:可以定义Pass的名字和任意数量的标签,为Pass命名后,可以在别的Shader中使用改名字来重用它
//二。标签则可以用来向渲染管线说明Pass的意图;
//三,渲染设置:只用于固定功能管线着色器可以设置图形硬件的各种状态,
//可用的设置如下:
//1.Material{}:材质,定义一个顶点光照管线材质
//2.Lighting{}:光照,提供选择有On,Off
//3.Cull:裁剪,设置裁剪的模式,有Back,front,off
//4.ZTest:深度测试,模式包括:Less,Greater,GEqual,Equal,NotEqual,Always;
//5.ZWrite:深度缓存写入,取值为On,Off
//6.Foq{}:雾效,设置雾效参数
//7.AlphaTest:设置Alpha测试,模式:Less,Greater,LEqua
//8.Blend:alpha融合
//9.Color:颜色,设置顶点关照关闭时使用的颜色值
//10.ColorMask:颜色遮罩,其值为0,关闭所有颜色通道渲染,取值为RGBA或者RGB的任意组合
//11.offset:深度偏移
//12.SeparateSpecular:高光颜色取值为On,或者OFF
//13.ColorMaterial:颜色集,当计算顶点光照时,使用每个顶点的颜色
SubShader{
Pass{
//
Material{
Diffuse[_Color]
}
SeparateSpecular On
Lighting On //光照 or "off"
Cull off //剔除(前,后)or “front” or “off”(什么都不提出)
}
}
FallBack "Diffuse" //默认慢反射,如果上面的GPU都不支持,会默认返回Diffuse(支持所有的平台)这个Shader
}
小测试,写一个简单的效果,让草坪贴图看起来更真实:
代码如下:
Shader "CustomLearn/Sceond" {
Properties{
//主颜色
_Color("Main Color",color) = (1,1,1,0.5)
//高光
_SpecColor("Spec Color",color) = (1,1,1,1)
//自发光
_Emmision("Emmision",color) = (0,0,0,0)
//太阳光
_Shiness("Shiness",Range(0.01,1)) =0.7
//主纹理
_MainTex("MainTexture",2D) = "white"{}
}
SubShader{
//tag表示你输出的是什么,如果输出中都是非透明物体,写在Opaque中,如果想渲染透明的或者半透明的物体,写在Transparent中
//其他的标签还有:“IqnoreProjector” = “True”(忽略投影,),不被Projector投影所影响
//“ForceNoShaderCasting” = “True”(从来不产生阴影)
//“Queue” = “XXX”(指定渲染顺序队列)
Tags{"Queue" = "Transparent"}
//“Queue”中可以使用的值有:
//BackGroud:是最早被调用的渲染,用来渲染天空或者背景
//Geometry:默认值,用来渲染非透明物体
//AlphaTest:用来渲染透明度的
//Overlay:用来渲染叠加效果是渲染的最后阶段
//透明的混合
Blend srcAlpha OneMinusSrcAlpha
pass{
Material{
//漫反射颜色
Diffuse[_Color]
//环境光颜色
Ambient[_Color]
Shininess[_Shiness]
Specular[_SpecColor]
Emission[_Emmision]
}
//开启灯光
Lighting On
//开启顶点光照的平行高光颜色
SeparateSpecular On
//设置纹理
SetTexture[_MainTex]{
//纹理颜色
constantcolor[_Color]
//混合效果
//纹理*原色的两倍,纹理*常量颜色
Combine texture*primary DOUBLE,texture*constant
}
}
}
FallBack "Diffuse"
}
2,表面着色器
Shader "CustomLearn/Thrid" {
Properties {
_Color("Color",Color)=(1,1,1,1)
//对于贴图来说,其值可以用一个代表tint颜色的字符串来表示
//后面跟option选项,选项值可以为空,这里的option之和贴图有关,里面至少要有一个为空{},
//如果需要加入一些特定的选项,有:ObjectLinear、SphereMap、CubeReflect
//图片的字符串默认值可以为:White,black,gray,bump(凹凸)
_MainTex("Albeo (RGB)",2D)="white"{}
//表面光滑度
_Glossiness("Smoothness",Range(0,1)) = 0.5
//表面带有金属光泽度
_Metallic("Metallic",Range(0,1)) = 0.0
}
SubShader {
//表面着色器可以被若干个标签所修饰,而硬件将通过判定这些标签来决定什么时候该用什么着色器
//如果"RenderType"="Opaque",表示在渲染非透明的物体时调用,所以透明Transparent(表示有透明效果的物体时调用)
//RennderType课赋值的类型有:
//1. opaque:绝大部分不透明物体使用这个
//2. Transparent:绝大部分透明或者半透明物体,粒子特效使用
//3.Background:天空盒子使用这个
//4.Overlay:用来渲染叠加效果,镜头光晕使用这个
Tags{"RenderType" = "Opaque"} //渲染不透明的
//LOD指的是Level of Detail 的缩写,我们能够使用什么样的Shader实际由它来决定
//Unity内的Shader指定了一组LOD值,我们在写Shader的时候,可以将这些值作为参考
//VertexLit(顶点光照):大约是:100
//Decal,Reflective VertexLit(反射顶点光照):150
//Diffuse:(漫反射):200
//Deiffuse Detail:250
//Bumped,Spercular(凹凸,高光):300
//BumpedSpercular(凹凸高光):400
//Parallax(视差):500
//Parallax Spercular(视差高光):600
LOD 200
//表面着色器中的实现代码需要放在CGPROGRAM……ENDCG中
CGPROGRAM
//#pragma(唯一标识) surface(使用表面着色器) surf(着色器表面函数的名字,用来处理Shader中的输入,以及负责输出) Standard fullforwardshadows//-
//LightModel:使用光照的模型,Lambert是普通的diffuse作为光照模型
#pragma surface surf Standard fullforwardshadows
//使用的Shader版本3.0
#pragma target 3.0
//表示GLSL中的纹理类型,相应的类型还有sampler1Dmsampler3D,samplerCube等
sampler2D _MainTex;
//所需要参与计算的数据
//输入解放构体中还可以包括其他成员
//float viewDir:视角方向
//float COLDR:每个顶点的颜色插值
//float4 screenPos:屏幕坐标(使用x,y,z,w)
//float3 worldPos:世界坐标
struct Input{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
//表面着色器代码方法,着色器就是给定了输出,然后给出输出尽心着色的代码
//第一个参数:IN是我们需要定义的输入结构,可以把所需要的参与计算的数据都放在该结构体汇总,出入方法使用
//第二个参数:inout SurfaceOutputStandard定义输出结构的类型,需要把方法中得到的结果赋值给该结构体里面的成员变量即可以完成着色
//SurfaceOutputStandard标准结构输出
//half:为半精度浮点数
//1.fixed3 Albedo:基础颜色(漫反射)
//2.fixed3 Normal:切线空间法线
//2.half Metallic:是否有金属特性,0=非金属特性,1=金属
//4.half Smoothness:是否光滑,0=粗糙,1=光滑
//5.half Occlision:遮挡
//6.fixed Alpha:透明度
void surf(Input IN,inout SurfaceOutputStandard o){
// tex2D方法是CG程序中用来在一张贴图上对一个点进行采样的方法
//返回一个fixed4类型的值(fixed取代的一个浮点数)
//这里是对输入的_MainTex进行采样
fixed4 c = tex2D(_MainTex,IN.uv_MainTex)*_Color;
//吧采样后的颜色赋值给输出颜色
o.Albedo = c.rgb;
o.Alpha = c.a;
o.Metallic= _Metallic;
o.Smoothness = _Glossiness;
}
//表示CG的语法结束
ENDCG
}
FallBack "Diffuse"
}
实例测试:一个真实的石头
//实现法线贴图的,让模型的表面实现一些凹凸的细节
Shader "CustomLearn/Forth" {
Properties {
//纹理属性
_MainTex("Texture",2D) = "white"{}
//发现贴图属性
_BumpMap("Bump",2D) = "bump"{}
}
SubShader {
//表示渲染非透明物体
Tags{"RenderType" = "Opaque"}
//LOD默认200,可以省略
//CG代码
CGPROGRAM
#pragma surface surf Lambert
//版本可以省略#pragma
//输入的数据结构体
struct Input{
float2 uv_MainTex;
float2 uv_BumpMap;
};
sampler2D _MainTex;
sampler2D _BumpMap;
void surf(Input IN,inout SurfaceOutput o){
//输出颜色的处理
o.Albedo = tex2D(_MainTex,IN.uv_MainTex).rgb;
//在计算发现的时候,只需要调用UnpackNormal这个函数就可以实现
//趋近的映射或者说UnpackNormal是对法线纹理的采样方法,将法线纹理中的颜色映射回正确的法线向量
o.Normal = UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));
}
ENDCG
}
FallBack "Diffuse"
}
实例测试02:动态云图
Shader "CustomLearn/Five" {
Properties {
//纹理
_MainTex("Albedo(RGB)",2D) = "white"{}
//颜色
_Color("Color",color)=(0,0,0,0)
//透明度
_Alpha("Alpha",Range(0,1)) = 0.5
_SpeedX("X_speed",Range(0.5,10)) = 0.6
_SpeedY("Y_speed",Range(0.5,10)) = 0.6
}
SubShader {
Tags{"ReaderType" = "Transparent"}
CGPROGRAM
//alpha表示透明
#pragma surface surf Lambert alpha
sampler2D _MainTex;
fixed _Alpha;
fixed _SpeedX;
fixed _SpeedY;
fixed4 _Color;
//输入结构体
struct Input{
float2 uv_MainTex;
};
void surf(Input IN,inout SurfaceOutput o){
fixed xSpeed = _SpeedX*_Time*0.1;
fixed ySpeed = _SpeedY*_Time*0.1;
//根据输入的纹理的uv信息和设置的速度得到要动态重新显示的纹理上的uv
fixed2 uv = IN.uv_MainTex - fixed2(xSpeed,ySpeed);
//根据计算出的动态uv进行像素点采样
fixed3 c = tex2D(_MainTex,uv);
o.Albedo = c.rgb;
o.Alpha = _Alpha;
}
ENDCG
}
FallBack "Diffuse"
}