Fork me on GitHub

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点,直接使用颜色信息进行着色。
posted @ 2015-01-03 15:38  Terry√  阅读(531)  评论(0编辑  收藏  举报