Unity Shader最重要的任务是指定各种着色器所需的代码。这些着色器代码可以写在SubShader语义块中(如:表面着色器),也可以写在Pass语义块中(如:顶点/片元着色器、固定函数着色器)。

    在Unity中,我们可以使用三种形式来编写Unity Shader,而不管使用哪种形式,真正意义上的Shader代码都需要包含在ShaderLab语义块中。



  • 表面着色器形式

 



  1. 表面着色器是Unity自己创建的一种着色器代码类型。它的代码量很少,Unity在背后做了很多工作,但渲染的代价比较大。
  2. 表面着色器是Unity对顶点、/片元着色器的更高一层的抽象。当给Unity提供一个表面着色器的时候,它在背面仍把该着色器转换成对应的顶点/片元着色器。
  3. 表面着色器被定义在SubShader语义块(不是Pass语义块)中CGPROGRAM和ENDCG之间。原因是,表面着色器不需要开发者关心使用多少个Pass、每个Pass如何渲染等问题,Unity会在背后为我们做好这些事情。
  4. CGPROGRAM和ENDCG之间的代码是使用CG/HLSL编写的,也就是说,我们需要把CG/HLSL语言嵌套在ShaderLab语言中。(注意:这里的CG/HLSL是经过Unity封装后提供的,某些地方不同于标准的CG/HLSL语法。)


  • 顶点/片元着色器形式




  1. 相比表面着色器更加复杂,但更加灵活,我们可以控制渲染的实现细节。
  2. 顶点/片元着色器代码块写在Pass语义块内。原因是,我们需要自己定义每个Pass需要使用的Shader代码。
  3. 顶点/片元着色器代码也是使用CG/HLSL编写的。




  • 固定函数着色器形式




  1. 之前两种Unity Shader形式都使用了可编程渲染。但对于一些较旧的设备,它们不支持可编程管线着色器,这时候就需要使用固定函数着色器来完成渲染,这种着色器只能实现一些简单的效果。
  2. 固定函数着色器代码被定义在Pass语义块中,这些代码相当于Pass中的一些渲染设置。
  3. 固定函数着色器代码需要完全使用ShaderLab的语法,而非使用CG/HLSL。
  4. 在Unity5.2中,所有固定函数着色器都会在背后被Unity编译成对立的顶点/片元着色器。因此,真正意义上的固定函数着色器已经不存在了。




  • 该选择哪种着色器
  1. 如果需要和各种光源打交道,使用表面着色器,但要注意它在移动平台上的性能表现。
  2. 如果光照数目非常少,可以使用顶点/片元着色器。
  3. 如果有很多自定义的渲染效果,使用顶点/片元着色器。
  4. 只有明确需要使用固定函数着色器(如在旧设备上运行游戏)时才使用固定函数着色器,否则使用另两个着色器。