Direct3D中的Shader是这样的:
1. ASM Shader是最元老的也是DX8主要使用Shader
2. fxc编译器可以同时编译ASM,HLSL和fx脚本,其中HLSL和fx可以查看编译后的GPU汇编代码
3. D3D9中,fx是HLSL的一种渲染脚本,简化了HLSL设置及常量绑定,并且附带RenderStateBlock及设置
但只能用于制作简单的Shader
4. DirectXSDK中有一个概念混淆:C++例子中的BasicHLSL使用的其实还是fx,HLSLwithoutEffects例子才是真正的纯HLSL
5.fx与HLSL程序鉴别:
使用fx程序必定含有:D3DXCreateEffectXXX 系列函数, ID3DXEffect对象,渲染中能看到SetTechnique,BeginPass,EndPass之类的字眼
使用纯HLSL程序含有:D3DXCompileShader,ID3DXConstantTable对象,GetConstantByName,GetConstantDesc之类的字眼
6. 在fx中包含有 VertexShader,PixelShader代码及profile,entry,RenderState设置及简单的绘制过程(pass)。一次编译后,VS,PS,Texture,Sampler及常量都是在ID3DXEffect对象中自动完成,无需手动设置。
7. HLSL可以将VS及PS代码写入1个.hlsl文件。注意,以下这种代码可以在HLSL中编译过,但实际没有任何效果
1: sampler_state
2: {
3: Texture = <tex>;
4: MipFilter = LINEAR;
5: MinFilter = LINEAR;
6: MagFilter = LINEAR;
7: };
这点可以参考AMD RenderMonkey中只在shader中使用sampler而忽略texture。
8. fx中往shader设置纹理使用的是ID3DXBaseEffect::SetTexture下的这个函数
1: HRESULT SetTexture(
2: D3DXHANDLE hParameter,
3: LPDIRECT3DBASETEXTURE9 pTexture
4: );
但是在HLSL中,这点就变得很麻烦,需要手动设置,可以参考这篇文章
Shader代码片段:
1: sampler Samp0 = sampler_state
2: {
3: Texture = <Tex0>;
4: MipFilter = LINEAR;
5: MinFilter = LINEAR;
6: MagFilter = LINEAR;
7: };
编译HLSL代码后得到ConstantTable,然后取出句柄:
1: ScalarHandle = pixelConstTable->GetConstantByName(0, "Scalar");
2:
3: Samp0Handle = pixelConstTable->GetConstantByName(0, "Samp0");
4:
5: Samp1Handle = pixelConstTable->GetConstantByName(0, "Samp1");
再从句柄取出symbol的描述:
1: UINT count;
2:
3: pixelConstTable->GetConstantDesc(Samp0Handle, & Samp0Desc, &count);
4:
5: pixelConstTable->GetConstantDesc(Samp1Handle, & Samp1Desc, &count);
通过上面的描述,将纹理变量的寄存器偏移作为纹理的stage
8. 优化常量设置速度的方法一般就是根据字符串取出句柄,以后每次渲染时,只通过句柄设置。但ID3DXConstantTable最后还是通过
IDirect3DDevice9::SetPixelShaderConstantX 系列函数来实现的
1: HRESULT SetPixelShaderConstantF(
2: UINT StartRegister,
3: CONST float * pConstantData,
4: UINT Vector4fCount
5: );
9. HLSL将一段包含VS和PS代码编译完成后,将得到VS和PS两个单独的ID3DXConstantTable