一、ShaderLab

Shader Lab是Unity提供的编写 Unity Shader 的一种说明性语言。

从设计上来说,Shader Lab类似与CgFX和Direct3D Effects(.FX)语言,他们都定义了要显示一个材质所需的所有东西,而不仅仅是着色器代码。

Shader "ShaderName"{
  Properties{
         //属性
  }
  SubShader{
       //显卡A使用的子着色器  
  }
  SubShader{
      //显卡B使用的子着色器
  }
  Fallback "VertexLit"
}

  二、Unity Shader的结构

(1)Properties

Properties{
     Name ("DisplayName",PropertiesType)=DefaultValue
     Name ("DisplayName",PropertiesType)=DefaultValue
     //更多属性
}

Properties语义块支持的属性类型

属性类型

默认值的定义语法

例子

Int

number

_Int("Int",Int)=2

Float

number

_Float("Float",Float)=1.5

Range(min,max)

number

_Range("Range",Range(0.0,5.0))=3.0

Color

(num,num,num,num)

_Color("Color",Color)=(1,1,1,1)

Vector

(num,num,num,num)

_Vector("Vector",Vector)=(2,3,4,5)

2D

"defaulttexture"{}

_2D("2D",2D)=""{}

Cube

"defaulttexture"{}

_Cube("Cube",Cube)="white"{}

3D

"defaulttexture"{}

_3D("3D",3D)="back"{}

 

 

 

 

 

 

 

 

 

 

属性类型的例子:

Shader"Custom/ShaderLabProperties"{
   Properties{
       //Number and Sliders
      _Int("Int",Int)=2
      _Float("Float",Float)=1.0
      _Range("Range",Rnage(1.0,2.0))=1.5
      //Colors and Vectors
      _Color("Color",Color)=(1,1,1,1)
      _Vector("Vector",Vector)=(1,2,3,4)
      //Texctures
      _2D("2D",2D)=""{}
      _Cube("Cube",Cube)="white"{}
      _3D("3D",3D)="black"{}
   }
   FallBack "Diffuse"
}

(2)SubShader

SubShader{
  //可选的
  [Tags]

  //可选的
  [RenderSetup]

  Pass{
   
  }
  //Other Passes
}

每一个Pass定义了一次完整的渲染流程,但如果Pass的数目过多,往往会造成渲染性能的下降。

SubShader 和 Pass 中的标签设置不一样,但状态设置的语法是相同的。

SubShader 进行的设置会应用到所有的Pass。

状态设置

常见的渲染状态设置选项

状态名称

设置指令

解释

Cull

Cull Back|Front|Off

设置剔除模式:剔除背面/正面/关闭剔除

ZTest

ZTest Less Greater|LEqual|GEqual|Equal|NotEqual|Always

设置深度测试时使用的函数

ZWrite

ZWrite On|Off

 开启/关闭深度写入

Blend

Blend Off|SrcFactor DstFactor

关闭/开启设置混合模式

 

 

 

 

 

 

SubShader的标签

SubShader 的标签(Tags)是一个键值对(Key/Value Pair),它的键和值都是字符串类型。这些键值对是SubShader和渲染引擎之间的沟通桥梁。

Tags{ "TagName 1" = "Value1" "TagName 2" = "Value2" }

SubShader的标签类型

标签类型

说明

例子

Queue

控制渲染顺序,指定该物体属于哪一个渲染队列。

这种方式可以保证所有的透明物体可以在不透明物体后渲染。

也可自定义渲染顺序。

Tags{ "Queue" = "Transparent"}

RenderType

对着色器进行分类。

例如这是一个不透明着色器 或 是一个透明着色器等。

可被用于着色器替换(ShaderReplacement)功能。

Tags{ "RenderType" = "Opaque"}

DisableBatching

一些SubShader在使用批处理时会出现问题。

例如:使用模型空间下的坐标进行顶点动画。

这时可以通过该标签直接指明是否对该SubShader使用批处理。

Tags{ "DisableBatching" = "True"}

ForceNoShadowCasting

控制使用该SubShader的物体是否会投射阴影

Tags{ "ForceNoShadowCasting" = "True"}

IgnoreProjector

如果该标签为“True”,

那么使用该SubShader的物体不会受Projector的影响。

通常用于透明物体

Tags{"IgnoreProjector" = "True"}

CanUseSpriteAtlas

当该SubShader是用于精灵(sprites)时,将该标签设为“False”

Tags{ "CanUseSpriteAtlas" = "False"}

PreviewType

指明材质面板将如何预览该材质。

默认为球形,可设为“Plane” “SkyBox”

Tags{ "PreviewType" = "Plane"}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Pass语义块

Pass{
   [Name]
   [Tags]
   [RenderSetup]
//Other code
}

可以在Pass中定义该Pass的名称,如:

Name "MyPassName"

通过这个名称,可以使用Shader Lab的Use Pass命令来直接使用其他Unity Shader中的Pass。

UsePass "MyShader/MYPASSNAME"
   
   //Unity内部会把所有Pass的名称转换成大写字母
   //使用UsePass命令时,Pass名字必须大写

Pass中还可以使用固定管线的着色器命令。

Pass的标签也是用于告诉渲染引擎怎么来渲染该物体。

Pass的标签类型

标签类型

说明

例子

LightMode

定义该Pass在Unity的渲染流水线中的角色

Tags{ "LightMode" = "ForwardBase"}

RequireOptions

用于指定当满足某些条件时渲染该Pass,它的值是一个由空格分隔的字符串。

目前支持的选项有:SoftVegectation

Tags{ "RequireOptions" = "SoftVegetation"}

 

 

 

 

 

UnityShader还支持一些特殊的Pass,以便进行代码复用 或 实现更复杂的效果。

Use Pass:复用其他Unity Shader中的Pass

Grab Pass:该Pass负责抓取屏幕并将结果存储在一张纹理中,以用于后续的Pass处理。

(3)FallBack

Fallback "name"
//或者
Fallback Off

Fallback还会影响阴影的投射。

Fallback使用的内置Shader中包含了一个通用的阴影投射的Pass。

正确设置Fallback也非常重要。

三、UnityShader的形式

着色器代码写在SubShader语义块中是表面着色器的做法,写在Pass语义块中,是顶点/片元着色器和固定函数着色器的做法。

Shader "MyShader" {
   Properties{
     //所需的各种属性
   }
   SubShader{
     //真正意义上的Shader代码会出现在这里
     //表面着色(Surface Shader)或者
     //顶点/片元着色器(Vertex/Fragment Shader)或者
     //固定函数着色器(Fixed Function Shader)
   }
   SubShader{
     //和上一个SubShader类似
   }
}

(1)表面着色器(Surface Shader)

表面着色器是Unity自己创造的一种着色器代码类型。

代码量很少,但渲染代价很大。

在背后仍旧把它转换成对应的顶点/片元着色器。

它存在的价值在于,为我们处理了很多光照细节。

Shader "Custom/Simple Surface Shader"{
  SubShader{
     Tags{ "RenderType" = "Opaque"}
     CGPROGRAM
     #pragma surface surf Lambert
     struct Input{
         float4 color:COLOP;
     };
     void surf (Input IN, inout SurfaceOutput o ){
         o.Albedo = 1;
     }
     ENDCG
  }
  Fallback "Diffuse"
}

CGPROGRAM 和 ENDCG 之间的代码是使用 CG/HLSL 编写的

(2)顶点/片元着色器(Vertex/Fragment Shader)

灵活性高,可控制渲染细节。

Shader "Custom/Simple VertecFragment Shader"{
   SubShader{
       Pass{
         CGPROGRAM
         
         #pragma vertex vert
         #peagma fragment farag

         float4 vert(float4 v : POSITION) : SV_POSITION{
            return mul (UNITY_MATRIX_MVP, v );
         }
      
         float4 frag() : SV_Target {
            return fixed4(1.0,0..0,0.0,1.0);
         }

         ENDCG
       }
   }
}

(3)固定函数着色器(Fixed Function Shader)

不支持可编程管线着色器,就需要使用固定函数着色器来完成渲染。

Shader "Tutorial/Basic" {
   Properties {
      _Color ("Main Color",Color) = (1,0.5,0.5,1)
   }
   SubShader {
      Pass {
        Material {
           Diffuse [_Color]
        }
        Lighting On
      }
   }
}

(4)选择哪种UnityShader形式

  • 和各种光源打交道,选表面着色器。
  • 光源数目比较少,有很多自定义渲染效果的,选顶点/片元着色器。