Unity Shaders 第一个默认程序分析
Unity Shaders 第一个默认程序
1 Shader "Custom/Shader" { 2 Properties { 3 _MainTex ("Base (RGB)", 2D) = "white" {} 4 } 5 SubShader { 6 Tags { "RenderType"="Opaque" } 7 LOD 200 8 9 CGPROGRAM 10 #pragma surface surf Lambert 11 12 sampler2D _MainTex; 13 14 struct Input { 15 float2 uv_MainTex; 16 }; 17 18 void surf (Input IN, inout SurfaceOutput o) { 19 half4 c = tex2D (_MainTex, IN.uv_MainTex); 20 o.Albedo = c.rgb; 21 o.Alpha = c.a; 22 } 23 ENDCG 24 } 25 FallBack "Diffuse" 26 }
1,Tags 硬件童工这些标签来决定什么时候调用该着色器。
Tags{“RenderType”=“Opaque"}告诉系统应该在渲染非透明物体的时候调用我们。
“RenderType”=“Transparent"表示渲染含有透明效果的物体时候调用。
在这里暗示你得shader输出的是什么。
“IgnoreProjector”=“True” 不被Projectors影响。
“ForceNoShadowCasting”=“True”从不产生阴影。
“Queue”=“xxx"指定渲染顺序队列。
注意:不透明物体可能无法呈现在透明物体之后的情况。可能由于shader渲染顺序不正确导致的。
预定义的Queue有:
Background: 最早被调用的渲染,用来渲染太空盒或背景
Geomery:这是默认值,用来渲染非透明物体。
AlphaTest:用来渲染经过AlphaTest的像素,单独AlphaTest设定一个Queue是出于对效率的考虑。
Transparent:以从后往前的顺序渲染透明物体。
Overlay:用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等效果)。
我们也可以这么写 “Queue”=“Transparent+100”,表示一个在Transparent之后100的Queue上进行调用。通过调用Queue值,我们可以确保某些物体一定在另一些物体之前或之后渲染。
2,LOD 是Level of Detail的缩写。这个值决定我们用什么样的Shader。
当Quality Settings中我们设定的LOD小于subShader中得LOD时,这个SubShader将不可用。
根据设备图形性能来调整画质的时候,可以比较准确的控制。
VertextLit =100
Decal,Reflective VertexLit=150
Diffuse=200
Diffuse Detail,Reflective Bumped Unit,Reflective Bumped VertexLit=250
Bumped,Specular=300
Bumped Specular=400
Parallax=500
Parallax Specular=600
3,编译指令:
#progma surface Func Lambert 声明我们要写的一个表面Shader Func 指定了光照模型。
surface 声明一个表面着色器
Func 着色器方法的名字
Lambert 使用的光照模型。 Lambert 就是普通的diffuse 漫反射
4,sampler2D 和texture texture 加载后 储存在 sampler2D类型的对象中。 简单说就是sampler2D就是GLSL中得2D贴图类型。 相应还有sampler1D,sampler3D,samplerCube
我们每个shader 由两个独立的块组成,外面属性声明,回滚是使用Unity可以直接使用和编译的ShaderLab;而 里面的是 CGPROGRAM…. ENDCG 块,是CG程序。CG程序想访问Properties中所定义的变量的话,必须使用和之前变量名相同的名字的进行声明。 那么CG程序就可以访问这个变量了。
5,CG已经规定好了声明表面着色器方法的参数的类型和名字。就是:
第一个参数是一个Input结构。第二个参数是一个inout的SurfaceOutput 结构。
Input结构是需要我们去定义的结构,可以把所需要的参与计算的数据都放到这个Input结构中,传入surf 函数使用;
第二个SurfaceOutput 是已经定义好了的输出结构,但是一开始的时候内容是空白的,我们需要向里面填写输出,
这样就可以完成着色了。
6,unity中每个贴图变量之前都会加上uv_代表提取它的值是uv值,其实就是代表贴图上点的二维坐标。之后可以在surf程序中访问uv_MainText来获取这张贴图当前需要的点得坐标值了。
7,在计算输出的时候Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出。第二个参数是一个可写的SurfaceOutput,SurfaceOutput是预设定的输出结构,我们的surf函数的目标就是根据输入把这个结构填上。
SurfaceOutput结构如下:
struct SurfaceOutput{
half3 Albedo; //像素的颜色
half3 Normal; //像素的法向量
half3 Emission;//像素的发散颜色
half Specular;// 像素的镜面高光
half Gloss; //像素的发光强度
half Alpha; //像素的透明值
}
8,half4 c = tex2D (_MainTex, IN.uv_MainTex);
text2D函数:用来在一张贴图中对一个点进行采样的方法,返回float4,这里对_MainText上的点进行采样,并将其颜色的rgb值赋予了输出的像素颜色,将a值赋予了透明度。这样着色器 就可以,找到贴图上对应的uv点,直接使用颜色信息进行着色。