UnityShader系列文章转载于 @浅墨_毛星云,为本人的学习笔记,转载请注明出处。
文章链接:https://blog.csdn.net/poem_qianmo/article/details/40955607
Shader和Material的基础概念
先引用一段文字,阐述Shader和Material的基本关系
“Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等,加上对应的Shader,以及对Shader的特定参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到就是一个Material(材质)。之后,我们便可以将材质赋予合适的renderer(渲染器)来进行渲染(输出)了
所以说Shader并没有什么特别神奇的,它只是一段规定好输入(颜色,贴图等)和输出(渲染器能够读懂的点和颜色的对应关系)的程序,而Shader开发者要做的就是根据输入,进行计算变换,产生输出而已。”
文字出自 《猫都能学会的Unity3D Shader入门指南(一)》。
Unity中Shader的三种类型
我们知道,计算机图形学中的渲染管线一般分为两种类型:
固定渲染管线
可编程渲染管线
而在Unity中,Shader可分为以下三种类型
固定功能着色器(Fixed Function Shader)
表面着色器(Surface Shader)
顶点着色器&片段着色器(Vertex Shader & Fragment Shader)
怎么区别Unity中的Shader类型
没有嵌套CG语言,也就是代码段中没有CGPROGRAM和ENDCG关键字的,就是固定功能着色器
嵌套了CG语言,代码段中有surf函数的,就是表面着色器
嵌套了CG语言,代码段中有#pragma vertex name 和 #pragma fragment frag声明的,就是顶点着色器&片段着色器
Unity中Shader的基础框架
Shader "name"{
Properties{
}
SubShader{
}
SubShader{
}......
Fallback
}
Unity中所有的着色器都是有Shader关键字开始,随后的字符串表示着色器的名字。这个名字会显示在Inspector检视面板中,该名字是一段描述性文字,并不需要与Shader文件名相同。
Shader的整体框架如下图所示
首先是属性的定义,用来指定这段代码将有哪些输入。接下来是一个或者多个的子着色器,在实际运行中,哪一个子着色器被使用是有运行的平台决定的。子着色器是代码的主体,每一个子着色器包含一个或者多个的pass。在计算着色时,平台先选择最优先可以使用的着色器,然后依次运行其中的Pass,然后得到输出的结果。当所有SubShader都不能运行时,则会执行Fallback(比如运行设备实在太老了,所有的SubShader中都有不被支持的特性,才会执行Fallback)
Shader "typedef/4.简单纹理的载入Shader" {
//--------------------------------------------------------【属性】--------------------------------------------
Properties {
//纹理
_MainTex("基础纹理",2D)="White"{TexGen SphereMap}
}
//--------------------------------------------------【第一个子着色器】--------------------------------------------
SubShader {
//------------------------------------通道------------------------------------------
Pass{
//设置纹理为属性中选择的纹理
SetTexture[_MainTex]{combine texture}
}
}
FallBack "Diffuse"
}
需要注意的是,SubShader在UnityShader中必须至少有一个。
Properties属性
properties一般定义在着色器的起始部分,在使用Shader的时候可以直接在材质检视面板里编辑这些属性,如下图:
Properties快内的语法都是单行的。每个属性都是由内部名称开始,后面括号中是显示在检视面板中的名称和该属性的类型。等号后边是默认值
即
_内部名称("编辑器中显示的名称",属性类型)=默认值
属性的类型
name("display name",Range(min,max)) = number
定义浮点数属性,在检视面板中可通过一个标注最大最小的滑条来修改
name("display name",Color) = (r,g,b,a)
定义颜色属性
name("display name",2D) = "name"{options}
定义2D纹理属性
name("display name",Rect) = "name"{options}
定义长方形(非2次方)纹理属性
name("display name",Cube) = "name"{options}
定义立方贴图属性
name("display name",Float) = number
定义浮点数属性
name("display name",Vector) = (number,number,number,number)
定义一个四元素的容器(相当于Vector4)属性
注意事项:
包含在着色器中的每一个属性通过name索引(在Unity中,通常使用下划线开始一个着色器属性的名字)。属性会将display name显示在材质检视器中
对于Range和Float类型的属性只能是单精度值
对于Color和Vector类型的属性将包含4个由括号围住的数描述
对于纹理(2D,Rect,Cube)缺省值既可以是一个空字符串也可以是某个内置的缺省纹理:“white”、“black”、“gray”、“bump”
在子着色器中,属性值通过[name]来访问
关于纹理属性选项
name("display name",2D)="name"{options}
options是可选的,可选的选项有:
TexGen纹理生成类型。即纹理的自动生成纹理坐标时的模式,可以是ObjectLinear, EyeLinear,SphereMap, CubeReflect, CubeNormal的其中之一;这些模式和OpenGL纹理生成模式相对应。注意如果使用自定义顶点程序,那么纹理生成将被忽略。
LightmapMode 光照贴图模式。如果我们给出这个选项,纹理将能被渲染器的光线贴图属性所影响。纹理不能被使用在材质中,而是取自渲染器的设定。
例如:
_MainTex("基础纹理",2D)="White"{TexGen SphereMap}
光照、材质与颜色
在Pass{ }中,可以进行以下内容的编写
Color Color
设定对象的纯色。颜色即可以是(RGBA),也可以是被方框包围的颜色属性值,例如:Color(r,g,b,a)、Color[_Color]
Material{Material Block}
材质块被用于定义对象的材质属性
Lighting On|Off
开启光照,也就是定义材质块中的设定是否有效。想要有效的话必须使用Lighting On命名开启光照,而颜色则通过Color命令直接给出
SeparateSecular On|Off
开启独立镜面反射。这个命令会添加高光光照到着色器通道的末尾,因此对高光没有影响。只在光照开启时有效。
ColorMaterial AmbientAndDiffuse|Emission
使用每个顶点的颜色代替材质中的颜色集。AmbientAndDiffuse代替材质的阴影和漫反射值;Emission代替材质中的光发射值。
材质块Material Block
Diffuse Color(R,G,B,A)
漫反射颜色构成。这就是对象的基本颜色。
Ambient Color(R,G,B,A)
环境色颜色构成。这是当对象被RenderSetting中设定的环境色所照射时对象所表现的颜色
Specular Color(R,G,B,A)
对象反射高光的颜色。
Shininess Number
加亮时的光泽度,在0和1之间。0的时候你会发现更大的高亮也看起来像漫反射光照,1的时候你会获得一个细微的亮斑
Emission Color
自发光颜色,也就是当不被任何光照所照到时,对象的颜色。
而打在对象上的完整光照颜色最终是:
最终颜色=环境光反射颜色*渲染设置环境设置*(灯光颜色*漫反射颜色+灯光颜色*镜面反射颜色)+自发光
综合应用
Shader "typedef/6.光照材质完备正式版Shader" {
//--------------------------------------------------------【属性】--------------------------------------------
Properties {
_Color("主颜色",Color) = (1,1,1,0)
_SpecColor("高光颜色", Color) = (1,1,1,1)
_Emission("自发光颜色",Color) = (0,0,0,0)
_Shininess("光泽度",Range(0.01,1)) = 0.7
_MainTex("基础纹理",2D) = "white"{}
}
//--------------------------------------------------【子着色器】--------------------------------------------
SubShader {
//------------------------------------通道------------------------------------------
Pass{
//----------------------------材质------------------------
Material{
//可调节的漫反射光和环境光反射颜色
Diffuse[_Color]
Ambient[_Color]
//光泽度
Shininess[_Shininess]
//高光颜色
Specular[_SpecColor]
//自发光颜色
Emission[_Emission]
}
//开启光照
Lighting On
//开启独立镜面反射
SeparateSpecular On
//设置纹理并进行纹理混合
SetTexture[_MainTex]{
Combine texture * primary DOUBLE,texture*primary
}
}
}
FallBack "Diffuse"
}