解说Unity 3.x 着色器转换指南

2015年03月15日 15:30 0 点赞 0 评论 更新于 2025-11-21 17:10

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 名称来访问一些内置变量,例如模型视图投影矩阵。然而,这种方式在某些平台上是不可行的。所以,在 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。建议使用与 sampler2D 和 tex2D 类似的用法来替代 samplerRECT、texRECT。同时,如果正在进行任何特殊的 OpenGL 像素寻址操作,则需要从着色器中删除相关代码。例如,只保留非 OpenGL 部分(在着色器中寻找 SHADER_API_D3D9 或 SHADER_API_OPENGL 宏)。

作者信息

boke

boke

共发布了 3994 篇文章