Unity Shaders and Effects Cookbook:表面着色器
这篇文章要和大家介绍下表面着色器Surface Shader,不了解表面着色器的同学可以看看。
1、创建基本的表面着色器
在Assets 中创建文件夹 ,命名为 Materials 。 在 Materials 里面 Create 一个 Shader 。再创建一个 Material 。都命名为 BasicDiffuse 。
打开BasicDiffuse.shader 。里面默认已经添加了 基本的漫反射着色器 代码,这个Shader 接受一个 纹理信息 。
把自动创建的 Shader 改名,如下:
Shader "CookBookShaders/BasicDiffuse" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
选择上面创建的 Material ( BasicDiffuse.mat ) , 在 Inspector 中,点击下拉框,选择上面创建的 Shader ( CookBookShaders/BasicDiffuse ) ,这样就将着色器 赋给了 材质 。
然后创建一个 Cube ,把 BasisDiffuse.mat 拖到 Cube 上。
这样就完成了 着色器开发环境 的设置。
对于表面着色器来说,很多元素都在后台完成了,Unity采用 CG 作为着色语言,CG让代码编写更加高效。
表面着色器语言大多基于组件的方式写入着色器。
Unity内置了大量的 CG 功能,在 Editor/Data/CGIncludes 这个目录中可以看到几个 CG 文件。
我们刚才创建的 基本的表面着色器 ,用到了 其中的 UnityCG.cginc 、Lighting.cginc、UnityShaderVariables.cginc 这三个CG文件。
2、为表面着色器添加属性
着色器的属性,是让我们可以在编辑器或者在代码中去调整着色器的值。
2.1 、Properties区域着色器中的属性
在 Shader 中的 Properties ,对应着 同名的变量,这就类似于 Properties 中的是 变量的 名字字符串。Unity 通过读取 Properties 中的属性 来创建对应的编辑器控件,显示在 Inspector 窗口上,让我们很方便的去编辑这个属性的值。
Properties 中属性的格式如下:
_EmissiveColor : 变量名
"Emissive Color" : 编辑器中 Inspector面板上显示的名称
Color : 变量类型
(1,1,1,1) :默认值
我们来添加一个着色器属性
修改默认的 Shader代码,删除默认的 _MainTex 属性
修改 Properties 块如下:
Properties { _EmissiveColor("Emissive Color",Color) = (1,1,1,1) //设置默认值 }
返回 Unity 查看,现在能在编辑器中看到 Emissive Color 这个设置
再添加一个 Range 属性
Properties { _EmissiveColor("Emissive Color",Color) = (1,1,1,1) //设置默认值 _EmissivePowValue("EmissivePow Value",Range(0,10)) = 1 }
Range 是一个范围,在编辑器中是一个滑动条
好,已经添加了属性,下面来使用这两个属性。
2.2 、在着色器中使用属性
首先删除原来的代码 ,这句代码中声明了一个变量 _MainTex ,对应我们之前删除的 _MainTex 属性。我们删掉它 添加我们自己的变量
sampler2D _MainTex;
然后下面的 surf 函数中用到 _MainTex 的代码也删除
half4 c = tex2D (_MainTex, IN.uv_MainTex);
对应上面新增的两个属性,添加我们的同名变量。
float4 _EmissiveColor float _EmissivePowValue
然后在 surf 函数中使用这两个新增的变量
void surf (Input IN, inout SurfaceOutput o) { float4 c; c=pow(_EmissiveColor,_EmissivePowValue); o.Albedo = c.rgb; o.Alpha = c.a; }
完整的 BasicDiffuse.shader
Shader "CookBookShaders/BasicDiffuse" { Properties { _EmissiveColor("Emissive Color",Color) = (1,1,1,1) //设置默认值 _EmissivePowValue("EmissivePow Value",Range(0,10)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert float4 _EmissiveColor; float _EmissivePowValue; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { float4 c; c=pow(_EmissiveColor,_EmissivePowValue); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
Pow :求幂函数,例如 Pow(2,3) = 8
修改完代码之后,再到 Unity中查看。调解 滑动条,就能看到不同的效果。
在 Shader 中,对指定的 _EmissiveColor 进行了 以 _EmissivePowValue 为指数的求幂。
在编辑器中对 EmissiveColor 指定的值是 0-255 范围的,这个值在 Shader 中被 规格化为 0-1 。
所以随着 EmissivePowValue 的值越来越大,c=pow(_EmissiveColor,_EmissivePowValue); 这个求的值里面的 RGBA 是越来越小,逼近 0 ,所以慢慢得,方块就变成了黑色。
示例工程下载:http://pan.baidu.com/s/1skjNqNz