编写顶点和片元着色器
ShaderLab 着色器不仅仅包括“硬件着色器”。这些着色器做很多事情。它们描述在材质检视器 (Material Inspector) 中显示的属性,容纳用于不同图形硬件的多种着色器实现,配置固定函数硬件状态等等。实际可编程着色器 - 如顶点和片元程序 - 只是整个 ShaderLab“着色器”概念的一部分。请查看着色器教程中的基本简介。在这里,我们将调用低级硬件着色器着色器程序。
如果您想编写与光照交互的着色器,请查看表面着色器文档。本页剩余部分将假设着色器不与 Unity 光照交互(例如:特殊效果、Image Effects|图像效果等。)
着色器程序的编写采用 Cg/HLSL 语言,是通过在着色器文本中 Pass 命令内的某处嵌入“代码片段”的来实现的。它们通常看起来像这样:
Pass { // ...常用的通道状态设置... CGPROGRAM // 该代码片段的编译指令,例如: #pragma vertex vert #pragma fragment frag // Cg 代码自身 ENDCG // ...通道设置的剩余部分... }
Cg 代码片段
Cg 程序代码片段被编写在 CGPROGRAM 和 ENDCG 之间。
在代码片段编译指令的开头,可以使用 #pragma 指令。指示编译哪些着色器函数的编译指令:
#pragma vertex 名称 - 将函数名称编译为顶点着色器。
#pragma fragment 名称 - 将函数名称编译为片元着色器。
#pragma geometry 名称 - 将函数名称编译为 DX10 几何结构着色器。要使这个选项自动打开 #pragma target 4.0,请参阅下文。
#pragma hull 名称 - 将函数名称编译为 DX11 外壳着色器。要使这个选项自动打开 #pragma target 5.0,请参阅下文。
#pragma domain 名称 - 将函数名称编译为 DX11 域着色器。要使这个选项自动打开 #pragma target 5.0,请参阅下文。
其他编译指令:
#pragma target 名称 - 要编译成哪个着色器目标。有关详细信息,请参阅着色器目标。
#pragma only_renderers 空格隔开的名称 - 仅为给定渲染器编译着色器。默认情况下,为所有渲染器编译着色器。有关详细信息,请参阅渲染器。
#pragma exclude_renderers 空格隔开的名称 - 不仅为给定渲染器编译着色器。默认情况下,为所有渲染器编译着色器。有关详细信息,请参阅渲染器。
#pragma glsl - 为桌面 OpenGL 平台编译着色器时,将 Cg/HLSL 转换成 GLSL (而不是默认设置,即 ARB 顶点/片元程序)。使用此指令可启用导数指令 (derivative instruction)、具有明确 LOD 等级的纹理采样等。
#pragma glsl_no_auto_normalization - 为移动 GLSL (iOS/Android) 编译着色器时,关闭法线和切线向量的自动规范化性能。默认情况下,法线和切线是在 iOS/Android 平台上的顶点着色器中被规范化的。
#pragma fragmentoption 选项 - 添加选项到已编译的 OpenGL 片元程序。有关允许使用的选项的列表,请参阅 ARB 片元程序详述。该指令对顶点程序或被编译成非 OpenGL 目标的程序无影响。
每个代码片段都必须包含一个顶点程序或一个片元程序或两者皆包含。因此,要求使用一个 #pragma vertex 指令或一个 #pragma fragment 指令或两者都使用。
着色器目标
默认情况下,Unity 将着色器编译为简约 Shader Model 2.0 的相等物。使用 #pragma target 可使着色器被编译成其他能力等级。当前支持以下目标:
#pragma target 2.0 (默认) - 简约 Shader Model 2.0
Direct3D 9 上的 Shader Model 2.0。
具有 256 位指令限制的ARB_vertex_program、具有 96 位指令限制(32 位纹理 + 64 位算法)的 ARB_fragment_program、16 个临时寄存器 (temporary register) 和 4 个纹理间接 (texture indirection)。
#pragma target 3.0 - 编译成 Shader Model 3.0:
Direct3D 9 上的 Shader Model 3.0。
无指令限制的 ARB_vertex_program、具有 1024 位指令限制(512 位纹理 + 512 位算法)的 ARB_fragment_program、32 个临时寄存器 (temporary register) 和 4 个纹理间接 (texture indirection)。可使用 #pragma profileoption 指令覆盖这些限制。例如:
#pragma profileoption MaxTexIndirections=256
将纹理间接限制增加到 256 个。请注意,一些 Shader Model 3.0 功能(如导数指令)是不受 ARB_vertex_program/ARB_fragment_program 支持的。您可以使用 #pragma glsl 转换成限制较少的 GLSL 来代替。
#pragma target 4.0 - 编译成 DX10 Shader Model 4.0。当前只有 DirectX 11 渲染器支持该目标。
#pragma target 5.0 - 编译成 DX11 Shader Model 5.0。当前只有 DirectX 11 渲染器支持该目标。
渲染平台
Unity 支持几个渲染 API(例如,Direct3D 9 和 OpenGL),默认情况下,所有着色器程序都编译成受支持的渲染器。使用 #pragma only_renderers 或 #pragma exclude_renderers 指令,您可以指示编译成哪些渲染器。如果您知道您将只把 Mac OS X (无 Direct3D)或 Windows(Unity 默认为 D3D)作为目标,或者如果某个特定着色器只在一个渲染器中可用,而在其他渲染器中不可用,这样是有用的。当前受支持的渲染器名称有:
d3d9 - Direct3D 9.
d3d11 - Direct3D 11.
opengl - OpenGL.
gles - OpenGL ES 2.0.
xbox360 - Xbox 360.
ps3 - PlayStation 3.
flash - Flash.
例如,以下这行指令只会将着色器编译为 D3D9 模式:
#pragma only_renderers d3d9
小节
在 Cg 中访问着色器属性
提供 顶点数据给顶点程序
内置着色器包含文件
预定义着色器预处理宏
Built-in state variables in shader programs
GLSL 着色器程序