SDK范例CompiledEffect分析及疑点探讨

CompiledEffect分析

2009-06-22 DirectXer

 

这个例子必须使用VisualStudio中编译后才能执行,直接运行Bin下的CompiledEffect.exe会提示找不到CompiledEffect.fxo文件。CompiledEffect.fxo文件CompiledEffect.fx编译后的文件。在VisualStudio中,右键选择CompiledEffect.fx,弹出菜单中选择属性,“自定义生成步骤”的命令行中,显示的是CompiledEffect.fxo的生成命令:
fxc /Od /Zi /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"
输出项中显示的是生成的文件名:
$(ProjectDir)$(inputName).fxo

 

fxc是effect文件的离线编译工具,是一命令行程序。位于“(SDK root)/Utilities/Bin/x86/”中,使用方法和相关编译选项参见SDK文档:DirectX Graphics/Tools/Effect-Compiler Tool。

 

使用已编译的文件创建ID3DXEffect对象时,是不能设置编译选项的。编译选项必须在使用fxc.exe编译CompiledEffect.fxo文件时,在fxc.exe的参数中设置。对于此程序,有三个生成配置:Debug,Debug Shader,Release,使用的参数是不相同的。


Debug:
fxc /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"
Release:
fxc /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"
Debug Shader:
fxc /Od /Zi /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"

其中选项:
/Od-不使用优化(Disable optimizations)
/Zi-允许调试信息(Enable debugging information)
/Tfx_2_0-Shader模型为Effect fx_2_0。

 

创建ID3DXEffect对象代码为:
D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &g_pEffect, NULL );
与使用非编译Effect文件时的代码对比:
DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;
#ifdef DEBUG_VS
    dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
    dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif
D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, NULL, &g_pEffect9, NULL )

 

代码中似乎没有其它难点了,不过有一点需要我们探讨一下:
在CompiledEffect.fx中,PixelShader函数为RenderScenePS(),在此函数中,颜色值是MeshTextureSampler纹理与Diffuse的乘积,MeshTextureSampler使用的纹理变量为g_MeshTexture,而cpp代码中,并未对此进行设值,按理来说,渲染后的3D对象应该是不带纹理的,但运行时发现并非如此。什么原因呢?我也并不确定,希望能够一起探讨一下:
程序中渲染的3D对象是一个Mesh,使用的是CDXUTXFileMesh类,渲染是在CDXUTXFileMesh.Render(LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets, bool bDrawAlphaSubsets)中进行的,设置Mesh中带的材质和纹理进行渲染:
pd3dDevice->SetMaterial( &m_pMaterials[i] );
pd3dDevice->SetTexture( 0, m_pTextures[i] );
m_pMesh->DrawSubset( i );

代码中设置了0级纹理,在effect文件中,对应的是register(s0),而CompiledEffect.fx并未定义,我认为它是默认使用s0,只是因为s0未定义,因此使用了MeshTextureSampler的MipFilter,MinFilter和MagFilter的设置而已。

试验1:
我们可以将technique RenderScene中的
PixelShader  = compile ps_2_0 RenderScenePS();
改为
PixelShader = null;
对比可以发现,3D对象仍有纹理,只不过有些粗糙,因为纹理默认使用的是POINT过滤的。

试验2:
复原CompiledEffect.fx代码,在代码中加入如下的定义:
sampler myVar : register(s0) =
sampler_state
{
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};
再运行时会发现,3D对象的纹理没有了。因为这时定义了register(s0),原来的默认项就不能再用了,必须把RenderScenePS()中的MeshTextureSampler改为myVar才行。

试验3:
复原CompiledEffect.fx代码,在代码中定义一个IDirect3DTexture9对象,设置给Effect:
g_pEffect->SetTexture("g_MeshTexture", g_pTexture);
运行时会发现,设置的纹理并未起作用。

试验4:在试验3的基础上,在CompiledEffect.fx中加入试验2的代码。
运行发现,设置的纹理起作用了。

不知道以上分析是否正确,欢迎高手进来讨论。

 

其它备忘:
1. ID3DXEffect对象的创建流程:
   1) ID3DXEffect对象是在OnCreateDevice回调函数中创建的,
    D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, D3DXFX_NOT_CLONEABLE,
        NULL, &g_pEffect, NULL );
   2) 在OnResetDevice回调函数中要调用ID3DXEffect.OnResetDevice(),接下来就可以调用ID3DXEffect的其它方法了。
   3) 在OnFrameRender回调函数中渲染3D对象:
   UINT iPass, cPasses;
   g_pEffect->Begin( &cPasses, 0 );
   for( iPass = 0; iPass < cPasses; iPass++ )
   {
      V( g_pEffect->BeginPass( iPass ) );
      V( g_Mesh.Render( pd3dDevice ) );
      g_pEffect->EndPass();
   }
   g_pEffect->End();
   4) 在OnLostDevice回调函数中要调用ID3DXEffect.OnLostDevice()。
   5) 在OnDestroyDevice回调函数中释放:
      SAFE_RELEASE( g_pEffect );

2. 将Mesh移到原点:
   1)创建Mesh:
   g_Mesh.Create( pd3dDevice, L"dwarf//dwarf.x" );

   2) 获取Mesh的顶点Buffer:
   IDirect3DVertexBuffer9* pVB = NULL;
   g_Mesh.m_pMesh->GetVertexBuffer( &pVB );
   void* pVertices = NULL;
   pVB->Lock( 0, 0, &pVertices, 0 );
  
   3)根据顶点数据计算包围球位置和半径:
   D3DXComputeBoundingSphere( ( D3DXVECTOR3* )pVertices,
       g_Mesh.m_pMesh->GetNumVertices(),
       D3DXGetFVFVertexSize( g_Mesh.m_pMesh->GetFVF() ),
       &g_vObjectCenter, &g_fObjectRadius );
   pVB->Unlock();
   SAFE_RELEASE( pVB );
   D3DXMatrixTranslation( &g_mCenterWorld, -g_vObjectCenter.x, -g_vObjectCenter.y, -g_vObjectCenter.z );
   ...
   D3DXMATRIXA16 mWorld;
   mWorld = g_mCenterWorld * *g_Camera.GetWorldMatrix();
   g_pEffect->SetMatrix( g_hWorld, &mWorld );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值