Unity3D技术之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_MVPglstate.matrix.modelview[0]替换为UNITY_MATRIX_MVglstate.matrix.projection替换为UNITY_MATRIX_Pglstate.matrix.transpose.modelview[0]替换为UNITY_MATRIX_T_MVglstate.matrix.invtrans.modelview[0]替换为UNITY_MATRIX_IT_MVglstate.matrix.texture[0]替换为UNITY_MATRIX_TEXTURE0glstate.matrix.texture[1]替换为UNITY_MATRIX_TEXTURE1glstate.matrix.texture[2]替换为UNITY_MATRIX_TEXTURE2glstate.matrix.texture[3]替换为UNITY_MATRIX_TEXTURE3glstate.lightmodel.ambient替换为UNITY_LIGHTMODEL_AMBIENTglstate.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 宏)。