《精通DirectX 3D》第二十章 效果 04_EffectParam

《精通DirectX 3D》第二十章 效果 04_EffectParam



《精通DirectX 3D》第二十章 效果 04_EffectParam_第1张图片


EffectParam.fx

// ==============================================================
//  Desc: 效果文件
// ==============================================================


// --------------------------------------------------------------
//  全局变量
// --------------------------------------------------------------
shared float4x4 g_mWorld;
shared float4x4 g_mView;
shared float4x4 g_mProj;

shared float4 g_vLight      
=  float4(  0.0f 0.0f - 10.0f 1.0f  );   // 光源在观察空间中的位置
shared float4 g_vLightColor  =  float4(  1.0f 1.0f 1.0f 1.0f  );
texture  g_txScene;
float4   Diffuse;


// --------------------------------------------------------------
//  纹理采样器
// --------------------------------------------------------------
sampler2D g_samScene  =  sampler_state
{
    Texture 
=   < g_txScene > ;
    MinFilter 
=  Linear;
    MagFilter 
=  Linear;
    MipFilter 
=  Linear;
};


// --------------------------------------------------------------
//  Desc: 顶点渲染
// --------------------------------------------------------------
void  VertScene( float4 vPos : POSITION,
                float3 vNormal : NORMAL,
                float2 vTex0 : TEXCOORD0,
                
out  float4 oDiffuse : COLOR0,
                
out  float4 oPos : POSITION,
                
out  float2 oTex0 : TEXCOORD0 )
{
    
// 顶点坐标变换
    oPos  =  mul( vPos, g_mWorld );
    oPos 
=  mul( oPos, g_mView );
    oPos 
=  mul( oPos, g_mProj );

    
// 计算顶点在观察空间中的坐标
    float4 wPos  =  mul( vPos, g_mWorld );
    wPos 
=  mul( wPos, g_mView );

    
// 计算顶点在观察空间中的法线向量
    float3 N  =   mul( vNormal, (float3x3)g_mWorld );
    N 
=  normalize( mul( N, (float3x3)g_mView ) );

    
// 计算灯光方向
    float3 InvL  =  g_vLight  -  wPos;
    InvL 
=  normalize( InvL );

    
// 计算顶点漫反射颜色
    oDiffuse  =  saturate( dot( N, InvL ) )  *  Diffuse  *  g_vLightColor;

    
// 简单复制输出纹理坐标
    oTex0  =  vTex0;
}


// --------------------------------------------------------------
//  Desc: 像素渲染
// --------------------------------------------------------------
float4 PixScene( float4 Diffuse : COLOR0,
                 float2 Tex0 : TEXCOORD0 ) : COLOR0
{
    
return  tex2D( g_samScene, Tex0 )  *  Diffuse;
}


// --------------------------------------------------------------
//  Desc: 技术
// -------------------------------------------------------------
technique RenderScene
{
    pass P0
    {
        VertexShader 
=  compile vs_2_0 VertScene();
        PixelShader  
=  compile ps_2_0 PixScene();
    }
}


// =============================================================================
//  Desc: 主程序源文件
// =============================================================================
#include  " dxstdafx.h "
#include 
" resource.h "
#include 
< crtdbg.h >

// #define DEBUG_VS    //  Uncomment this line to debug vertex shaders 
// #define DEBUG_PS    //  Uncomment this line to debug pixel shaders 

//  SCROLL_TIME dictates the time one scroll op takes, in seconds.
#define  SCROLL_TIME 0.5f

// -----------------------------------------------------------------------------
//  Desc: 网格列表结构
// -----------------------------------------------------------------------------
struct  MESHLISTDATA
{
    WCHAR wszName[MAX_PATH];
    WCHAR wszFile[MAX_PATH];
    DWORD dwNumMat;  
// 材质数量
} g_MeshListData[]  =
{
    { L
" Car " , L " car2.x " 0  },
    { L
" Banded Earth " , L " sphereband.x " 0  },
    { L
" Dwarf " , L " dwarf\\DwarfWithEffectInstance.x " 0  },
    { L
" Virus " , L " cytovirus.x " 0  },
    { L
" Car " , L " car2.x " 0  },
    { L
" Banded Earth " , L " sphereband.x " 0  },
    { L
" Dwarf " , L " dwarf\\DwarfWithEffectInstance.x " 0  },
};


// -----------------------------------------------------------------------------
//  Desc: 顶点结构和灵活顶点格式
// -----------------------------------------------------------------------------
struct  MESHVERTEX
{
    D3DXVECTOR3 Position;
    D3DXVECTOR3 Normal;
    D3DXVECTOR2 Tex;

    
const   static  D3DVERTEXELEMENT9 Decl[ 4 ];
};


// -----------------------------------------------------------------------------
//  Desc: 顶点声明
// -----------------------------------------------------------------------------
const  D3DVERTEXELEMENT9 MESHVERTEX::Decl[]  =
{
    { 
0 0 ,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,  0  },
    { 
0 12 , D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,    0  },
    { 
0 24 , D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  0  },
    D3DDECL_END()
};


// -----------------------------------------------------------------------------
//  Desc: 网格材质结构
// -----------------------------------------------------------------------------
struct  CMeshMaterial
{
    ID3DXEffect        
* m_pEffect;
    D3DXHANDLE          m_hParam;
    IDirect3DTexture9  
* m_pTexture;

public :
    CMeshMaterial()
    {
        m_pEffect  
=  NULL;
        m_hParam   
=  NULL;
        m_pTexture 
=  NULL;
    }

    
~ CMeshMaterial()
    {
        SAFE_RELEASE( m_pEffect );
        SAFE_RELEASE( m_pTexture );
    }

    
const  CMeshMaterial  & operator = const  CMeshMaterial  & rhs )
    {
        m_pEffect 
=  rhs.m_pEffect;
        m_hParam 
=  rhs.m_hParam;
        m_pTexture 
=  rhs.m_pTexture;
        m_pEffect
-> AddRef();
        m_pTexture
-> AddRef();
        
return   * this ;
    }
};


// 外部变量
extern  ID3DXEffect *  g_pEffect;                 // 效果
extern  IDirect3DTexture9 *  g_pDefaultTex;       // 纹理
extern  IDirect3DCubeTexture9 *  g_pEnvMapTex;    // 立方体纹理


// -----------------------------------------------------------------------------
//  Desc: 效果网格类
// -----------------------------------------------------------------------------
class  CEffectMesh
{
    WCHAR          m_wszMeshFile[MAX_PATH];
    ID3DXMesh     
* m_pMesh;
    CMeshMaterial 
* m_pMaterials;
    DWORD          m_dwNumMaterials;

public :
    CEffectMesh()
    {
        m_pMesh          
=  NULL;
        m_pMaterials     
=  NULL;
        m_dwNumMaterials 
=   0 ;
    }

    CEffectMesh( 
const  CEffectMesh  & old )
    {
        m_pMesh 
=  NULL; 
        m_pMaterials 
=  NULL;
        
* this   =  old;
    }

    
~ CEffectMesh()
    {
        Destroy();
    }

    
const  CEffectMesh  & operator = const  CEffectMesh  & rhs )
    {
        
if this   ==   & rhs )
            
return   * this ;

        StringCchCopyW( m_wszMeshFile, MAX_PATH, rhs.m_wszMeshFile );
        m_dwNumMaterials 
=  rhs.m_dwNumMaterials;
        SAFE_RELEASE( m_pMesh );
        
if ( ( m_pMesh  =  rhs.m_pMesh )  !=   0  ) m_pMesh -> AddRef();
        delete[] m_pMaterials;
        m_pMaterials 
=   new  CMeshMaterial[m_dwNumMaterials];
        
if ( m_pMaterials )
        {
            
for ( UINT i  =   0 ; i  <  m_dwNumMaterials;  ++ i )
                m_pMaterials[i] 
=  rhs.m_pMaterials[i];
        }
        
return   * this ;
    }

    DWORD GetNumMaterials() 
const  {  return  m_dwNumMaterials; }
    ID3DXMesh 
* GetMesh() {  return  m_pMesh; }

    HRESULT Create( LPCWSTR wszFileName, IDirect3DDevice9 
* pd3dDevice );

    HRESULT Destroy()
    {
        delete[] m_pMaterials;
        m_pMaterials 
=  NULL;
        m_dwNumMaterials 
=   0 ;
        SAFE_RELEASE( m_pMesh );
        
return  S_OK;
    }

    
void  Render( IDirect3DDevice9  * pd3dDevice )
    {
        HRESULT hr;

        
for ( UINT i  =   0 ; i  <  m_dwNumMaterials;  ++ i )
        {
            CMeshMaterial 
* pMat  =   & m_pMaterials[i];
            V( pMat
-> m_pEffect -> ApplyParameterBlock( pMat -> m_hParam ) );

            UINT cPasses;
            V( pMat
-> m_pEffect -> Begin(  & cPasses,  0  ) );
            
for ( UINT p  =   0 ; p  <  cPasses;  ++ p )
            {
                V( pMat
-> m_pEffect -> BeginPass( p ) );
                V( m_pMesh
-> DrawSubset( i ) );
                V( pMat
-> m_pEffect -> EndPass() );
            }
            V( pMat
-> m_pEffect -> End() );
        }
    }
};


// -----------------------------------------------------------------------------
//  Desc: 网格控制球类
// -----------------------------------------------------------------------------
class  CMeshArcBall :  public  CD3DArcBall
{
public :
    
void  OnBegin(  int  nX,  int  nY, D3DXMATRIXA16  * pmInvViewRotate )
    {
        m_bDrag 
=   true ;
        m_qDown 
=  m_qNow;
        m_vDownPt 
=  ScreenToVector( ( float )nX, ( float )nY );
        D3DXVECTOR4 v;
        D3DXVec3Transform( 
& v,  & m_vDownPt, pmInvViewRotate );
        m_vDownPt 
=  (D3DXVECTOR3)v;
    }

    
void  OnMove(  int  nX,  int  nY, D3DXMATRIXA16  * pmInvViewRotate )
    {
        
if  (m_bDrag) 
        { 
            m_vCurrentPt 
=  ScreenToVector( ( float )nX, ( float )nY );
            D3DXVECTOR4 v;
            D3DXVec3Transform( 
& v,  & m_vCurrentPt, pmInvViewRotate );
            m_vCurrentPt 
=  (D3DXVECTOR3)v;
            m_qNow 
=  m_qDown  *  QuatFromBallPoints( m_vDownPt, m_vCurrentPt );
        }
    }

    LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, D3DXMATRIXA16 
* pmInvViewRotate )
    {
        
//  Current mouse position
         int  iMouseX  =  ( short )LOWORD(lParam);
        
int  iMouseY  =  ( short )HIWORD(lParam);

        
switch ( uMsg )
        {
            
case  WM_LBUTTONDOWN:
            
case  WM_LBUTTONDBLCLK:
                SetCapture( hWnd );
                OnBegin( iMouseX, iMouseY, pmInvViewRotate );
                
return  TRUE;

            
case  WM_LBUTTONUP:
                ReleaseCapture();
                OnEnd();
                
return  TRUE;

            
case  WM_CAPTURECHANGED:
                
if ( (HWND)lParam  !=  hWnd )
                {
                    ReleaseCapture();
                    OnEnd();
                }
                
return  TRUE;

            
case  WM_MOUSEMOVE:
                
if ( MK_LBUTTON & wParam )
                {
                    OnMove( iMouseX, iMouseY, pmInvViewRotate );
                }
                
return  TRUE;
        }
        
return  FALSE;
    }
};


// -----------------------------------------------------------------------------
//  全局变量
// -----------------------------------------------------------------------------
ID3DXFont *                  g_pFont  =  NULL;          // ID3DXFont字体对象
ID3DXSprite *                g_pTextSprite  =  NULL;    // ID3DXSprite文本精灵对象
 
bool                        g_bShowHelp  =   true ;      // 标识是否显示简单说明文本
CDXUTDialogResourceManager g_DialogResourceManager; // 对话框资源管理器
CD3DSettingsDlg            g_SettingsDlg;           // Direct3D设备设置对话框
CDXUTDialog                g_HUD;                   // 对话框
CDXUTDialog                g_SampleUI;              // 对话框

IDirect3DTexture9
*          g_pDefaultTex  =  NULL;    // 默认纹理
IDirect3DCubeTexture9 *      g_pEnvMapTex   =  NULL;    // 环境映射纹理

ID3DXEffect
*                   g_pEffect  =  NULL;        // 效果接口
IDirect3DVertexDeclaration9   * g_pDecl  =  NULL;          // 顶点声明
ID3DXEffectPool *               g_pEffectPool  =  NULL;    // 效果池
DWORD                         g_dwShaderFlags  =  D3DXFX_NOT_CLONEABLE;  // 渲染器创建标志

CModelViewerCamera            g_Camera;           
// 摄影机
CGrowableArray < CEffectMesh >    g_Meshes;            // 网格模型列表
CGrowableArray < CMeshArcBall >   g_ArcBall;           // 各个网格模型的控制球
CGrowableArray < D3DXMATRIXA16 >  g_amWorld;           // 各个网格模型的世界矩阵

int                      g_nActiveMesh  =   0 ;         // 激活网格模型书
D3DXMATRIXA16           g_mScroll;                 // 滚动矩阵
float                    g_fAngleToScroll  =   0.0f ;   // 滚动的角度
float                    g_fAngleLeftToScroll  =   0.0f ;


// -----------------------------------------------------------------------------
//  控件ID
// -----------------------------------------------------------------------------
#define  IDC_TOGGLEFULLSCREEN    1
#define  IDC_TOGGLEREF           3
#define  IDC_CHANGEDEVICE        4
#define  IDC_SHARE               5
#define  IDC_SCROLLLEFT          6
#define  IDC_SCROLLRIGHT         7
#define  IDC_MESHNAME            8
#define  IDC_MATCOUNT            9


// -----------------------------------------------------------------------------
//  Desc: 函数声明
// -----------------------------------------------------------------------------
bool     CALLBACK IsDeviceAcceptable( D3DCAPS9 *  pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,  bool  bWindowed,  void *  pUserContext );
bool     CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *  pDeviceSettings,  const  D3DCAPS9 *  pCaps,  void *  pUserContext );
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9
*  pd3dDevice,  const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc,  void *  pUserContext );
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9
*  pd3dDevice,  const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc,  void *  pUserContext );
void     CALLBACK OnFrameMove( IDirect3DDevice9 *  pd3dDevice,  double  fTime,  float  fElapsedTime,  void *  pUserContext );
void     CALLBACK OnFrameRender( IDirect3DDevice9 *  pd3dDevice,  double  fTime,  float  fElapsedTime,  void *  pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
bool *  pbNoFurtherProcessing,  void *  pUserContext );
void     CALLBACK KeyboardProc( UINT nChar,  bool  bKeyDown,  bool  bAltDown,  void *  pUserContext );
void     CALLBACK OnGUIEvent( UINT nEvent,  int  nControlID, CDXUTControl *  pControl,  void *  pUserContext );
void     CALLBACK OnLostDevice(  void *  pUserContext );
void     CALLBACK OnDestroyDevice(  void *  pUserContext );

void     InitApp();
HRESULT LoadMesh( IDirect3DDevice9
*  pd3dDevice, WCHAR *  strFileName, ID3DXMesh **  ppMesh );
void     RenderText();


// -----------------------------------------------------------------------------
//  Desc: 效果网格模型创建函数
// -----------------------------------------------------------------------------
HRESULT CEffectMesh::Create( LPCWSTR wszFileName, IDirect3DDevice9  * pd3dDevice )
{
    HRESULT hr;

    WCHAR str[MAX_PATH];
    WCHAR wszMeshPath[MAX_PATH];
    ID3DXBuffer 
* pAdjacency;
    ID3DXBuffer 
* pMaterials;
    ID3DXBuffer 
* pEffectInstance;
    DWORD dwNumMaterials;

    
// 保存网格文件名
    StringCchCopy( m_wszMeshFile, MAX_PATH, wszFileName );

    
// 加载网格模型
    V_RETURN( DXUTFindDXSDKMediaFileCch( wszMeshPath, MAX_PATH, m_wszMeshFile ) );
    V_RETURN( D3DXLoadMeshFromX( wszMeshPath, D3DXMESH_MANAGED, pd3dDevice,
                                    
& pAdjacency,  & pMaterials,  & pEffectInstance,
                                    
& dwNumMaterials,  & m_pMesh ) );
   
    ID3DXMesh 
* pCloneMesh;
    V_RETURN( m_pMesh
-> CloneMesh( m_pMesh -> GetOptions(), MESHVERTEX::Decl, pd3dDevice,  & pCloneMesh ) );
    m_pMesh
-> Release();
    m_pMesh 
=  pCloneMesh;

    
// 从路径中提取文件名
    WCHAR  * pLastBSlash  =  wcsrchr( wszMeshPath, L ' \\ '  );
    
if ( pLastBSlash )
    {
        
* ( pLastBSlash  +   1  )  =  L ' \0 ' ;
    }
    
else
        StringCchCopyW( wszMeshPath, MAX_PATH, L
" .\\ "  );

    
// 确保网格模型顶点包含法线信息
     bool  bHasNormals  =  ( m_pMesh -> GetFVF()  &  D3DFVF_NORMAL )  !=   0 ;
    
if ! bHasNormals )
        D3DXComputeNormals( m_pMesh, (DWORD
* )pAdjacency -> GetBufferPointer() );

    m_pMaterials 
=   new  CMeshMaterial[dwNumMaterials];
    
if ! m_pMaterials )
        
return  E_OUTOFMEMORY;

    
// 提取材质
    D3DXMATERIAL  * pXMats  =  (D3DXMATERIAL  * )pMaterials -> GetBufferPointer();
    D3DXEFFECTINSTANCE 
* pEI  =  (D3DXEFFECTINSTANCE  * )pEffectInstance -> GetBufferPointer();
    
for ( UINT i  =   0 ; i  <  dwNumMaterials;  ++ i )
    {
        
//  Obtain the effect

        hr 
=  S_OK;
       
        StringCchCopyW( str, MAX_PATH, wszMeshPath );
        MultiByteToWideChar( CP_ACP, 
0 , pEI[i].pEffectFilename,  - 1 , str  +  lstrlenW( str ), MAX_PATH );

        
if ( pEI[i].pEffectFilename  ==  NULL )
            hr 
=  E_FAIL;

        WCHAR wszFxName[MAX_PATH];
        MultiByteToWideChar( CP_ACP, 
0 , pEI[i].pEffectFilename,  - 1 , wszFxName, MAX_PATH );

        
if ( SUCCEEDED(hr) )
        {
            WCHAR szTmp[MAX_PATH];
            StringCchCopy( szTmp, MAX_PATH, L
" SharedFx\\ "  );
            StringCchCat( szTmp, MAX_PATH, wszFxName );
            hr 
=  DXUTFindDXSDKMediaFileCch( str, MAX_PATH, szTmp );
            
if ( FAILED( hr ) )
            {
                
// 从SKD目录中查找
                hr  =  DXUTFindDXSDKMediaFileCch( str, MAX_PATH, wszFxName );
            }
        }

        
if ( SUCCEEDED( hr ) )
            DXUTGetGlobalResourceCache().CreateEffectFromFile( pd3dDevice, str, NULL, NULL, g_dwShaderFlags, g_pEffectPool,
                                                               
& m_pMaterials[i].m_pEffect, NULL );
        
if ! m_pMaterials[i].m_pEffect )
        {
            
//  No valid effect for this material.  Use the default.
            m_pMaterials[i].m_pEffect  =  g_pEffect;
            m_pMaterials[i].m_pEffect
-> AddRef();
        }

        
//  Set the technique this material should use
        D3DXHANDLE hTech;
        m_pMaterials[i].m_pEffect
-> FindNextValidTechnique( NULL,  & hTech );
        m_pMaterials[i].m_pEffect
-> SetTechnique( hTech );

        
//  Create a parameter block to include all parameters for the effect.
        m_pMaterials[i].m_pEffect -> BeginParameterBlock();
        
for ( UINT param  =   0 ; param  <  pEI[i].NumDefaults;  ++ param )
        {
            D3DXHANDLE hHandle 
=  m_pMaterials[i].m_pEffect -> GetParameterByName( NULL, pEI[i].pDefaults[param].pParamName );
            D3DXPARAMETER_DESC desc;
            
if ( hHandle  !=  NULL )
            {
                m_pMaterials[i].m_pEffect
-> GetParameterDesc( hHandle,  & desc );
                
if ( desc.Type  ==  D3DXPT_BOOL  ||  
                    desc.Type 
==  D3DXPT_INT  ||  
                    desc.Type 
==  D3DXPT_FLOAT  ||  
                    desc.Type 
==  D3DXPT_STRING )
                {
                    m_pMaterials[i].m_pEffect
-> SetValue( pEI[i].pDefaults[param].pParamName,
                                                        pEI[i].pDefaults[param].pValue,
                                                        pEI[i].pDefaults[param].NumBytes );
                }
            }
        }

        
// 获取纹理
        hr  =  S_OK;

        
if ( pXMats[i].pTextureFilename )
        {
            StringCchCopyW( str, MAX_PATH, wszMeshPath );
            MultiByteToWideChar( CP_ACP, 
0 , pXMats[i].pTextureFilename,  - 1 , str  +  lstrlenW( str ), MAX_PATH );
            
            
if ( INVALID_FILE_ATTRIBUTES  ==  ::GetFileAttributesW( str ) )
            {
                WCHAR wszTexName[MAX_PATH];
        
                MultiByteToWideChar( CP_ACP, 
0 , pXMats[i].pTextureFilename,  - 1 , wszTexName, MAX_PATH );
                hr 
=  DXUTFindDXSDKMediaFileCch( str, MAX_PATH, wszTexName );
            }

            
if ( SUCCEEDED( hr ) )
                DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, str, 
& m_pMaterials[i].m_pTexture );
        }

        
if ! m_pMaterials[i].m_pTexture )
        {
            
// 如果没有纹理, 或纹理加载失败,使用默认纹理
            m_pMaterials[i].m_pTexture  =  g_pDefaultTex;
            m_pMaterials[i].m_pTexture
-> AddRef();
        }

        
//  Include the texture in the parameter block if the effect requires one.
        D3DXHANDLE hTexture  =  m_pMaterials[i].m_pEffect -> GetParameterByName( NULL,  " g_txScene "  );
        
if ( hTexture )
            m_pMaterials[i].m_pEffect
-> SetTexture( hTexture, m_pMaterials[i].m_pTexture );

        
//  Include the environment map texture in the parameter block if the effect requires one.
        hTexture  =  m_pMaterials[i].m_pEffect -> GetParameterByName( NULL,  " g_txEnvMap "  );
        
if ( hTexture )
            m_pMaterials[i].m_pEffect
-> SetTexture( hTexture, g_pEnvMapTex );

        
//  Save the parameter block
        m_pMaterials[i].m_hParam  =  m_pMaterials[i].m_pEffect -> EndParameterBlock();
    }

    SAFE_RELEASE( pAdjacency );
    SAFE_RELEASE( pMaterials );
    SAFE_RELEASE( pEffectInstance );
    m_dwNumMaterials 
=  dwNumMaterials;
    
return  S_OK;
}


// -----------------------------------------------------------------------------
//  Desc: 入口函数
// -----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR,  int  )
{
    
// 为Debug配置启用运行时内存检查功能
#if  defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF 
|  _CRTDBG_LEAK_CHECK_DF );
#endif

    
// 设置回调函数
    DXUTSetCallbackDeviceCreated( OnCreateDevice );
    DXUTSetCallbackDeviceReset( OnResetDevice );
    DXUTSetCallbackDeviceLost( OnLostDevice );
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackKeyboard( KeyboardProc );
    DXUTSetCallbackFrameRender( OnFrameRender );
    DXUTSetCallbackFrameMove( OnFrameMove );

    
// 全屏幕模式下显示鼠标光标
    DXUTSetCursorSettings(  true true  );

    
// 应用程序相关的初始化
    InitApp();

    
// 初始化DXUT, 创建窗口, 创建Direct3D设备对象
    DXUTInit(  true true true  );
    DXUTCreateWindow( L
" EffectParam "  );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, 
true 640 480 , IsDeviceAcceptable, ModifyDeviceSettings );

    
// 进入消息循环和场景渲染
    DXUTMainLoop();

    
// 在此进行应用程序相关的清除工作

    
return  DXUTGetExitCode();
}


// -----------------------------------------------------------------------------
//  Desc: 应用程序相关初始化
// -----------------------------------------------------------------------------
void  InitApp()
{
    
// 初始化对话框
    g_SettingsDlg.Init(  & g_DialogResourceManager );
    g_HUD.Init( 
& g_DialogResourceManager );
    g_SampleUI.Init( 
& g_DialogResourceManager );

    
// 为g_HUD对话框设置消息处理函数,添加控件
    g_HUD.SetCallback( OnGUIEvent );  int  iY  =   10
    g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L
" Toggle full screen " 35 , iY,  125 22  );
    g_HUD.AddButton( IDC_TOGGLEREF, L
" Toggle REF (F3) " 35 , iY  +=   24 125 22  );
    g_HUD.AddButton( IDC_CHANGEDEVICE, L
" Change device (F2) " 35 , iY  +=   24 125 22 , VK_F2 );

    
// 为g_SampleUI对话框设置消息处理函数,添加控件
    g_SampleUI.SetCallback( OnGUIEvent ); iY  =   10 ;
    g_SampleUI.AddStatic( IDC_MESHNAME, L
" Mesh Name " 0 , iY,  160 20  );
    g_SampleUI.AddStatic( IDC_MATCOUNT, L
" Number of materials: 0 " 0 , iY  +=   20 160 20  );
    g_SampleUI.AddButton( IDC_SCROLLLEFT, L
" << " 5 , iY  +=   24 70 24  );
    g_SampleUI.AddButton( IDC_SCROLLRIGHT, L
" >> " 85 , iY,  70 24  );
    g_SampleUI.AddCheckBox( IDC_SHARE, L
" Enable shared parameters " 0 , iY  +=   32 160 24 true  );

    
// 初始化控制球
     for int  i  =   0 ; i  <   sizeof (g_MeshListData) / sizeof (g_MeshListData[ 0 ]);  ++ i )
    {
        g_ArcBall.Add( CMeshArcBall() );
        g_ArcBall[g_ArcBall.GetSize()
- 1 ].SetTranslationRadius(  2.0f  );
    }

    
// 设置摄影机
    D3DXVECTOR3 vecEye( 0.0f 0.0f - 5.0f );
    D3DXVECTOR3 vecAt (
0.0f 0.0f - 3.0f );
    g_Camera.SetViewParams( 
& vecEye,  & vecAt );
    g_Camera.SetButtonMasks( 
0 , MOUSE_WHEEL,  0  );
    g_Camera.SetRadius( 
5.0f 1.0f  );
}


// -----------------------------------------------------------------------------
//  Desc: 设备能力检查
// -----------------------------------------------------------------------------
bool  CALLBACK IsDeviceAcceptable( D3DCAPS9 *  pCaps, D3DFORMAT AdapterFormat, 
                                  D3DFORMAT BackBufferFormat, 
bool  bWindowed,  void *  pUserContext )
{
    
// 检查后台缓冲区格式是否支持Alpha混合等操作(post pixel blending operations)
    IDirect3D9 *  pD3D  =  DXUTGetD3DObject(); 
    
if ( FAILED( pD3D -> CheckDeviceFormat( pCaps -> AdapterOrdinal, pCaps -> DeviceType,
                    AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
                    D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        
return   false ;

    
// 检查当前设备支持的像素渲染器版本是否低于1.1
     if ( pCaps -> PixelShaderVersion  <  D3DPS_VERSION(  1 1  ) )
        
return   false ;

    
return   true ;
}


// -----------------------------------------------------------------------------
//  Desc: 修改Direct3D渲染设备设置
// -----------------------------------------------------------------------------
bool  CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *  pDeviceSettings,  const  D3DCAPS9 *  pCaps,  void *  pUserContext )
{
    
//  Turn vsync off
    pDeviceSettings -> pp.PresentationInterval  =  D3DPRESENT_INTERVAL_IMMEDIATE;
    g_SettingsDlg.GetDialogControl()
-> GetComboBox( DXUTSETTINGSDLG_PRESENT_INTERVAL ) -> SetEnabled(  false  );

    
// 如果硬件不支持, 则切换到软件顶点处理
     if ( (pCaps -> DevCaps  &  D3DDEVCAPS_HWTRANSFORMANDLIGHT)  ==   0   ||
         pCaps
-> VertexShaderVersion  <  D3DVS_VERSION( 1 , 1 ) )
    {
        pDeviceSettings
-> BehaviorFlags  =  D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }

    
// 如果硬件不支持顶点混合, 则使用软件顶点处理模式
     if ( pCaps -> MaxVertexBlendMatrices  <   2  )
        pDeviceSettings
-> BehaviorFlags  =  D3DCREATE_SOFTWARE_VERTEXPROCESSING;


    
// 如果使用硬件顶点处理, 则改为混合顶点处理
     if ( pDeviceSettings -> BehaviorFlags  &  D3DCREATE_HARDWARE_VERTEXPROCESSING )
        pDeviceSettings
-> BehaviorFlags  =  D3DCREATE_MIXED_VERTEXPROCESSING;    

    
//  Add mixed vp to the available vp choices in device settings dialog.
     bool  bSvp, bHvp, bPHvp, bMvp;
    DXUTGetEnumeration()
-> GetPossibleVertexProcessingList(  & bSvp,  & bHvp,  & bPHvp,  & bMvp );
    DXUTGetEnumeration()
-> SetPossibleVertexProcessingList( bSvp,  false false true  );

    
// 调试顶点渲染器需要参考设备或软件顶点处理
#ifdef DEBUG_VS
    
if ( pDeviceSettings -> DeviceType  !=  D3DDEVTYPE_REF )
    {
        pDeviceSettings
-> BehaviorFlags  &=   ~ D3DCREATE_HARDWARE_VERTEXPROCESSING;
        pDeviceSettings
-> BehaviorFlags  &=   ~ D3DCREATE_PUREDEVICE;
        pDeviceSettings
-> BehaviorFlags  |=  D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }
#endif

    
// 调试像素渲染器需要参考设备
#ifdef DEBUG_PS
    pDeviceSettings
-> DeviceType  =  D3DDEVTYPE_REF;
#endif

    
// 如果使用参考设备,则弹出警告对话框
     static   bool  s_bFirstTime  =   true ;
    
if ( s_bFirstTime )
    {
        s_bFirstTime 
=   false ;
        
if ( pDeviceSettings -> DeviceType  ==  D3DDEVTYPE_REF )
            DXUTDisplaySwitchingToREFWarning();
    }

    
return   true ;
}


// -----------------------------------------------------------------------------
//  Desc: 在此创建管理内存资源对象
// -----------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9 *  pd3dDevice,  const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc,  void *  pUserContext )
{
    HRESULT hr;
    WCHAR str[MAX_PATH];

    V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) );
    V_RETURN( g_SettingsDlg.OnCreateDevice( pd3dDevice ) );

    
//  Create the effect pool object if shared param is enabled
     if ( g_SampleUI.GetCheckBox( IDC_SHARE ) -> GetChecked() )
        V_RETURN( D3DXCreateEffectPool( 
& g_pEffectPool ) );

    
//  Create the vertex decl
    V_RETURN( pd3dDevice -> CreateVertexDeclaration( MESHVERTEX::Decl,  & g_pDecl ) );
    pd3dDevice
-> SetVertexDeclaration( g_pDecl );

    
//  Create the 1x1 white default texture
    V_RETURN( pd3dDevice -> CreateTexture(  1 1 1 0 , D3DFMT_A8R8G8B8,
                                         D3DPOOL_MANAGED, 
& g_pDefaultTex, NULL ) );
    D3DLOCKED_RECT lr;
    V_RETURN( g_pDefaultTex
-> LockRect(  0 & lr, NULL,  0  ) );
    
* (LPDWORD)lr.pBits  =  D3DCOLOR_RGBA(  255 255 255 255  );
    V_RETURN( g_pDefaultTex
-> UnlockRect(  0  ) );

    
//  Create the environment map texture
    V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L " lobby\\lobbycube.dds "  ) );
    V_RETURN( D3DXCreateCubeTextureFromFile( pd3dDevice, str, 
& g_pEnvMapTex ) );

    
//  Initialize the font
    V_RETURN( DXUTGetGlobalResourceCache().CreateFont( pd3dDevice,  15 0 , FW_BOLD,  0 , FALSE, DEFAULT_CHARSET, 
                                                       OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH 
|  FF_DONTCARE, 
                                                       L
" Arial " & g_pFont ) );

    
//  Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
    
//  shader debugger. Debugging vertex shaders requires either REF or software vertex 
    
//  processing, and debugging pixel shaders requires REF.  The 
    
//  D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
    
//  shader debugger.  It enables source level debugging, prevents instruction 
    
//  reordering, prevents dead code elimination, and forces the compiler to compile 
    
//  against the next higher available software target, which ensures that the 
    
//  unoptimized shaders do not exceed the shader model limitations.  Setting these 
    
//  flags will cause slower rendering since the shaders will be unoptimized and 
    
//  forced into software.  See the DirectX documentation for more information about 
    
//  using the shader debugger.
    #ifdef DEBUG_VS
        g_dwShaderFlags 
|=  D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
    
#endif
    #ifdef DEBUG_PS
        g_dwShaderFlags 
|=  D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
    
#endif

    
//  Read the D3DX effect file
    V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L " EffectParam.fx "  ) );

    
//  If this fails, there should be debug output as to 
    
//  they the .fx file failed to compile
    V_RETURN( DXUTGetGlobalResourceCache().CreateEffectFromFile( pd3dDevice, str, NULL, NULL, g_dwShaderFlags, 
                                                                 g_pEffectPool, 
& g_pEffect, NULL ) );

    
//  Create the meshes
     for int  i  =   0 ; i  <   sizeof (g_MeshListData) / sizeof (g_MeshListData[ 0 ]);  ++ i )
    {
        CEffectMesh NewMesh;
        
if ( SUCCEEDED( NewMesh.Create( g_MeshListData[i].wszFile, DXUTGetD3DDevice() ) ) )
        {
            g_Meshes.Add( NewMesh );
            D3DXMATRIXA16 mW;
            LPVOID pVerts 
=  NULL;
            D3DXMatrixIdentity( 
& mW );
            
if ( SUCCEEDED( NewMesh.GetMesh() -> LockVertexBuffer(  0 & pVerts ) ) )
            {
                D3DXVECTOR3 vCtr;
                
float  fRadius;
                
if ( SUCCEEDED( D3DXComputeBoundingSphere( ( const  D3DXVECTOR3 * )pVerts,
                                                        NewMesh.GetMesh()
-> GetNumVertices(),
                                                        NewMesh.GetMesh()
-> GetNumBytesPerVertex(),
                                                        
& vCtr,  & fRadius ) ) )
                {
                    D3DXMatrixTranslation( 
& mW,  - vCtr.x,  - vCtr.y,  - vCtr.z );
                    D3DXMATRIXA16 m;
                    D3DXMatrixScaling( 
& m,  1.0f   /  fRadius,
                                            
1.0f   /  fRadius,
                                            
1.0f   /  fRadius );
                    D3DXMatrixMultiply( 
& mW,  & mW,  & m );
                }
                NewMesh.GetMesh()
-> UnlockVertexBuffer();
            }

            g_MeshListData[i].dwNumMat 
=  NewMesh.GetNumMaterials();
            g_amWorld.Add( mW );

            
//  Set the arcball window size
             const  D3DSURFACE_DESC *  pD3DSD  =  DXUTGetBackBufferSurfaceDesc();
            g_ArcBall[g_ArcBall.GetSize()
- 1 ].SetWindow( pD3DSD -> Width, pD3DSD -> Height );
        }
    }

    g_SampleUI.GetStatic( IDC_MESHNAME )
-> SetText( g_MeshListData[g_nActiveMesh].wszName );
    WCHAR wsz[
256 ];
    StringCchPrintf( wsz, 
256 , L " Number of materials: %u " , g_MeshListData[g_nActiveMesh].dwNumMat );
    wsz[
255 =  L ' \0 ' ;
    g_SampleUI.GetStatic( IDC_MATCOUNT )
-> SetText( wsz );

    D3DXMatrixIdentity( 
& g_mScroll );

    
return  S_OK;
}


// --------------------------------------------------------------------------------------
//  This callback function will be called immediately after the Direct3D device has been 
//  reset, which will happen after a lost device scenario. This is the best location to 
//  create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
//  the device is lost. Resources created here should be released in the OnLostDevice 
//  callback. 
// --------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9 *  pd3dDevice, 
                                
const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc,  void *  pUserContext )
{
    HRESULT hr;

    V_RETURN( g_DialogResourceManager.OnResetDevice() );
    V_RETURN( g_SettingsDlg.OnResetDevice() );

    
if ( g_pFont )
        V_RETURN( g_pFont
-> OnResetDevice() );
    
if ( g_pEffect )
        V_RETURN( g_pEffect
-> OnResetDevice() );

    
//  Create a sprite to help batch calls when drawing many lines of text
    V_RETURN( D3DXCreateSprite( pd3dDevice,  & g_pTextSprite ) );

    
//  Setup the camera's projection parameters
     float  fAspectRatio  =  pBackBufferSurfaceDesc -> Width  /  (FLOAT)pBackBufferSurfaceDesc -> Height;
    g_Camera.SetProjParams( D3DX_PI
/ 4 , fAspectRatio,  0.1f 1000.0f  );
    
for int  i  =   0 ; i  <  g_ArcBall.GetSize();  ++ i )
        g_ArcBall[i].SetWindow( pBackBufferSurfaceDesc
-> Width, pBackBufferSurfaceDesc -> Height );

    g_HUD.SetLocation( pBackBufferSurfaceDesc
-> Width - 170 0  );
    g_HUD.SetSize( 
170 170  );
    g_SampleUI.SetLocation( ( pBackBufferSurfaceDesc
-> Width - 170  )  /   2 , pBackBufferSurfaceDesc -> Height - 120  );
    g_SampleUI.SetSize( 
170 120  );

    
return  S_OK;
}


// --------------------------------------------------------------------------------------
//  This callback function will be called once at the beginning of every frame. This is the
//  best location for your application to handle updates to the scene, but is not 
//  intended to contain actual rendering calls, which should instead be placed in the 
//  OnFrameRender callback.  
// --------------------------------------------------------------------------------------
void  CALLBACK OnFrameMove( IDirect3DDevice9 *  pd3dDevice,  double  fTime,  float  fElapsedTime,  void *  pUserContext )
{
    
//  Update the scroll matrix
     float  fFrameAngleToScroll  =  g_fAngleToScroll  *  fElapsedTime  /  SCROLL_TIME;
    
if ( fabs( fFrameAngleToScroll )  >  fabs( g_fAngleLeftToScroll ) )
        fFrameAngleToScroll 
=  g_fAngleLeftToScroll;
    g_fAngleLeftToScroll 
-=  fFrameAngleToScroll;
    D3DXMATRIXA16 m;
    D3DXMatrixRotationY( 
& m, fFrameAngleToScroll );
    g_mScroll 
*=  m;
    
//  Update the camera's position based on user input 
    g_Camera.FrameMove( fElapsedTime );
}


// --------------------------------------------------------------------------------------
//  This callback function will be called at the end of every frame to perform all the 
//  rendering calls for the scene, and it will also be called if the window needs to be 
//  repainted. After this function has returned, DXUT will call 
//  IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
// --------------------------------------------------------------------------------------
void  CALLBACK OnFrameRender( IDirect3DDevice9 *  pd3dDevice,  double  fTime,  float  fElapsedTime,  void *  pUserContext )
{
    
//  If the settings dialog is being shown, then
    
//  render it instead of rendering the app's scene
     if ( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.OnRender( fElapsedTime );
        
return ;
    }

    HRESULT hr;
    D3DXMATRIXA16 mWorld;
    D3DXMATRIXA16 mWorldView;
    D3DXMATRIXA16 mViewProj;
    D3DXMATRIXA16 mWorldViewProjection;

    
//  Clear the render target and the zbuffer 
    V( pd3dDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET  |  D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0 66 75 121 ),  1.0f 0 ) );

    
//  Render the scene
     if ( SUCCEEDED( pd3dDevice -> BeginScene() ) )
    {
        
//  Get the projection & view matrix from the camera class
        mViewProj  =   * g_Camera.GetViewMatrix()  *   * g_Camera.GetProjMatrix();

        
//  Update the effect's variables.  Instead of using strings, it would 
        
//  be more efficient to cache a handle to the parameter by calling 
        
//  ID3DXEffect::GetParameterByName
        D3DXVECTOR4 vLightView(  0.0f 0.0f - 10.0f 1.0f  );
        V( g_pEffect
-> SetVector(  " g_vLight " & vLightView ) );

        
float  fAngleDelta  =  D3DX_PI  *   2.0f   /  g_Meshes.GetSize();
        
for int  i  =   0 ; i  <  g_Meshes.GetSize();  ++ i )
        {
            D3DXMATRIXA16 mWorld 
=   * g_ArcBall[i].GetRotationMatrix()  *   * g_ArcBall[i].GetTranslationMatrix();
            mWorld 
=  g_amWorld[i]  *  mWorld;
            D3DXMATRIXA16 mRot;
            D3DXMATRIXA16 mTrans;
            D3DXMatrixTranslation( 
& mTrans,  0.0f 0.0f - 3.0f  );
            D3DXMatrixRotationY( 
& mRot, fAngleDelta  *  ( i  -  g_nActiveMesh ) );
            mWorld 
*=  mTrans  *  mRot  *  g_mScroll;
            mWorldView 
=  mWorld  *   * g_Camera.GetViewMatrix();
            mWorldViewProjection 
=  mWorld  *  mViewProj;
            V( g_pEffect
-> SetMatrix(  " g_mWorld " & mWorld ) );
            V( g_pEffect
-> SetMatrix(  " g_mView " , g_Camera.GetViewMatrix() ) );
            V( g_pEffect
-> SetMatrix(  " g_mProj " , g_Camera.GetProjMatrix() ) );
            g_Meshes[i].Render( pd3dDevice );
        }

        RenderText();
        V( g_HUD.OnRender( fElapsedTime ) );
        V( g_SampleUI.OnRender( fElapsedTime ) );

        V( pd3dDevice
-> EndScene() );
    }

    
if ( g_fAngleLeftToScroll  ==   0.0f  )
    {
        D3DXMatrixIdentity( 
& g_mScroll );
    }
}


// --------------------------------------------------------------------------------------
//  Render the help and statistics text. This function uses the ID3DXFont interface for 
//  efficient text rendering.
// --------------------------------------------------------------------------------------
void  RenderText()
{
    
//  The helper object simply helps keep track of text position, and color
    
//  and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
    
//  If NULL is passed in as the sprite object, then it will work however the 
    
//  pFont->DrawText() will not be batched together.  Batching calls will improves performance.
    CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite,  15  );

    
//  Output statistics
    txtHelper.Begin();
    txtHelper.SetInsertionPos( 
5 5  );
    txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 1.0f 0.0f 1.0f  ) );
    txtHelper.DrawTextLine( DXUTGetFrameStats(
true ) );  //  Show FPS
    txtHelper.DrawTextLine( DXUTGetDeviceStats() );

    txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 1.0f 1.0f 1.0f  ) );
    txtHelper.DrawFormattedTextLine( L
" Number of meshes: %d\n " , g_Meshes.GetSize() );

    
//  Draw help
     if ( g_bShowHelp )
    {
        
const  D3DSURFACE_DESC *  pd3dsdBackBuffer  =  DXUTGetBackBufferSurfaceDesc();
        txtHelper.SetInsertionPos( 
10 , pd3dsdBackBuffer -> Height - 15 * 6  );
        txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 0.75f 0.0f 1.0f  ) );
        txtHelper.DrawTextLine( L
" Controls (F1 to hide): "  );

        txtHelper.SetInsertionPos( 
40 , pd3dsdBackBuffer -> Height - 15 * 5  );
        txtHelper.DrawTextLine( L
" Rotate Mesh: Left mouse drag\n "
                                L
" Zoom: Mouse wheel\n "
                                L
" Quit: ESC "  );
    }
    
else
    {
        txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 1.0f 1.0f 1.0f  ) );
        txtHelper.DrawTextLine( L
" Press F1 for help "  );
    }

    
//  Draw shared param description
    txtHelper.SetInsertionPos(  5 50  );
    
if ( g_pEffectPool )
    {
        txtHelper.SetForegroundColor( D3DXCOLOR( 
0.0f 1.0f 0.0f 1.0f  ) );
        txtHelper.DrawTextLine( L
" Shared parameters are enabled.  When updating transformation\n "
                                L
" matrices on one effect object, all effect objects automatically\n "
                                L
" see the updated values. "  );
    }
    
else
    {
        txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 0.0f 0.0f 1.0f  ) );
        txtHelper.DrawTextLine( L
" Shared parameters are disabled.  When transformation matrices\n "
                                L
" are updated on the default effect object (diffuse only), only that\n "
                                L
" effect object has the up-to-date values.  All other effect objects\n "
                                L
" do not have valid matrices for rendering. "  );
    }

    txtHelper.End();
}


// --------------------------------------------------------------------------------------
//  Before handling window messages, DXUT passes incoming windows 
//  messages to the application through this callback function. If the application sets 
//  *pbNoFurtherProcessing to TRUE, then DXUT will not process this message.
// --------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,  bool *  pbNoFurtherProcessing,  void *  pUserContext )
{
    
//  Always allow dialog resource manager calls to handle global messages
    
//  so GUI state is updated correctly
     * pbNoFurtherProcessing  =  g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    
if * pbNoFurtherProcessing )
        
return   0 ;

    
if ( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        
return   0 ;
    }

    
//  Give the dialogs a chance to handle the message first
     * pbNoFurtherProcessing  =  g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    
if * pbNoFurtherProcessing )
        
return   0 ;
    
* pbNoFurtherProcessing  =  g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    
if * pbNoFurtherProcessing )
        
return   0 ;

    
//  Pass all remaining windows messages to camera so it can respond to user input
    g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
    D3DXMATRIXA16 mViewRotate 
=   * g_Camera.GetViewMatrix();
    mViewRotate._41 
=  mViewRotate._42  =  mViewRotate._43  =   0.0f ;
    D3DXMatrixInverse( 
& mViewRotate, NULL,  & mViewRotate );
    
if ( g_ArcBall.GetSize()  >   0  )
        g_ArcBall[g_nActiveMesh].HandleMessages( hWnd, uMsg, wParam, lParam, 
& mViewRotate );

    
return   0 ;
}


// --------------------------------------------------------------------------------------
//  As a convenience, DXUT inspects the incoming windows messages for
//  keystroke messages and decodes the message parameters to pass relevant keyboard
//  messages to the application.  The framework does not remove the underlying keystroke 
//  messages, which are still passed to the application's MsgProc callback.
// --------------------------------------------------------------------------------------
void  CALLBACK KeyboardProc( UINT nChar,  bool  bKeyDown,  bool  bAltDown,  void *  pUserContext )
{
    
if ( bKeyDown )
    {
        
switch ( nChar )
        {
            
case  VK_F1: g_bShowHelp  =   ! g_bShowHelp;  break ;
        }
    }
}


// --------------------------------------------------------------------------------------
//  Handles the GUI events
// --------------------------------------------------------------------------------------
void  CALLBACK OnGUIEvent( UINT nEvent,  int  nControlID, CDXUTControl *  pControl,  void *  pUserContext )
{
    
switch ( nControlID )
    {
        
case  IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen();  break ;
        
case  IDC_TOGGLEREF:        DXUTToggleREF();  break ;
        
case  IDC_CHANGEDEVICE:     g_SettingsDlg.SetActive(  ! g_SettingsDlg.IsActive() );  break ;

        
case  IDC_SHARE:
        {
            
//  Shared param status changed. Destroy and recreate everything
            
//  with or without effect pool as appropriate.
             if ( DXUTGetD3DDevice() )
            {
                
//  We need to call the callbacks of the resource manager or the ref
                
//  count will not reach 0.

                OnLostDevice( NULL );
                DXUTGetGlobalResourceCache().OnLostDevice();
                OnDestroyDevice( NULL );
                DXUTGetGlobalResourceCache().OnDestroyDevice();
                OnCreateDevice( DXUTGetD3DDevice(), DXUTGetBackBufferSurfaceDesc(), NULL );
                DXUTGetGlobalResourceCache().OnCreateDevice( DXUTGetD3DDevice() );
                OnResetDevice( DXUTGetD3DDevice(), DXUTGetBackBufferSurfaceDesc(), NULL );
                DXUTGetGlobalResourceCache().OnResetDevice( DXUTGetD3DDevice() );
            }
            
break ;
        }

        
case  IDC_SCROLLLEFT:
        
case  IDC_SCROLLRIGHT:
        {
            
//  Only scroll if we have more than one mesh
             if ( g_Meshes.GetSize()  <=   1  )
                
break ;

            
//  Only scroll if we are not already scrolling
             if ( g_fAngleLeftToScroll  !=   0.0f  )
                
break ;

            
//  Compute the angle to scroll
            g_fAngleToScroll  =  g_fAngleLeftToScroll  =  nControlID  ==  IDC_SCROLLLEFT  ?   - D3DX_PI  *   2.0f   /  g_Meshes.GetSize() :
                                                                                     D3DX_PI 
*   2.0f   /  g_Meshes.GetSize();

            
//  Initialize the scroll matrix to be reverse full-angle rotation,
            
//  then gradually decrease to zero (identity).
            D3DXMatrixRotationY(  & g_mScroll,  - g_fAngleToScroll );
            
//  Update front mesh index
             if ( nControlID  ==  IDC_SCROLLLEFT )
            {
                
++ g_nActiveMesh;
                
if ( g_nActiveMesh  ==  g_Meshes.GetSize() )
                    g_nActiveMesh 
=   0 ;
            }
            
else
            {
                
-- g_nActiveMesh;
                
if ( g_nActiveMesh  <   0  )
                    g_nActiveMesh 
=  g_Meshes.GetSize()  -   1 ;
            }

            
//  Update mesh name and material count
            g_SampleUI.GetStatic( IDC_MESHNAME ) -> SetText( g_MeshListData[g_nActiveMesh].wszName );
            WCHAR wsz[
256 ];
            StringCchPrintf( wsz, 
256 , L " Number of materials: %u " , g_MeshListData[g_nActiveMesh].dwNumMat );
            wsz[
255 =  L ' \0 ' ;
            g_SampleUI.GetStatic( IDC_MATCOUNT )
-> SetText( wsz );

            
break ;
        }
    }
}


// --------------------------------------------------------------------------------------
//  This callback function will be called immediately after the Direct3D device has 
//  entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
//  in the OnResetDevice callback should be released here, which generally includes all 
//  D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
//  information about lost devices.
// --------------------------------------------------------------------------------------
void  CALLBACK OnLostDevice(  void *  pUserContext )
{
    g_DialogResourceManager.OnLostDevice();
    g_SettingsDlg.OnLostDevice();
    
if ( g_pFont )
        g_pFont
-> OnLostDevice();
    
if ( g_pEffect )
        g_pEffect
-> OnLostDevice();
    SAFE_RELEASE(g_pTextSprite);
}


// --------------------------------------------------------------------------------------
//  This callback function will be called immediately after the Direct3D device has 
//  been destroyed, which generally happens as a result of application termination or 
//  windowed/full screen toggles. Resources created in the OnCreateDevice callback 
//  should be released here, which generally includes all D3DPOOL_MANAGED resources. 
// --------------------------------------------------------------------------------------
void  CALLBACK OnDestroyDevice(  void *  pUserContext )
{
    g_DialogResourceManager.OnDestroyDevice();
    g_SettingsDlg.OnDestroyDevice();
    SAFE_RELEASE( g_pEffect );
    SAFE_RELEASE( g_pFont );
    SAFE_RELEASE( g_pDefaultTex );
    SAFE_RELEASE( g_pEffectPool );
    SAFE_RELEASE( g_pDecl );
    SAFE_RELEASE( g_pEnvMapTex );

    
for int  i  =   0 ; i  <  g_Meshes.GetSize();  ++ i )
        g_Meshes[i].Destroy();

    g_Meshes.RemoveAll();
    g_amWorld.RemoveAll();
}








你可能感兴趣的:(《精通DirectX 3D》第二十章 效果 04_EffectParam)