解说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 名称来访问一些内置变量,例如模型视图投影矩阵。然而,这种方式在某些平台上是不可行的。所以,在 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 宏)。