Unity 3.x 着色器转换指南

Unity 3 的渲染系统有许多新功能和变更之处,ShaderLab 也进行了相应更新。Unity 2.x 中使用的一些高级着色器,特别是使用逐像素照明的着色器需要更新到 Unity 3。如果出现更新问题,欢迎向我们寻求帮助!

在 Unity 3.x 中打开 Unity 2.x 工程时,会尽量自动升级着色器文件。下列文件列出了着色器的所有更改,及需要手动升级着色器时的做法。

逐像素照明着色器

在 Unity 2.x 中,编写照亮每个像素的着色器非常复杂。这些着色器有多个通道,每个都带 LightMode 标签(一般为 PixelOrNone、Vertex 和 Pixel)。在 Unity 3.0 中添加 延迟照明 (Deferred Lighting) 并对旧的向前渲染进行更改之后,我们需要一个更简单、更强大且面向未来的着色器编写方法,该着色器与灯光互动。所有旧的逐像素照明着色器都需要重写为表面 着色器 (Surface Shaders)。

Cg 着色器更改

内置 “glstate” 变量重命名

在 Unity 2.x 中,可通过 glstate.matrix.mvp 等内置 Cg 名称访问一些内置变量(如模型*view*投影矩阵)。但是,这在某些平台上是不可行的,因而在 Unity 3.0 中,我们重命名了这些内置变量。升级工程时所有这些替换工作将自动完成:

  • glstate.matrix.mvp 替换为 UNITY_MATRIX_MVP
  • glstate.matrix.modelview[0] 替换为 UNITY_MATRIX_MV
  • glstate.matrix.projection 替换为 UNITY_MATRIX_P
  • glstate.matrix.transpose.modelview[0] 替换为 UNITY_MATRIX_T_MV
  • glstate.matrix.invtrans.modelview[0] 替换为 UNITY_MATRIX_IT_MV
  • glstate.matrix.texture[0] 替换为 UNITY_MATRIX_TEXTURE0
  • glstate.matrix.texture[1] 替换为 UNITY_MATRIX_TEXTURE1
  • glstate.matrix.texture[2] 替换为 UNITY_MATRIX_TEXTURE2
  • glstate.matrix.texture[3] 替换为 UNITY_MATRIX_TEXTURE3
  • glstate.lightmodel.ambient 替换为 UNITY_LIGHTMODEL_AMBIENT
  • glstate.matrix.texture 替换为 UNITY_MATRIX_TEXTURE

语义变化

此外,对于顶点至片段 (vertex-to-fragment) 结构的位置 (position) 语义,建议使用 SV_POSITION(而不是 POSITION)。

更严格的错误检查

根据平台不同,可能使用 Cg 之外的其他编译器(如 Windows 中的 HLSL)来编译着色器,这些编译器的错误检查更严格。最常见的情况是:

  • 所有顶点/片段着色器输入和输出需要有指定的“语义 (semantics)”。Unity 2.x 允许不指定任何语义(在这种情况下,将使用一些 TEXCOORD),而在Unity 3.0 中,语义是必需的。
  • 需要写入所有着色器的输出变量。例如,如有 float4 color:COLOR 作为顶点着色器输出,就不能只写入 rgb,却让 alpha 未初始化。

其他更改

去除 RECT 纹理

在 Unity 2.x 中,RenderTextures 可以不是二次幂尺寸,因而被称为 “RECT” 纹理。它们在着色器属性中由 “RECT” 纹理类型进行指定,在 Cg 着色器中用作 samplerRECT、texRECT 等。RECT 纹理的坐标是 OpenGL 中的一个特例:以像素为单位。在所有其他平台上,纹理坐标同任何其他纹理一样:纹理从 0.0 至 1.0。

我们决定在 Unity 3.0 中去除这个 OpenGL 特例,并同等对待非二次幂 RenderTextures。建议替代 samplerRECT、texRECT 及常规的 sampler2D 和 tex2D 类似用法。同时,如果正在进行任何特殊的 OpenGL 像素寻址,则需要从着色器中删除。比如只保留非 OpenGL 部分(在着色器中寻找 SHADER_API_D3D9 或 SHADER_API_OPENGL 宏)。