返回
Featured image of post Shader入门精要-UnityShader基础

Shader入门精要-UnityShader基础

笔记摘自书籍《Shader入门精要》

Unity 材质的创建

我们可以在Unity的菜单栏中选择Assets->Create->Material来创建。当创建了一个材质后,就可以把它赋给一个对象,将材质直接拖拽到Scene视图中的对象上。

Unity Shader的创建

我们可以在Unity的菜单栏中选择Assets->Create->Shader来创建。同时Unity给我们提供了4种Unity Shader模板来供我们选择。

  • Standard Surface Shader会产生一个包含了标准光照模型的表面着色器模板。
  • Unlit Shader则会产生一个不包含光照(但包含雾效)的基本的顶点/片元着色器。
  • Image Effect Shader则为我们实现各种屏幕后处理效果提供了一个基本模板。
  • Compute Shader会产生一种特殊的Shader文件,这类Shader利用GPU的并行性来进行一些与常规渲染流水线无关的计算。 ###Unity Shader的导入 在Project视图中选中某个Unity Shader即可看到该Shader的导入设置面版。

Default Maps可以指定该Unity Shader使用的默认纹理。 Surface shader是否是一个表面着色器。 Fixed function是否是一个固定函数着色器。 Compiled code下拉列表可以让开发者检查该Unity Shader针对不同图像编程接口(列如OpenGL、D3D9、D3D11等)最终编译成的Shader代码。 Render queue使用的渲染队列。 Disable batching是否关闭批处理。 Properties属性列表。

Shader Lab

Unity Shader是Unity为开发者提供的高级层渲染抽象层。Unity希望通过这种方式来让开发者更加轻松的控制渲染。在Unity中所有的Unity Shader都是使用ShaderLab来编写的。

Unity Shader的结构

1.Shader的起名

每个Unity Shader文件的第一行都需要通过Shader语义来指定该Unity Shader的名字。 当为材质选择使用的Unity Shader是,这些名称就会出现在材质面板的下拉列表里。

Shader "Custom/MyShader" {}

那么这个Unity Shader在材质面板中的位置就是 Shader->Custom->MyShader

2.Properties

Properties语义块中包含了一系列的属性,这些属性将会出现在材质面板中。

 Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}

在Unity中这些属性名字通常由一个下划线开始。显示的名称会出现在材质面板上。我们需要指定每个属性的类型。除此之外,我们还需要给每个属性指定一个默认值,我们第一次把这个Unity Shader赋给某个材质是,材质面板上显示的就是这些默认值。

Shader "Unity Shaders Book/Chapter 3/MyShader" {
	Properties {
		// Numbers and Sliders
		_Int ("Int", Int) = 2
		_Float ("Float", Float) = 1.5
		_Range("Range", Range(0.0, 5.0)) = 3.0
		// Colors and Vectors
		_Color ("Color", Color) = (1,1,1,1)
		_Vector ("Vector", Vector) = (2, 3, 6, 1)
		// Textures
		_2D ("2D", 2D) = "" {}
		_Cube ("Cube", Cube) = "white" {}
		_3D ("3D", 3D) = "black" {}
	}

3.SubShader

SubShader中定义了一系列的Pass以及可以选的状态标签设置。每个Pass定义了一次完整的渲染流程。

  • 状态设置 Shader Lab提供了一系列渲染状态的设置指令。当在SubShader块中设置了渲染状态时,将会应用到所有的Pass,如果我们希望这样,可以在Pass语义块中单独的进行设置。

  • SubShader的标签 SubShader的标签是一个键值对,他的键和值都是字符串类型。它们用来告诉Unity的渲染引擎:SubShader我希望怎样以及何时渲染这个对象。

  • Pass语义块
Pass{
  [Name]
  [Tags]
  [RenderSetup]
  //Other code
}

首先,我们可以在Pass中定义该Pass的名称

Name "MyPassName"

通过这个名字,我们可以使用Shader Lab的UsePass来直接使用其他的Unity Shader中的Pass来提高代码的复用性。在Unity内部会把所有的Pass名称转换为大写字母,所以使用UsePass必须使用大写形式的名字。

UsePass "MyShader/MYPASSNAME"

我们也可以对Pass设置渲染状态,SubShader的渲染状态同样适用于Pass。在Pass中我们还可以使用固定渲染管线着色器。 Pass同样可以设置标签,但是它不同于SubShader的标签,这些标签适用于告诉渲染引擎我们希望如何来渲染物体。

4.Fallback

Fallback用于告诉Unity,“如果上面的所有SubShader在这块显卡上都不能运行,那么就用这个最低级的Shader吧!”

Fallback "Name"
//或者关闭
Fallback off

###Unity Shader的形式 在Unity中,我们可以使用下面三种形式来编写Unity Shader。

Shader "MyShader"
  ProPerties{
    //各种所需的属性
  }
  SubShader{
    //真正意义上的Shader代码
    //表面着色器(Surface Shader)或者
    //顶点/片元着色器(Vertex/Fragment Shader)或者
    //固定函数着色器(Fixed Function Shader)
  }
  SubShader{
    //和上一个一样
  }
}
  • 表面着色器 表面着色器是Unity自己创造的一种着色器代码类型,但它在背后仍旧要转换成对应的顶点/片元着色器。它存在的价值在于Unity帮我们处理了很多光照细节,让我们不用心焦这些琐事。

从代码中可以看出表面着色器被定义在SubShader语义块内(非Pass语义块)的CGPROFGAMENDCG中,CGPROFGAMENDCG中的代码时使用CG/HLSL来编写的。。

  • 顶点/片元着色器

和表面着色器类似,顶点/片元着色器的代码也需要定义在CGPROFGAMENDCG中,不同的是,顶点/片元着色器是写在Pass语义块内,而非SubShader内。

  • 固定函数着色器 上面的两种Unity Shader形式都使用了可编程管线,而对一些比较老旧的设备,其GPU支持DirectX 7.0或OpenGL 1.5或OpenGL ES1.1),这时候我们就需要使用固定函数着色器来完成渲染,这些着色器往往只能完成一些非常简单的效果。固定函数着色器是定义在Pass语义块中的,且不需要定义在CGPROFGAMENDCG中,完全使用Shader Lab的语法。

  • 选择哪种Shader形式 1.如果与各种光源打交道,可以使用表面着色器,但需要担心它在移动平台的表现。 2.如果光照数目非常少,或者需要自定义很多渲染效果,那么请选择顶点/片元着色器。