在 Direct3D 9 中使用着色器

编译特定硬件的着色器

着色器首次添加到 DirectX 8.0 中的 Microsoft DirectX。 当时,定义了多个虚拟着色器计算机,每个虚拟机大致对应于顶级 3D 图形供应商生产的特定图形处理器。 对于每个虚拟着色器计算机,都设计了一种汇编语言。 编写到着色器模型的程序 (名称vs_1_1和ps_1_1 - ps_1_4) 相对较短,通常由开发人员直接使用适当的汇编语言编写。 应用程序将使用 D3DXAssembleShader 将此可读的汇编语言代码传递到 D3DX 库,并获取着色器的二进制表示形式,而着色器又使用 CreateVertexShaderCreatePixelShader 传递。 有关详细信息,请参阅软件开发工具包 (SDK) 。

Direct3D 9 中的情况与此类似。 应用程序使用 D3DXCompileShader 将 HLSL 着色器传递到 D3DX ,并获取已编译着色器的二进制表示形式,后者又使用 CreatePixelShaderCreateVertexShader 传递到 Microsoft Direct3D。 运行时不知道有关 HLSL 的任何信息,只知道二进制程序集着色器模型。 这很好,因为这意味着 HLSL 编译器可以独立于 Direct3D 运行时进行更新。 还可以使用 fxc 脱机编译着色器。

除了开发 HLSL 编译器外,Direct3D 9 还引入了程序集级着色器模型,以公开最新一代图形硬件的功能。 应用程序开发人员可以在 (vs_2_0、vs_3_0、ps_2_0 ps_3_0) 这些新模型的程序集中工作,但我们希望大多数开发人员迁移到 HLSL 进行着色器开发。

当然,编写 HLSL 程序来表达特定着色算法的功能不会自动使其在任何给定硬件上运行。 应用程序调用 D3DX 以使用 D3DXCompileShader 将着色器编译为二进制程序集代码。 此入口点的限制之一是一个参数,该参数定义 HLSL 编译器应使用哪个程序集级模型 (或编译目标) 来表达最终着色器代码。 如果应用程序在运行时执行 HLSL 着色器编译 (而不是编译时间或脱机) ,则应用程序可以检查 Direct3D 设备的功能,并选择要匹配的编译目标。 如果 HLSL 着色器中表示的算法过于复杂,无法在所选编译目标上执行,编译将失败。 这意味着,虽然 HLSL 是着色器开发的巨大优势,但它并不能使开发人员摆脱将游戏交付给具有不同功能图形设备的目标受众的现实。 作为游戏开发人员,你仍必须管理视觉对象的分层方法;这意味着为更强大的图形卡编写更好的着色器,并为旧卡编写更多基本版本。 但是,通过编写良好的 HLSL,可以显著减轻这种负担。

许多开发人员选择在交付之前将着色器从 HLSL 编译为二进制程序集代码,而不是在应用程序加载时或首次使用时在客户的计算机上使用 D3DX 编译 HLSL 着色器。 这使他们的 HLSL 源代码远离窥探,并确保其应用程序运行的所有着色器都经过其内部质量保证过程。 用于脱机编译着色器的一个方便实用工具是 fxc。 此工具有许多选项可用于编译指定编译目标的代码。 如果要优化着色器,或者只是大致了解虚拟着色器计算机在更详细级别的功能,那么在开发过程中研究反汇编的输出可能非常具有教育意义。 下面汇总了这些选项:

初始化着色器常量

着色器常量包含在常量表中。 这可以通过 ID3DXConstantTable 接口进行访问。 全局着色器变量可以在着色器代码中初始化。 这些在运行时通过调用 SetDefaults 进行初始化。

将着色器参数绑定到特定寄存器

编译器会自动将寄存器分配给全局变量。 编译器会将 Environment 分配给采样器寄存器 s0,SparkleNoise 分配给采样器寄存器 s1,将k_s分配给常量寄存器 c0 (假设尚未为以下三个全局变量分配其他采样器或常量寄存器) :

sampler Environment;
sampler SparkleNoise;
float4 k_s;

还可以将变量绑定到特定寄存器。 若要强制编译器分配给特定寄存器,请使用以下语法:

register(RegisterName)

其中 RegisterName 是特定寄存器的名称。 以下示例演示了特定的寄存器分配语法,其中采样器环境将绑定到采样器寄存器 s1,SparkleNoise 将绑定到采样器寄存器 s0,k_s将绑定到常量寄存器 c12:

sampler Environment : register(s1);
sampler SparkleNoise : register(s0);
float4 k_s : register(c12);

呈现可编程着色器

着色器通过设置设备中的当前着色器、初始化着色器常量、告知设备不同输入数据来自何处,最后呈现基元来呈现着色器。 可以通过分别调用以下方法来实现上述每一项:

调试着色器

Microsoft Visual Studio .NET 的 DirectX 扩展在 Visual Studio .NET 集成开发环境 (IDE) 中提供完全集成的 HLSL 调试器。 若要准备着色器调试,必须在计算机上安装正确的工具, (请参阅 在 Visual Studio (Direct3D 9) ) 中调试着色器

HLSL 编程指南