ShaderLab 着色器不止包含“硬件着色器”。它们执行很多操作。它们描述了在材质检视面板中显示的属性,包含用于不同图形硬件的多个着色器实现,配置固定函数硬件状态,等等。实际的可编程着色器(如顶点和片元程序)只是整个 ShaderLab 的“着色器”概念的一部分。有关基本介绍,请查看着色器教程。在本文中,我们将低级别硬件着色器称为__着色器程序__。
如果要编写与光照交互的着色器,请查看表面着色器文档。如需查看一些示例,请参阅顶点和片元着色器示例。本页的其余部分假设着色器不与 Unity 光源(例如特殊效果、后期处理效果等等)交互。
着色器程序用 HLSL 语言编写,在着色器文本中嵌入“代码片段”(在 Pass 命令中的某个位置)。着色器程序通常如下所示:
Pass {
// ...常规通道状态设置 ...
CGPROGRAM
// 此代码片段的编译指令,例如:
#pragma vertex vert
#pragma fragment frag
// Cg/HLSL 代码本身
ENDCG
// ...通道设置的剩余部分 ...
}
HLSL 程序代码片段写入到 CGPROGRAM 和 ENDCG 关键字之间,或者 HLSLPROGRAM 和 ENDHLSL 之间。后一种形式不会自动包含 HLSLSupport 和 UnityShaderVariables 内置头文件。
在代码片段的开头,可使用 #pragma 语句的形式提供编译指令。以下指令可指示要编译的着色器函数:
其他编译指令:
每个代码片段必须至少包含一个顶点程序和一个片元程序。因此,#pragma vertex 和 #pragma fragment 指令是必需的。
从 Unity 5.0 开始不执行任何操作并且可以安全删除的编译指令:#pragma glsl
、#pragma glsl_no_auto_normalization
、#pragma profileoption
和 #pragma fragmentoption
。
Unity 仅支持着色器文件中的 #pragma 指令,而不支持 include 中的指令。
Unity 支持多种渲染 API(例如 Direct3D 11 和 OpenGL),默认情况下,所有着色器程序都编译到所有支持的渲染器中。您可以使用 #pragma only_renderers 或 #pragma exclude_renderers 指令指示要编译到的渲染器。如果您确信自己显式使用的一些着色器语言功能在某些平台上无法实现,这样做将非常有用。支持的渲染器名称包括:
例如,以下行仅会将着色器编译到 D3D11 模式:
#pragma only_renderers d3d11