编写表面着色器

编写与光照交互的着色器是十分复杂的事情。有不同的光照类型、不同的阴影选项和不同的渲染路径(正向和延时渲染),着色器应以某种方法处理此种程度的复杂性。

Unity 的表面着色器 (Surface Shader) 是一种代码生成方法,用它来编写光照着色器比用低级的顶点/像素着色器程序容易得多。请注意,表面着色器 (Surface Shader) 中不包含自定义语言、魔法或忍者;它只会生成本应手写的所有重复代码。您仍要用 Cg/HLSL 语言来编写着色器代码。

相关的一些示例,请参阅表面着色器示例表面着色器自定义光照示例

工作原理

定义一个“表面函数”,此函数将您需要的任意 UV 或数据作为输入信息并填入输出结构 SurfaceOutput。SurfaceOutput 大体上描述了表面的属性(它的反射率颜色、法线、发射量、高光等)。您要用 Cg/HLSL 语言来编写此代码。

然后,表面着色器 (Surface Shader) 编译器会计算出需要什么输入信息以及填入了什么输出信息等,并生成实际的顶点和像素着色器以及渲染通道 (rendering pass) 来处理正向和延时渲染。

标准的表面着色器输出结构如下:

struct SurfaceOutput {
    half3 Albedo;
    half3 Normal;
    half3 Emission;
    half Specular;
    half Gloss;
    half Alpha;
};

样例

请参阅表面着色器示例表面着色器自定义光照示例表面着色器密铺页面。

表面着色器编译指令

表面着色器与其他任何着色器一样放置于 CGPROGRAM..ENDCG 块中。区别是:

#pragma surface 指令是:

    #pragma surface surfaceFunction lightModel [optionalparams]

所需参数:

Optional parameters:

此外,您还可以在 CGPROGRAM 块中编写 #pragma debug,然后表面编译器 (surface compiler) 将产生大量生成代码的注释。您可以在着色器检视器中使用开放的编译着色器 (Open Compiled Shader) 进行查看。

表面着色器输入结构

输入结构 Input 通常具有着色器所需的所有纹理坐标。纹理坐标必须被命名为纹理名称前加“uv”(或以“uv2”开头以使用第二纹理坐标集)。

其他能放入 Input 结构中的值:

表面着色器和 DirectX 11

目前表面着色器编译管线 (compilation pipeline) 的一些部分不理解 DirectX 11 HLSL 语法,因此如果是诸如 StructuredBuffers、 RWTextures 和其他非 DX9 语法等的 HLSL 功能,则您必须将它纳入仅特定于 DX11 的预处理器宏:有关详细信息,请参阅特定于平台的差异页面。

更多文档

Page last updated: 2013-06-28