Version: 2019.2
支持 DX11/OpenGL Core 曲面细分的表面着色器
顶点和片元着色器示例

编写顶点和片元着色器

ShaderLab 着色器不止包含“硬件着色器”。它们执行很多操作。它们描述了在材质检视面板中显示的属性,包含用于不同图形硬件的多个着色器实现,配置固定函数硬件状态,等等。实际的可编程着色器(如顶点和片元程序)只是整个 ShaderLab 的“着色器”概念的一部分。有关基本介绍,请查看着色器教程。在本文中,我们将低级别硬件着色器称为__着色器程序__。

如果要编写与光照交互的着色器,请查看表面着色器文档。如需查看一些示例,请参阅顶点和片元着色器示例。本页的其余部分假设着色器不与 Unity 光源(例如特殊效果、后期处理效果等等)交互。

着色器程序用 HLSL 语言编写,在着色器文本中嵌入“代码片段”(在 Pass 命令中的某个位置)。着色器程序通常如下所示:

  Pass {
        // ...常规通道状态设置 ...
      
        CGPROGRAM
        // 此代码片段的编译指令,例如:
        #pragma vertex vert
        #pragma fragment frag
      
        // Cg/HLSL 代码本身
      
        ENDCG
        // ...通道设置的剩余部分 ...
    }

HLSL 代码片段

HLSL 程序代码片段写入到 CGPROGRAMENDCG 关键字之间,或者 HLSLPROGRAMENDHLSL 之间。后一种形式不会自动包含 HLSLSupport 和 UnityShaderVariables 内置头文件

在代码片段的开头,可使用 #pragma 语句的形式提供编译指令。以下指令可指示要编译的着色器函数:

  • #pragma vertex name - 作为顶点着色器来编译函数 name
  • #pragma fragment name - 作为片元着色器来编译函数 name
  • #pragma geometry name - 作为 DX10 几何着色器来编译函数 name。如下所述,设置此选项会自动开启 #pragma target 4.0
  • #pragma hull name - 作为 DX11 外壳着色器来编译函数 name。如下所述,设置此选项会自动开启 #pragma target 5.0
  • #pragma domain name - 作为 DX11 域着色器来编译函数 name。如下所述,设置此选项会自动开启 #pragma target 5.0

其他编译指令:

  • #pragma target name - 要编译到的着色器目标。有关详细信息,请参阅着色器编译目标页面。
  • #pragma require feature …- 对着色器需要的 GPU 功能进行精细控制,请参阅着色器编译目标页面以了解详细信息。
  • #pragma only_renderers 空格分隔的名称 - 仅为给定的渲染器编译着色器。默认情况下,将为所有渲染器编译着色器。请参阅下文中的_渲染器_以了解详细信息。
  • #pragma exclude_renderers 空格分隔的名称 - 不为给定渲染器编译着色器。默认情况下,将为所有渲染器编译着色器。请参阅下文中的_渲染器_以了解详细信息。
  • #pragma multi_compile … - for working with multiple shader variants. Unused variants of multi_compile shaders are included in the game build.
  • #pragma multi_compile_local … - similar to multi_compile, but enumerated keywords are local. See Making multiple shader program variants: Keyword limits for more information.
  • #pragma shader_feature … - for working with multiple shader variants. Unused variants of shader_feature shaders are not included in the game build.
  • #pragma shader_feature_local … - similar to shader_feature, but enumerated keywords are local. See Making multiple shader program variants: Keyword limits for more information.
  • #pragma enable_d3d11_debug_symbols - 为针对 DirectX 11 编译的着色器生成调试信息,这将允许您通过 Visual Studio 2012(或更高版本)图形调试器来调试着色器。
  • #pragma hardware_tier_variants 渲染器名称 - 为每个可以运行所选渲染器的硬件层生成每个编译着色器的多个着色器硬件变体。请参阅下文中的_渲染器_以了解详细信息。
  • #pragma hlslcc_bytecode_disassembly - embed disassembled HLSLcc bytecode into translated shader.
  • #pragma disable_fastmath - enables precise IEEE 754 rules, mostly involving NaN handling (currently only affects Metal platform).
  • #pragma glsl_es2 - When set in a GLSL shader, generate a GLSL ES 1.0(OpenGL ES 2.0), even when the shader target is OpenGL ES 3.
  • #pragma editor_sync_compilation - Force synchronous compilation (affects Editor only).

每个代码片段必须至少包含一个顶点程序和一个片元程序。因此,#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 - Direct3D 11/12
  • glcore - OpenGL 3.x/4.x
  • gles - OpenGL ES 2.0
  • gles3 - OpenGL ES 3.x
  • metal - iOS/Mac Metal
  • vulkan - Vulkan
  • d3d11_9x - Direct3D 11 9.x 功能级别,通常在 WSA 平台上使用
  • xboxone - Xbox One
  • ps4 - PlayStation 4
  • n3ds - Nintendo 3DS
  • wiiu - Nintendo Wii U

例如,以下行仅会将着色器编译到 D3D11 模式:

#pragma only_renderers d3d11

另请参阅


  • 2018–03–20 页面已修订
  • 在 Unity 2018.1 中添加了着色器 #pragma 指令
支持 DX11/OpenGL Core 曲面细分的表面着色器
顶点和片元着色器示例