(Direct3D 11) 编译效果
创作效果后,下一步是编译代码以检查语法问题。
为此,可以调用 (D3DX11CompileFromFile、 D3DX11CompileFromMemory 或 D3DX11CompileFromResource ) 的编译 API 之一。 这些 API 调用编译 HLSL 代码fxc.exe效果编译器。 这就是效果中代码的语法非常类似于 HLSL 代码的原因。 (有几个异常稍后会在) 处理。 效果编译器/hlsl 编译器(fxc.exe)在实用工具文件夹的 SDK 中可用,因此可以选择脱机编译着色器 (或效果) 。 请参阅有关从命令行运行编译器的文档。
示例
下面是编译效果文件的示例。
WCHAR str[MAX_PATH];
DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );
hr = D3DX11CompileFromFile( str, NULL, NULL, pFunctionName, pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, NULL, &pBlob, &pErrorBlob, NULL );
包括
编译 API 的一个参数是 include 接口。 如果要在编译器读取包含文件时包含自定义行为,请生成其中之一。 编译器每次创建或编译使用 include 指针) 的效果 (时,都会执行此自定义行为。 若要实现自定义的 include 行为,请从 ID3DInclude 接口派生类。 这为类提供了两种方法: Open 和 Close。 在这些方法中实现自定义行为。
搜索“包含文件”
编译器在 pParentData 参数中传递给 include 处理程序的 Open 方法的指针可能不会指向包含编译器编译着色器代码所需的 #include 文件的容器。 也就是说,编译器可能会在 pParentData 中传递 NULL。 因此,建议 include 处理程序搜索其自己的包含位置列表以获取内容。 包含处理程序可以在调用其 Open 方法时接收这些位置时动态添加新的包含位置。
在以下示例中,假设着色器代码的包含文件都存储在 某处目录中 。 当编译器调用 include 处理程序的 Open 方法以打开和读取 somewhereelse\foo.h 的内容时,include 处理程序可以保存 某处 目录的位置。 稍后,当编译器调用 include 处理程序的 Open 方法来打开并读取 bar.h 的内容时,include 处理程序可以在 某个位置 目录中自动搜索 bar.h。
Main.hlsl:
#include "somewhereelse\foo.h"
Foo.h:
#include "bar.h"
宏
效果编译还可以使用指向在其他位置定义的宏的指针。 例如,假设你想要修改 BasicHLSL10 中的效果,以使用两个宏:零和一个。 此处显示了使用这两个宏的效果代码。
if( bAnimate )
vAnimatedPos += float4(vNormal, zero) *
(sin(g_fTime+5.5)+0.5)*5;
Output.Diffuse.a = one;
下面是两个宏的声明。
D3D10_SHADER_MACRO Shader_Macros[3] = { "zero", "0", "one", "1.0f", NULL, NULL };
宏是以 NULL 结尾的宏数组;其中,每个宏都是使用 D3D10_SHADER_MACRO 结构定义的。
修改编译效果调用以获取指向宏的指针。
D3DX11CompileFromFile( str, Shader_Macros, NULL, pFunctionName,
pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL,
NULL, &pBlob, &pErrorBlob, NULL );
HLSL 着色器标志
着色器标志指定 HLSL 编译器的着色器约束。 这些标志通过以下方式影响着色器编译器生成的代码:
- 优化代码大小。
- 包括调试信息,这会阻止流控制。
- 影响编译目标以及着色器是否可以在旧硬件上运行。
如果未指定两个冲突特征,则可以在逻辑上组合这些标志。 有关标志的列表,请参阅 D3D10_SHADER常量。
FX 标志
创建效果以定义编译行为或运行时效果行为时,请使用这些标志。 有关标志的列表,请参阅 常量D3D10_EFFECT。
检查错误
如果在编译过程中发生错误,API 将返回一个接口,其中包含来自效果编译器的错误。 此接口称为 ID3DBlob。 它不可直接读取:但是,通过返回指向包含数据 ((字符串) )的缓冲区的指针,可以看到任何编译错误。
此示例在 BasicHLSL.fx 中包含错误,第一个变量声明发生两次。
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
// Declare the same variable twice
float4 g_MaterialAmbientColor; // Material's ambient color
此错误会导致编译器返回以下错误,如 Microsoft Visual Studio 中“监视”窗口的以下屏幕截图所示。
由于编译器在 LPVOID 指针中返回错误,因此请将其强制转换为监视窗口中的字符串。
下面是从失败的编译返回错误的代码。
// Read the D3DX effect file
WCHAR str[MAX_PATH];
ID3DBlob* l_pBlob_Effect = NULL;
ID3DBlob* l_pBlob_Errors = NULL;
hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );
hr = D3DX11CompileFromFile( str, NULL, NULL, pFunctionName,
pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL,
NULL, &pBlob, &pErrorBlob, NULL );
LPVOID l_pError = NULL;
if( pErrorBlob )
{
l_pError = pErrorBlob->GetBufferPointer();
// then cast to a char* to see it in the locals window
}
相关主题