《精通DirectX 3D》第二十章 效果 05_FragmentLinker
fragment就是hlsl积木,方便组合、去除、添加。
FragmentLinker.fx
//
==============================================================
// Desc: Effect文件
// ==============================================================
// --------------------------------------------------------------
// 全局变量
// --------------------------------------------------------------
float4 g_vMaterialAmbient = float4( 0.3f , 0.3f , 0.3f , 1.0f );
float4 g_vMaterialDiffuse = float4( 0.6f , 0.6f , 0.6f , 1.0f );
float4 g_vLightColor = float4( 1.0f , 1.0f , 1.0f , 1.0f );
float3 g_vLightPosition = float3( 0.0f , 5.0f , - 5.0f );
texture g_MeshTexture;
float g_fTime;
float4x4 g_mWorld;
float4x4 g_mWorldViewProjection;
// --------------------------------------------------------------
// 纹理采样器
// --------------------------------------------------------------
sampler MeshTextureSampler:s0;
// ---------------------------------------------------------------
// 顶点渲染器段落, Projection transform
// ---------------------------------------------------------------
void Projection( float4 vPosObject: POSITION,
float3 vNormalObject: NORMAL,
float2 vTexCoordIn: TEXCOORD0,
out float4 vPosWorld: r_PosWorld,
out float3 vNormalWorld: r_NormalWorld,
out float4 vPosProj: POSITION,
out float2 vTexCoordOut: TEXCOORD0,
uniform bool bAnimate )
{
// 动画顶点
if ( bAnimate )
vPosObject.x *= ( 1 + sin( g_fTime ) / 2 );
// 顶点坐标变换
vPosProj = mul( vPosObject, g_mWorldViewProjection );
// 将顶点坐标和法线变换到世界空间, 用于光照
vPosWorld = mul( vPosObject, g_mWorld );
vNormalWorld = mul( vNormalObject, (float3x3)g_mWorld );
// 输出纹理坐标
vTexCoordOut = vTexCoordIn;
}
// 顶点渲染器段落声明
vertexfragment ProjectionFragment_Animated = compile_fragment vs_2_0 Projection( true );
vertexfragment ProjectionFragment_Static = compile_fragment vs_2_0 Projection( false );
// ---------------------------------------------------------------
// 顶点渲染器段落, Ambient scene lighting
// ---------------------------------------------------------------
void Ambient( out float4 vColor: COLOR0 )
{
// 计算环境光照颜色
vColor = g_vLightColor * g_vMaterialAmbient;
}
// 像素渲染器段落
vertexfragment AmbientFragment = compile_fragment vs_2_0 Ambient();
// ---------------------------------------------------------------
// 顶点渲染器段落, Diffuse scene lighting
// ---------------------------------------------------------------
void AmbientDiffuse( float3 vPosWorld: r_PosWorld,
float3 vNormalWorld: r_NormalWorld,
out float4 vColor: COLOR0 )
{
// 计算灯光方向
float3 vLight = normalize( g_vLightPosition - vPosWorld );
// 计算环境光照和漫反射光照
vColor = g_vLightColor * g_vMaterialAmbient;
vColor += g_vLightColor * g_vMaterialDiffuse * saturate( dot( vLight, vNormalWorld ) );
}
// 顶点渲染器段落声明
vertexfragment AmbientDiffuseFragment = compile_fragment vs_2_0 AmbientDiffuse();
// --------------------------------------------------------------
// 像素渲染器
// --------------------------------------------------------------
void ModulateTexture( float4 vColorIn: COLOR0,
float2 vTexCoord: TEXCOORD0,
out float4 vColorOut: COLOR0 )
{
// 混合顶点光照颜色和纹理颜色
vColorOut = vColorIn * tex2D( MeshTextureSampler, vTexCoord );
}
// Desc: Effect文件
// ==============================================================
// --------------------------------------------------------------
// 全局变量
// --------------------------------------------------------------
float4 g_vMaterialAmbient = float4( 0.3f , 0.3f , 0.3f , 1.0f );
float4 g_vMaterialDiffuse = float4( 0.6f , 0.6f , 0.6f , 1.0f );
float4 g_vLightColor = float4( 1.0f , 1.0f , 1.0f , 1.0f );
float3 g_vLightPosition = float3( 0.0f , 5.0f , - 5.0f );
texture g_MeshTexture;
float g_fTime;
float4x4 g_mWorld;
float4x4 g_mWorldViewProjection;
// --------------------------------------------------------------
// 纹理采样器
// --------------------------------------------------------------
sampler MeshTextureSampler:s0;
// ---------------------------------------------------------------
// 顶点渲染器段落, Projection transform
// ---------------------------------------------------------------
void Projection( float4 vPosObject: POSITION,
float3 vNormalObject: NORMAL,
float2 vTexCoordIn: TEXCOORD0,
out float4 vPosWorld: r_PosWorld,
out float3 vNormalWorld: r_NormalWorld,
out float4 vPosProj: POSITION,
out float2 vTexCoordOut: TEXCOORD0,
uniform bool bAnimate )
{
// 动画顶点
if ( bAnimate )
vPosObject.x *= ( 1 + sin( g_fTime ) / 2 );
// 顶点坐标变换
vPosProj = mul( vPosObject, g_mWorldViewProjection );
// 将顶点坐标和法线变换到世界空间, 用于光照
vPosWorld = mul( vPosObject, g_mWorld );
vNormalWorld = mul( vNormalObject, (float3x3)g_mWorld );
// 输出纹理坐标
vTexCoordOut = vTexCoordIn;
}
// 顶点渲染器段落声明
vertexfragment ProjectionFragment_Animated = compile_fragment vs_2_0 Projection( true );
vertexfragment ProjectionFragment_Static = compile_fragment vs_2_0 Projection( false );
// ---------------------------------------------------------------
// 顶点渲染器段落, Ambient scene lighting
// ---------------------------------------------------------------
void Ambient( out float4 vColor: COLOR0 )
{
// 计算环境光照颜色
vColor = g_vLightColor * g_vMaterialAmbient;
}
// 像素渲染器段落
vertexfragment AmbientFragment = compile_fragment vs_2_0 Ambient();
// ---------------------------------------------------------------
// 顶点渲染器段落, Diffuse scene lighting
// ---------------------------------------------------------------
void AmbientDiffuse( float3 vPosWorld: r_PosWorld,
float3 vNormalWorld: r_NormalWorld,
out float4 vColor: COLOR0 )
{
// 计算灯光方向
float3 vLight = normalize( g_vLightPosition - vPosWorld );
// 计算环境光照和漫反射光照
vColor = g_vLightColor * g_vMaterialAmbient;
vColor += g_vLightColor * g_vMaterialDiffuse * saturate( dot( vLight, vNormalWorld ) );
}
// 顶点渲染器段落声明
vertexfragment AmbientDiffuseFragment = compile_fragment vs_2_0 AmbientDiffuse();
// --------------------------------------------------------------
// 像素渲染器
// --------------------------------------------------------------
void ModulateTexture( float4 vColorIn: COLOR0,
float2 vTexCoord: TEXCOORD0,
out float4 vColorOut: COLOR0 )
{
// 混合顶点光照颜色和纹理颜色
vColorOut = vColorIn * tex2D( MeshTextureSampler, vTexCoord );
}
//
=============================================================================
// Desc: 主程序源文件
// =============================================================================
#include " dxstdafx.h "
#include " resource.h "
// #define DEBUG_VS // Uncomment this line to debug vertex shaders
// #define DEBUG_PS // Uncomment this line to debug pixel shaders
// -----------------------------------------------------------------------------
// 全局变量
// -----------------------------------------------------------------------------
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; // 对话框
CDXUTMesh g_Mesh; // 网格模型
CModelViewerCamera g_Camera; // 摄影机
D3DXVECTOR3 g_vObjectCenter; // 网格模型外包围球中心
FLOAT g_fObjectRadius; // 网格模型外包围球半径
D3DXMATRIXA16 g_mCenterWorld; // 网格模型世界矩阵
ID3DXFragmentLinker * g_pFragmentLinker = NULL; // 段落链接器
LPD3DXBUFFER g_pCompiledFragments = NULL; // 保存编译过的段落的缓冲区
IDirect3DPixelShader9 * g_pPixelShader = NULL; // 像素渲染器
IDirect3DVertexShader9 * g_pLinkedShader = NULL; // 通过段落链接器链接生成的顶点渲染器
LPD3DXCONSTANTTABLE g_pConstTable = NULL; // 顶点渲染器常量表
// 顶点渲染器使用的全局变量
D3DXVECTOR4 g_vMaterialAmbient( 0.3f , 0.3f , 0.3f , 1.0f );
D3DXVECTOR4 g_vMaterialDiffuse( 0.6f , 0.6f , 0.6f , 1.0f );
D3DXVECTOR4 g_vLightColor ( 1.0f , 1.0f , 1.0f , 1.0f );
D3DXVECTOR4 g_vLightPosition ( 0.0f , 5.0f , - 5.0f , 1.0f );
// -----------------------------------------------------------------------------
// 控件ID
// -----------------------------------------------------------------------------
#define IDC_STATIC -1
#define IDC_TOGGLEFULLSCREEN 1
#define IDC_TOGGLEREF 3
#define IDC_CHANGEDEVICE 4
#define IDC_ANIMATION 5
#define IDC_LIGHTING 6
// -----------------------------------------------------------------------------
// 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();
HRESULT LinkVertexShader();
// -----------------------------------------------------------------------------
// 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设备对象
DXUTCreateWindow( L " FragmentLinker " );
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.SetFont( 1 , L " Arial " , 14 , FW_BOLD );
CDXUTElement * pElement = g_SampleUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
if ( pElement )
{
pElement -> iFont = 1 ;
pElement -> dwTextFormat = DT_LEFT | DT_BOTTOM;
}
CDXUTComboBox * pComboBox = NULL;
g_SampleUI.AddStatic( IDC_STATIC, L " (V)ertex Animation " , 20 , 0 , 105 , 25 );
g_SampleUI.AddComboBox( IDC_ANIMATION, 20 , 25 , 140 , 24 , ' V ' , false , & pComboBox );
if ( pComboBox )
pComboBox -> SetDropHeight( 30 );
g_SampleUI.AddStatic( IDC_STATIC, L " (L)ighting " , 20 , 50 , 105 , 25 );
g_SampleUI.AddComboBox( IDC_LIGHTING, 20 , 75 , 140 , 24 , ' L ' , false , & pComboBox );
if ( pComboBox )
pComboBox -> SetDropHeight( 30 );
}
// -----------------------------------------------------------------------------
// 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 ;
// 检查设备支持的像素渲染器版本
if ( pCaps -> PixelShaderVersion < D3DPS_VERSION( 1 , 1 ) )
return false ;
return true ;
}
// -----------------------------------------------------------------------------
// Desc: 修改Direct3D渲染设备设置
// -----------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings * pDeviceSettings, const D3DCAPS9 * pCaps, void * pUserContext )
{
// 如果硬件不支持, 改为软件顶点处理
if ( (pCaps -> DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
pCaps -> VertexShaderVersion < D3DVS_VERSION( 1 , 1 ) )
{
pDeviceSettings -> BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
// 调试顶点渲染器需要参考设备或软件顶点处理
#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;
V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) );
V_RETURN( g_SettingsDlg.OnCreateDevice( pd3dDevice ) );
// 创建字体
V_RETURN( D3DXCreateFont( pd3dDevice, 15 , 0 , FW_BOLD, 1 , FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
L " Arial " , & g_pFont ) );
WCHAR strPath[MAX_PATH];
// 创建网格模型
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, L " dwarf\\dwarf.x " ) );
V_RETURN( g_Mesh.Create( pd3dDevice, strPath ) );
// 计算网格模型外包围球中心和半径
IDirect3DVertexBuffer9 * pVB = NULL;
V_RETURN( g_Mesh.m_pMesh -> GetVertexBuffer( & pVB ) );
void * pVertices = NULL;
hr = pVB -> Lock( 0 , 0 , & pVertices, 0 );
if ( FAILED(hr) )
{
SAFE_RELEASE( pVB );
return hr;
}
hr = D3DXComputeBoundingSphere( (D3DXVECTOR3 * )pVertices, g_Mesh.m_pMesh -> GetNumVertices(),
D3DXGetFVFVertexSize(g_Mesh.m_pMesh -> GetFVF()), & g_vObjectCenter,
& g_fObjectRadius );
pVB -> Unlock();
SAFE_RELEASE( pVB );
if ( FAILED(hr) )
return hr;
// 将网格模型移动到窗口中心
D3DXMatrixTranslation( & g_mCenterWorld, - g_vObjectCenter.x, - g_vObjectCenter.y, - g_vObjectCenter.z );
// 编译段落代码到指定的缓冲区
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, L " FragmentLinker.fx " ) );
V_RETURN( D3DXGatherFragmentsFromFile( strPath, NULL, NULL, 0 , & g_pCompiledFragments, NULL ) );
// 创建段落链接器
V_RETURN( D3DXCreateFragmentLinker( pd3dDevice, 0 , & g_pFragmentLinker ) );
// 将段落添加到链接器
V_RETURN( g_pFragmentLinker -> AddFragments( (DWORD * )g_pCompiledFragments -> GetBufferPointer() ) );
// 获取并保存各段落句柄
//hew: 把选项加到下拉框里
CDXUTComboBox * pComboBox = NULL;
pComboBox = g_SampleUI.GetComboBox( IDC_LIGHTING );
pComboBox -> RemoveAllItems();
pComboBox -> AddItem( L " Ambient " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " AmbientFragment " ) );
pComboBox -> AddItem( L " Ambient & Diffuse " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " AmbientDiffuseFragment " ) );
pComboBox = g_SampleUI.GetComboBox( IDC_ANIMATION );
pComboBox -> RemoveAllItems();
pComboBox -> AddItem( L " On " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " ProjectionFragment_Animated " ) );
pComboBox -> AddItem( L " Off " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " ProjectionFragment_Static " ) );
// 链接段落生成顶点渲染器
V_RETURN( LinkVertexShader() );
// 查找效果文件, 编译像素渲染器
ID3DXBuffer * pCode;
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, L " FragmentLinker.fx " ) );
V_RETURN( D3DXCompileShaderFromFile( strPath, NULL, NULL, " ModulateTexture " , " ps_2_0 " , 0 , & pCode, NULL, NULL ) );
// 创建像素渲染器
hr = pd3dDevice -> CreatePixelShader( (DWORD * )pCode -> GetBufferPointer(), & g_pPixelShader );
pCode -> Release();
// 设置像素渲染器
V_RETURN( pd3dDevice -> SetPixelShader(g_pPixelShader) );
// 设置摄影机观察参数
D3DXVECTOR3 vecEye( 3.0f , 0.0f , - 3.0f );
D3DXVECTOR3 vecAt ( 0.0f , 0.0f , - 0.0f );
g_Camera.SetViewParams( & vecEye, & vecAt );
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 辅助函数, 链接段落生成顶点渲染器, 具体链接哪些段落通过下拉列表指定
// -----------------------------------------------------------------------------
HRESULT LinkVertexShader()
{
HRESULT hr;
ID3DXBuffer * pCode;
DWORD * pShaderCode;
IDirect3DDevice9 * pd3dDevice = DXUTGetD3DDevice();
const int NUM_FRAGMENTS = 2 ;
D3DXHANDLE aHandles[ NUM_FRAGMENTS ] = { 0 };
// hew: 取下拉框的选项
aHandles[ 0 ] = (D3DXHANDLE) g_SampleUI.GetComboBox( IDC_ANIMATION ) -> GetSelectedData();
aHandles[ 1 ] = (D3DXHANDLE) g_SampleUI.GetComboBox( IDC_LIGHTING ) -> GetSelectedData();
// 先释放原来链接生成的顶点渲染器
SAFE_RELEASE( g_pLinkedShader );
// 链接段落生成顶点渲染器, 并获取顶点渲染器常量列表
// hew: 根据下拉框的项LinkShader
V_RETURN( g_pFragmentLinker -> LinkShader( " vs_2_0 " , 0 , aHandles, NUM_FRAGMENTS, & pCode, NULL ) );
pShaderCode = (DWORD * ) pCode -> GetBufferPointer();
V_RETURN( pd3dDevice -> CreateVertexShader( pShaderCode, & g_pLinkedShader ) );
V_RETURN( D3DXGetShaderConstantTable( pShaderCode, & g_pConstTable ) );
SAFE_RELEASE( pCode );
// 为当前渲染设备设置顶点渲染器
V_RETURN( pd3dDevice -> SetVertexShader( g_pLinkedShader ) );
// 通过常量表为顶点渲染器设置全局变量
if (g_pConstTable)
{
g_pConstTable -> SetVector( pd3dDevice, " g_vMaterialAmbient " , & g_vMaterialAmbient );
g_pConstTable -> SetVector( pd3dDevice, " g_vMaterialDiffuse " , & g_vMaterialDiffuse );
g_pConstTable -> SetVector( pd3dDevice, " g_vLightColor " , & g_vLightColor );
g_pConstTable -> SetVector( pd3dDevice, " g_vLightPosition " , & g_vLightPosition );
}
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 在此创建默认内存类型资源对象
// -----------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9 * pd3dDevice,
const D3DSURFACE_DESC * pBackBufferSurfaceDesc, void * pUserContext )
{
HRESULT hr;
V_RETURN( g_DialogResourceManager.OnResetDevice() );
V_RETURN( g_SettingsDlg.OnResetDevice() );
// 设置对话框位置和尺寸
g_HUD.SetLocation( pBackBufferSurfaceDesc -> Width - 170 , 0 );
g_HUD.SetSize( 170 , 170 );
g_SampleUI.SetLocation( pBackBufferSurfaceDesc -> Width - 170 , pBackBufferSurfaceDesc -> Height - 350 );
g_SampleUI.SetSize( 170 , 300 );
// 恢复字体
if ( g_pFont )
V_RETURN( g_pFont -> OnResetDevice() );
// 创建ID3DXSprite接口对象
V_RETURN( D3DXCreateSprite( pd3dDevice, & g_pTextSprite ) );
// 设置摄影机投影参数
float fAspectRatio = pBackBufferSurfaceDesc -> Width / (FLOAT)pBackBufferSurfaceDesc -> Height;
g_Camera.SetProjParams( D3DX_PI / 4 , fAspectRatio, 0.1f , 1000.0f );
g_Camera.SetWindow( pBackBufferSurfaceDesc -> Width, pBackBufferSurfaceDesc -> Height );
// 链接段落生成顶点渲染器
V_RETURN(LinkVertexShader());
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 更新场景
// -----------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9 * pd3dDevice, double fTime,
float fElapsedTime, void * pUserContext )
{
D3DXMATRIXA16 mWorld;
D3DXMATRIXA16 mView;
D3DXMATRIXA16 mProj;
D3DXMATRIXA16 mWorldViewProjection;
// 根据用户输入更新摄影机位置
g_Camera.FrameMove( fElapsedTime );
// 通过摄影机获取观察和投影矩阵
mWorld = g_mCenterWorld * * g_Camera.GetWorldMatrix();
mProj = * g_Camera.GetProjMatrix();
mView = * g_Camera.GetViewMatrix();
mWorldViewProjection = mWorld * mView * mProj;
// 通过常量表, 为渲染器设置全局变量
if (g_pConstTable)
{
g_pConstTable -> SetMatrix( pd3dDevice, " g_mWorldViewProjection " , & mWorldViewProjection );
g_pConstTable -> SetMatrix( pd3dDevice, " g_mWorld " , & mWorld );
g_pConstTable -> SetFloat( pd3dDevice, " g_fTime " , ( float )fTime );
}
}
// -----------------------------------------------------------------------------
// Desc: 渲染场景
// -----------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9 * pd3dDevice, double fTime, float fElapsedTime, void * pUserContext )
{
// 如果正在利用Direct3D设备设置对话框进行设置, 则不渲染场景
if ( g_SettingsDlg.IsActive() )
{
g_SettingsDlg.OnRender( fElapsedTime );
return ;
}
HRESULT hr;
// 清除后台颜色缓冲区和深度缓冲区
V( pd3dDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0 , 45 , 50 , 170 ), 1.0f , 0 ) );
// 渲染场景
if ( SUCCEEDED( pd3dDevice -> BeginScene() ) )
{
// 渲染网格模型
V( g_Mesh.Render( pd3dDevice ) );
// 渲染文本和控件
RenderText();
V( g_HUD.OnRender( fElapsedTime ) );
V( g_SampleUI.OnRender( fElapsedTime ) );
V( pd3dDevice -> EndScene() );
}
}
// -----------------------------------------------------------------------------
// Desc: 渲染文本
// -----------------------------------------------------------------------------
void RenderText()
{
CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
// 显示当前Direct3D设备状态和渲染帧速率
txtHelper.Begin();
txtHelper.SetInsertionPos( 5 , 5 );
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 0.0f , 1.0f ) );
txtHelper.DrawTextLine( DXUTGetFrameStats( true ) );
txtHelper.DrawTextLine( DXUTGetDeviceStats() );
txtHelper.DrawTextLine( L " Selected fragments are linked on-the-fly to create the current shader " );
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 1.0f , 1.0f ) );
// 显示其他简要信息
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 1.0f , 1.0f ) );
txtHelper.DrawTextLine( L " 段落(Fragment)使用示例程序 " );
// 显示简单帮助文本
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: " );
txtHelper.SetInsertionPos( 20 , pd3dsdBackBuffer -> Height - 15 * 5 );
txtHelper.DrawTextLine( L " Rotate model: Left mouse button\n "
L " Rotate camera: Right mouse button\n "
L " Zoom camera: Mouse wheel scroll\n " );
txtHelper.SetInsertionPos( 250 , pd3dsdBackBuffer -> Height - 15 * 5 );
txtHelper.DrawTextLine( L " Hide help: F1\n "
L " Quit: ESC\n " );
}
else
{
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 1.0f , 1.0f ) );
txtHelper.DrawTextLine( L " Press F1 for help " );
}
txtHelper.End();
}
// -----------------------------------------------------------------------------
// Desc: 消息处理
// -----------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool * pbNoFurtherProcessing, void * pUserContext )
{
* 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 ;
}
* pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
if ( * pbNoFurtherProcessing )
return 0 ;
* pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
if ( * pbNoFurtherProcessing )
return 0 ;
g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
return 0 ;
}
// -----------------------------------------------------------------------------
// Desc: 键盘消息处理
// -----------------------------------------------------------------------------
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void * pUserContext )
{
if ( bKeyDown )
{
switch ( nChar )
{
case VK_F1: g_bShowHelp = ! g_bShowHelp; break ;
}
}
}
// -----------------------------------------------------------------------------
// Desc: 各种控件消息处理
// -----------------------------------------------------------------------------
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_ANIMATION: LinkVertexShader(); break ;
case IDC_LIGHTING: LinkVertexShader(); break ;
}
}
// -----------------------------------------------------------------------------
// Desc: 释放在OnResetDevice()中创建的资源
// -----------------------------------------------------------------------------
void CALLBACK OnLostDevice( void * pUserContext )
{
g_DialogResourceManager.OnLostDevice();
g_SettingsDlg.OnLostDevice();
if ( g_pFont )
g_pFont -> OnLostDevice();
SAFE_RELEASE(g_pTextSprite);
}
// ------------------------------------------------------------------------------
// Desc: 释放在OnCreateDevice()中创建的资源
// ------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void * pUserContext )
{
g_DialogResourceManager.OnDestroyDevice();
g_SettingsDlg.OnDestroyDevice();
SAFE_RELEASE( g_pPixelShader );
SAFE_RELEASE( g_pLinkedShader );
SAFE_RELEASE( g_pFont );
g_Mesh.Destroy();
SAFE_RELEASE( g_pFragmentLinker );
SAFE_RELEASE( g_pCompiledFragments );
}
// Desc: 主程序源文件
// =============================================================================
#include " dxstdafx.h "
#include " resource.h "
// #define DEBUG_VS // Uncomment this line to debug vertex shaders
// #define DEBUG_PS // Uncomment this line to debug pixel shaders
// -----------------------------------------------------------------------------
// 全局变量
// -----------------------------------------------------------------------------
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; // 对话框
CDXUTMesh g_Mesh; // 网格模型
CModelViewerCamera g_Camera; // 摄影机
D3DXVECTOR3 g_vObjectCenter; // 网格模型外包围球中心
FLOAT g_fObjectRadius; // 网格模型外包围球半径
D3DXMATRIXA16 g_mCenterWorld; // 网格模型世界矩阵
ID3DXFragmentLinker * g_pFragmentLinker = NULL; // 段落链接器
LPD3DXBUFFER g_pCompiledFragments = NULL; // 保存编译过的段落的缓冲区
IDirect3DPixelShader9 * g_pPixelShader = NULL; // 像素渲染器
IDirect3DVertexShader9 * g_pLinkedShader = NULL; // 通过段落链接器链接生成的顶点渲染器
LPD3DXCONSTANTTABLE g_pConstTable = NULL; // 顶点渲染器常量表
// 顶点渲染器使用的全局变量
D3DXVECTOR4 g_vMaterialAmbient( 0.3f , 0.3f , 0.3f , 1.0f );
D3DXVECTOR4 g_vMaterialDiffuse( 0.6f , 0.6f , 0.6f , 1.0f );
D3DXVECTOR4 g_vLightColor ( 1.0f , 1.0f , 1.0f , 1.0f );
D3DXVECTOR4 g_vLightPosition ( 0.0f , 5.0f , - 5.0f , 1.0f );
// -----------------------------------------------------------------------------
// 控件ID
// -----------------------------------------------------------------------------
#define IDC_STATIC -1
#define IDC_TOGGLEFULLSCREEN 1
#define IDC_TOGGLEREF 3
#define IDC_CHANGEDEVICE 4
#define IDC_ANIMATION 5
#define IDC_LIGHTING 6
// -----------------------------------------------------------------------------
// 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();
HRESULT LinkVertexShader();
// -----------------------------------------------------------------------------
// 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设备对象
DXUTCreateWindow( L " FragmentLinker " );
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.SetFont( 1 , L " Arial " , 14 , FW_BOLD );
CDXUTElement * pElement = g_SampleUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
if ( pElement )
{
pElement -> iFont = 1 ;
pElement -> dwTextFormat = DT_LEFT | DT_BOTTOM;
}
CDXUTComboBox * pComboBox = NULL;
g_SampleUI.AddStatic( IDC_STATIC, L " (V)ertex Animation " , 20 , 0 , 105 , 25 );
g_SampleUI.AddComboBox( IDC_ANIMATION, 20 , 25 , 140 , 24 , ' V ' , false , & pComboBox );
if ( pComboBox )
pComboBox -> SetDropHeight( 30 );
g_SampleUI.AddStatic( IDC_STATIC, L " (L)ighting " , 20 , 50 , 105 , 25 );
g_SampleUI.AddComboBox( IDC_LIGHTING, 20 , 75 , 140 , 24 , ' L ' , false , & pComboBox );
if ( pComboBox )
pComboBox -> SetDropHeight( 30 );
}
// -----------------------------------------------------------------------------
// 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 ;
// 检查设备支持的像素渲染器版本
if ( pCaps -> PixelShaderVersion < D3DPS_VERSION( 1 , 1 ) )
return false ;
return true ;
}
// -----------------------------------------------------------------------------
// Desc: 修改Direct3D渲染设备设置
// -----------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings * pDeviceSettings, const D3DCAPS9 * pCaps, void * pUserContext )
{
// 如果硬件不支持, 改为软件顶点处理
if ( (pCaps -> DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
pCaps -> VertexShaderVersion < D3DVS_VERSION( 1 , 1 ) )
{
pDeviceSettings -> BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
// 调试顶点渲染器需要参考设备或软件顶点处理
#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;
V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) );
V_RETURN( g_SettingsDlg.OnCreateDevice( pd3dDevice ) );
// 创建字体
V_RETURN( D3DXCreateFont( pd3dDevice, 15 , 0 , FW_BOLD, 1 , FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
L " Arial " , & g_pFont ) );
WCHAR strPath[MAX_PATH];
// 创建网格模型
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, L " dwarf\\dwarf.x " ) );
V_RETURN( g_Mesh.Create( pd3dDevice, strPath ) );
// 计算网格模型外包围球中心和半径
IDirect3DVertexBuffer9 * pVB = NULL;
V_RETURN( g_Mesh.m_pMesh -> GetVertexBuffer( & pVB ) );
void * pVertices = NULL;
hr = pVB -> Lock( 0 , 0 , & pVertices, 0 );
if ( FAILED(hr) )
{
SAFE_RELEASE( pVB );
return hr;
}
hr = D3DXComputeBoundingSphere( (D3DXVECTOR3 * )pVertices, g_Mesh.m_pMesh -> GetNumVertices(),
D3DXGetFVFVertexSize(g_Mesh.m_pMesh -> GetFVF()), & g_vObjectCenter,
& g_fObjectRadius );
pVB -> Unlock();
SAFE_RELEASE( pVB );
if ( FAILED(hr) )
return hr;
// 将网格模型移动到窗口中心
D3DXMatrixTranslation( & g_mCenterWorld, - g_vObjectCenter.x, - g_vObjectCenter.y, - g_vObjectCenter.z );
// 编译段落代码到指定的缓冲区
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, L " FragmentLinker.fx " ) );
V_RETURN( D3DXGatherFragmentsFromFile( strPath, NULL, NULL, 0 , & g_pCompiledFragments, NULL ) );
// 创建段落链接器
V_RETURN( D3DXCreateFragmentLinker( pd3dDevice, 0 , & g_pFragmentLinker ) );
// 将段落添加到链接器
V_RETURN( g_pFragmentLinker -> AddFragments( (DWORD * )g_pCompiledFragments -> GetBufferPointer() ) );
// 获取并保存各段落句柄
//hew: 把选项加到下拉框里
CDXUTComboBox * pComboBox = NULL;
pComboBox = g_SampleUI.GetComboBox( IDC_LIGHTING );
pComboBox -> RemoveAllItems();
pComboBox -> AddItem( L " Ambient " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " AmbientFragment " ) );
pComboBox -> AddItem( L " Ambient & Diffuse " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " AmbientDiffuseFragment " ) );
pComboBox = g_SampleUI.GetComboBox( IDC_ANIMATION );
pComboBox -> RemoveAllItems();
pComboBox -> AddItem( L " On " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " ProjectionFragment_Animated " ) );
pComboBox -> AddItem( L " Off " , ( void * ) g_pFragmentLinker -> GetFragmentHandleByName( " ProjectionFragment_Static " ) );
// 链接段落生成顶点渲染器
V_RETURN( LinkVertexShader() );
// 查找效果文件, 编译像素渲染器
ID3DXBuffer * pCode;
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, L " FragmentLinker.fx " ) );
V_RETURN( D3DXCompileShaderFromFile( strPath, NULL, NULL, " ModulateTexture " , " ps_2_0 " , 0 , & pCode, NULL, NULL ) );
// 创建像素渲染器
hr = pd3dDevice -> CreatePixelShader( (DWORD * )pCode -> GetBufferPointer(), & g_pPixelShader );
pCode -> Release();
// 设置像素渲染器
V_RETURN( pd3dDevice -> SetPixelShader(g_pPixelShader) );
// 设置摄影机观察参数
D3DXVECTOR3 vecEye( 3.0f , 0.0f , - 3.0f );
D3DXVECTOR3 vecAt ( 0.0f , 0.0f , - 0.0f );
g_Camera.SetViewParams( & vecEye, & vecAt );
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 辅助函数, 链接段落生成顶点渲染器, 具体链接哪些段落通过下拉列表指定
// -----------------------------------------------------------------------------
HRESULT LinkVertexShader()
{
HRESULT hr;
ID3DXBuffer * pCode;
DWORD * pShaderCode;
IDirect3DDevice9 * pd3dDevice = DXUTGetD3DDevice();
const int NUM_FRAGMENTS = 2 ;
D3DXHANDLE aHandles[ NUM_FRAGMENTS ] = { 0 };
// hew: 取下拉框的选项
aHandles[ 0 ] = (D3DXHANDLE) g_SampleUI.GetComboBox( IDC_ANIMATION ) -> GetSelectedData();
aHandles[ 1 ] = (D3DXHANDLE) g_SampleUI.GetComboBox( IDC_LIGHTING ) -> GetSelectedData();
// 先释放原来链接生成的顶点渲染器
SAFE_RELEASE( g_pLinkedShader );
// 链接段落生成顶点渲染器, 并获取顶点渲染器常量列表
// hew: 根据下拉框的项LinkShader
V_RETURN( g_pFragmentLinker -> LinkShader( " vs_2_0 " , 0 , aHandles, NUM_FRAGMENTS, & pCode, NULL ) );
pShaderCode = (DWORD * ) pCode -> GetBufferPointer();
V_RETURN( pd3dDevice -> CreateVertexShader( pShaderCode, & g_pLinkedShader ) );
V_RETURN( D3DXGetShaderConstantTable( pShaderCode, & g_pConstTable ) );
SAFE_RELEASE( pCode );
// 为当前渲染设备设置顶点渲染器
V_RETURN( pd3dDevice -> SetVertexShader( g_pLinkedShader ) );
// 通过常量表为顶点渲染器设置全局变量
if (g_pConstTable)
{
g_pConstTable -> SetVector( pd3dDevice, " g_vMaterialAmbient " , & g_vMaterialAmbient );
g_pConstTable -> SetVector( pd3dDevice, " g_vMaterialDiffuse " , & g_vMaterialDiffuse );
g_pConstTable -> SetVector( pd3dDevice, " g_vLightColor " , & g_vLightColor );
g_pConstTable -> SetVector( pd3dDevice, " g_vLightPosition " , & g_vLightPosition );
}
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 在此创建默认内存类型资源对象
// -----------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9 * pd3dDevice,
const D3DSURFACE_DESC * pBackBufferSurfaceDesc, void * pUserContext )
{
HRESULT hr;
V_RETURN( g_DialogResourceManager.OnResetDevice() );
V_RETURN( g_SettingsDlg.OnResetDevice() );
// 设置对话框位置和尺寸
g_HUD.SetLocation( pBackBufferSurfaceDesc -> Width - 170 , 0 );
g_HUD.SetSize( 170 , 170 );
g_SampleUI.SetLocation( pBackBufferSurfaceDesc -> Width - 170 , pBackBufferSurfaceDesc -> Height - 350 );
g_SampleUI.SetSize( 170 , 300 );
// 恢复字体
if ( g_pFont )
V_RETURN( g_pFont -> OnResetDevice() );
// 创建ID3DXSprite接口对象
V_RETURN( D3DXCreateSprite( pd3dDevice, & g_pTextSprite ) );
// 设置摄影机投影参数
float fAspectRatio = pBackBufferSurfaceDesc -> Width / (FLOAT)pBackBufferSurfaceDesc -> Height;
g_Camera.SetProjParams( D3DX_PI / 4 , fAspectRatio, 0.1f , 1000.0f );
g_Camera.SetWindow( pBackBufferSurfaceDesc -> Width, pBackBufferSurfaceDesc -> Height );
// 链接段落生成顶点渲染器
V_RETURN(LinkVertexShader());
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 更新场景
// -----------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9 * pd3dDevice, double fTime,
float fElapsedTime, void * pUserContext )
{
D3DXMATRIXA16 mWorld;
D3DXMATRIXA16 mView;
D3DXMATRIXA16 mProj;
D3DXMATRIXA16 mWorldViewProjection;
// 根据用户输入更新摄影机位置
g_Camera.FrameMove( fElapsedTime );
// 通过摄影机获取观察和投影矩阵
mWorld = g_mCenterWorld * * g_Camera.GetWorldMatrix();
mProj = * g_Camera.GetProjMatrix();
mView = * g_Camera.GetViewMatrix();
mWorldViewProjection = mWorld * mView * mProj;
// 通过常量表, 为渲染器设置全局变量
if (g_pConstTable)
{
g_pConstTable -> SetMatrix( pd3dDevice, " g_mWorldViewProjection " , & mWorldViewProjection );
g_pConstTable -> SetMatrix( pd3dDevice, " g_mWorld " , & mWorld );
g_pConstTable -> SetFloat( pd3dDevice, " g_fTime " , ( float )fTime );
}
}
// -----------------------------------------------------------------------------
// Desc: 渲染场景
// -----------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9 * pd3dDevice, double fTime, float fElapsedTime, void * pUserContext )
{
// 如果正在利用Direct3D设备设置对话框进行设置, 则不渲染场景
if ( g_SettingsDlg.IsActive() )
{
g_SettingsDlg.OnRender( fElapsedTime );
return ;
}
HRESULT hr;
// 清除后台颜色缓冲区和深度缓冲区
V( pd3dDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0 , 45 , 50 , 170 ), 1.0f , 0 ) );
// 渲染场景
if ( SUCCEEDED( pd3dDevice -> BeginScene() ) )
{
// 渲染网格模型
V( g_Mesh.Render( pd3dDevice ) );
// 渲染文本和控件
RenderText();
V( g_HUD.OnRender( fElapsedTime ) );
V( g_SampleUI.OnRender( fElapsedTime ) );
V( pd3dDevice -> EndScene() );
}
}
// -----------------------------------------------------------------------------
// Desc: 渲染文本
// -----------------------------------------------------------------------------
void RenderText()
{
CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
// 显示当前Direct3D设备状态和渲染帧速率
txtHelper.Begin();
txtHelper.SetInsertionPos( 5 , 5 );
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 0.0f , 1.0f ) );
txtHelper.DrawTextLine( DXUTGetFrameStats( true ) );
txtHelper.DrawTextLine( DXUTGetDeviceStats() );
txtHelper.DrawTextLine( L " Selected fragments are linked on-the-fly to create the current shader " );
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 1.0f , 1.0f ) );
// 显示其他简要信息
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 1.0f , 1.0f ) );
txtHelper.DrawTextLine( L " 段落(Fragment)使用示例程序 " );
// 显示简单帮助文本
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: " );
txtHelper.SetInsertionPos( 20 , pd3dsdBackBuffer -> Height - 15 * 5 );
txtHelper.DrawTextLine( L " Rotate model: Left mouse button\n "
L " Rotate camera: Right mouse button\n "
L " Zoom camera: Mouse wheel scroll\n " );
txtHelper.SetInsertionPos( 250 , pd3dsdBackBuffer -> Height - 15 * 5 );
txtHelper.DrawTextLine( L " Hide help: F1\n "
L " Quit: ESC\n " );
}
else
{
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f , 1.0f , 1.0f , 1.0f ) );
txtHelper.DrawTextLine( L " Press F1 for help " );
}
txtHelper.End();
}
// -----------------------------------------------------------------------------
// Desc: 消息处理
// -----------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool * pbNoFurtherProcessing, void * pUserContext )
{
* 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 ;
}
* pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
if ( * pbNoFurtherProcessing )
return 0 ;
* pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
if ( * pbNoFurtherProcessing )
return 0 ;
g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
return 0 ;
}
// -----------------------------------------------------------------------------
// Desc: 键盘消息处理
// -----------------------------------------------------------------------------
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void * pUserContext )
{
if ( bKeyDown )
{
switch ( nChar )
{
case VK_F1: g_bShowHelp = ! g_bShowHelp; break ;
}
}
}
// -----------------------------------------------------------------------------
// Desc: 各种控件消息处理
// -----------------------------------------------------------------------------
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_ANIMATION: LinkVertexShader(); break ;
case IDC_LIGHTING: LinkVertexShader(); break ;
}
}
// -----------------------------------------------------------------------------
// Desc: 释放在OnResetDevice()中创建的资源
// -----------------------------------------------------------------------------
void CALLBACK OnLostDevice( void * pUserContext )
{
g_DialogResourceManager.OnLostDevice();
g_SettingsDlg.OnLostDevice();
if ( g_pFont )
g_pFont -> OnLostDevice();
SAFE_RELEASE(g_pTextSprite);
}
// ------------------------------------------------------------------------------
// Desc: 释放在OnCreateDevice()中创建的资源
// ------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void * pUserContext )
{
g_DialogResourceManager.OnDestroyDevice();
g_SettingsDlg.OnDestroyDevice();
SAFE_RELEASE( g_pPixelShader );
SAFE_RELEASE( g_pLinkedShader );
SAFE_RELEASE( g_pFont );
g_Mesh.Destroy();
SAFE_RELEASE( g_pFragmentLinker );
SAFE_RELEASE( g_pCompiledFragments );
}