【Direct3D】光照與材質

//-----------------------------------【程序說明】----------------------------------------------

//	 程序運行說明: 按鍵盤上數字鍵“1”鍵和“2”鍵可以在實體填充模式和線框填充模式之間切換。默認情況下是線框填充
//------------------------------------------------------------------------------------------------

//-----------------------------------【頭文件包含部分】---------------------------------------
//	描述:包含程序所依賴的頭文件
//------------------------------------------------------------------------------------------------
#include <d3d9.h>
#include <d3dx9.h>
#include <tchar.h>

//-----------------------------------【庫文件包含部分】---------------------------------------
//	描述:包含程序所依賴的庫文件
//------------------------------------------------------------------------------------------------
#pragma comment(lib,"winmm.lib")  //調用PlaySound函數所需庫文件
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")

//-----------------------------------【宏定義部分】--------------------------------------------
//	描述:定義一些輔助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_WIDTH	800							//爲窗口寬度定義的宏,以方便在此處修改窗口寬度
#define WINDOW_HEIGHT	600							//爲窗口高度定義的宏,以方便在此處修改窗口高度
#define WINDOW_TITLE	L"光照與材質"	//爲窗口標題定義的宏
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }   //定義一個安全釋放宏,便於後面COM接口指針的釋放



//-----------------------------------【全局變量聲明部分】-------------------------------------
//	描述:全局變量的聲明
//------------------------------------------------------------------------------------------------
LPDIRECT3DDEVICE9					g_pd3dDevice = NULL; //Direct3D設備對象
ID3DXFont*								g_pFont=NULL;    //字體COM接口
float											g_FPS = 0.0f;       //一個浮點型的變量,代表幀速率
wchar_t										g_strFPS[50];    //包含幀速率的字符數組
LPD3DXMESH							g_teapot = NULL;		//茶壺對象
LPD3DXMESH 							g_cube = NULL;			//立方體(盒子)對象
LPD3DXMESH 							g_sphere = NULL;		//球面體對象
LPD3DXMESH 							g_torus = NULL;		//圓環對象
D3DXMATRIX 							g_WorldMatrix[4],R;  //定義一些全局的世界矩陣


//-----------------------------------【全局函數聲明部分】-------------------------------------
//	描述:全局函數聲明,防止“未聲明的標識”系列錯誤
//------------------------------------------------------------------------------------------------
LRESULT CALLBACK	WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );//窗口過程函數
HRESULT					Direct3D_Init(HWND hwnd);		 //在這個函數中進行Direct3D的初始化
HRESULT					Objects_Init(HWND hwnd); 		//在這個函數中進行要繪製的物體的資源初始化
VOID							Direct3D_Render(HWND hwnd); 	//在這個函數中進行Direct3D渲染代碼的書寫
VOID							Direct3D_CleanUp( );					//在這個函數中清理COM資源以及其他資源
float							Get_FPS();									//計算幀數的函數
VOID							Matrix_Set();                              //封裝了四大變換的函數
void							Light_Set(LPDIRECT3DDEVICE9 pd3dDevice, UINT nType);  //封裝了光照的函數

//-----------------------------------【WinMain( )函數】--------------------------------------
//	描述:Windows應用程序的入口函數,我們的程序從這裏開始
//------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
	//【1】窗口創建四步曲之一:開始設計一個完整的窗口類
	WNDCLASSEX wndClass = { 0 };							//用WINDCLASSEX定義了一個窗口類
	wndClass.cbSize = sizeof( WNDCLASSEX ) ;			//設置結構體的字節數大小
	wndClass.style = CS_HREDRAW | CS_VREDRAW;	//設置窗口的樣式
	wndClass.lpfnWndProc = WndProc;					//設置指向窗口過程函數的指針
	wndClass.cbClsExtra		= 0;								//窗口類的附加內存,取0就可以了
	wndClass.cbWndExtra		= 0;							//窗口的附加內存,依然取0就行了
	wndClass.hInstance = hInstance;						//指定包含窗口過程的程序的實例句柄。
	wndClass.hIcon=(HICON)::LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);  //本地加載自定義ico圖標
	wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );    //指定窗口類的光標句柄。
	wndClass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);  //爲hbrBackground成員指定一個白色畫刷句柄	
	wndClass.lpszMenuName = NULL;						//用一個以空終止的字符串,指定菜單資源的名字。
	wndClass.lpszClassName = L"ForTheDreamOfGameDevelop";		//用一個以空終止的字符串,指定窗口類的名字。

	//【2】窗口創建四步曲之二:註冊窗口類
	if( !RegisterClassEx( &wndClass ) )				//設計完窗口後,需要對窗口類進行註冊,這樣才能創建該類型的窗口
		return -1;		

	//【3】窗口創建四步曲之三:正式創建窗口
	HWND hwnd = CreateWindow( L"ForTheDreamOfGameDevelop",WINDOW_TITLE,				//喜聞樂見的創建窗口函數CreateWindow
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
		WINDOW_HEIGHT, NULL, NULL, hInstance, NULL );

	//Direct3D資源的初始化,調用失敗用messagebox予以顯示
	if (!(S_OK==Direct3D_Init (hwnd)))
	{
		MessageBox(hwnd, _T("Direct3D初始化失敗~!"), _T("淺墨的消息窗口"), 0); //使用MessageBox函數,創建一個消息窗口 
	}

	//【4】窗口創建四步曲之四:窗口的移動、顯示與更新
	MoveWindow(hwnd,250,80,WINDOW_WIDTH,WINDOW_HEIGHT,true);		//調整窗口顯示時的位置,使窗口左上角位於(250,80)處
	ShowWindow( hwnd, nShowCmd );    //調用ShowWindow函數來顯示窗口
	UpdateWindow(hwnd);						//對窗口進行更新,就像我們買了新房子要裝修一樣

	PlaySound(L"ファングのテーマ.wav", NULL, SND_FILENAME | SND_ASYNC|SND_LOOP); //循環播放背景音樂 

	//【5】消息循環過程
	MSG msg = { 0 };  //初始化msg
	while( msg.message != WM_QUIT )			//使用while循環
	{
		if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )   //查看應用程序消息隊列,有消息時將隊列中的消息派發出去。
		{
			TranslateMessage( &msg );		//將虛擬鍵消息轉換爲字符消息
			DispatchMessage( &msg );		//該函數分發一個消息給窗口程序。
		}
		else
		{
			Direct3D_Render(hwnd);   //進行渲染
		}
	}
	//【6】窗口類的註銷
	UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance);  //程序準備結束,註銷窗口類
	return 0;  
}

//-----------------------------------【WndProc( )函數】--------------------------------------
//	描述:窗口過程函數WndProc,對窗口消息進行處理
//------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )      
{
	switch( message )						//switch語句開始
	{
	case WM_PAINT:						// 若是客戶區重繪消息
		Direct3D_Render(hwnd);                 //調用Direct3D渲染函數
		ValidateRect(hwnd, NULL);		// 更新客戶區的顯示
		break;									//跳出該switch語句

	case WM_KEYDOWN:					// 若是鍵盤按下消息
		if (wParam == VK_ESCAPE)    // 如果被按下的鍵是ESC
			DestroyWindow(hwnd);		// 銷燬窗口, 併發送一條WM_DESTROY消息
		break;									//跳出該switch語句

	case WM_DESTROY:					//若是窗口銷燬消息
		Direct3D_CleanUp();			//調用自定義的資源清理函數Game_CleanUp()進行退出前的資源清理
		PostQuitMessage( 0 );			//向系統表明有個線程有終止請求。用來響應WM_DESTROY消息
		break;									//跳出該switch語句

	default:										//若上述case條件都不符合,則執行該default語句
		return DefWindowProc( hwnd, message, wParam, lParam );		//調用缺省的窗口過程
	}

	return 0;									//正常退出
}

//-----------------------------------【Direct3D_Init( )函數】--------------------------------------
//	描述:Direct3D初始化函數,進行Direct3D的初始化
//------------------------------------------------------------------------------------------------
HRESULT Direct3D_Init(HWND hwnd)
{
	//--------------------------------------------------------------------------------------
	// 【Direct3D初始化四步曲之一,創接口】:創建Direct3D接口對象, 以便用該Direct3D對象創建Direct3D設備對象
	//--------------------------------------------------------------------------------------
	LPDIRECT3D9  pD3D = NULL; //Direct3D接口對象的創建
	if( NULL == ( pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) //初始化Direct3D接口對象,並進行DirectX版本協商
		return E_FAIL;

	//--------------------------------------------------------------------------------------
	// 【Direct3D初始化四步曲之二,取信息】:獲取硬件設備信息
	//--------------------------------------------------------------------------------------
	D3DCAPS9 caps; int vp = 0;
	if( FAILED( pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps ) ) )
	{
		return E_FAIL;
	}
	if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;   //支持硬件頂點運算,我們就採用硬件頂點運算,妥妥的
	else
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //不支持硬件頂點運算,無奈只好採用軟件頂點運算

	//--------------------------------------------------------------------------------------
	// 【Direct3D初始化四步曲之三,填內容】:填充D3DPRESENT_PARAMETERS結構體
	//--------------------------------------------------------------------------------------
	D3DPRESENT_PARAMETERS d3dpp; 
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.BackBufferWidth            = WINDOW_WIDTH;
	d3dpp.BackBufferHeight           = WINDOW_HEIGHT;
	d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
	d3dpp.BackBufferCount            = 1;
	d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
	d3dpp.MultiSampleQuality         = 0;
	d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
	d3dpp.hDeviceWindow              = hwnd;
	d3dpp.Windowed                   = true;
	d3dpp.EnableAutoDepthStencil     = true; 
	d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
	d3dpp.Flags                      = 0;
	d3dpp.FullScreen_RefreshRateInHz = 0;
	d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

	//--------------------------------------------------------------------------------------
	// 【Direct3D初始化四步曲之四,創設備】:創建Direct3D設備接口
	//--------------------------------------------------------------------------------------
	if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 
		hwnd, vp, &d3dpp, &g_pd3dDevice)))
		return E_FAIL;

	SAFE_RELEASE(pD3D) //LPDIRECT3D9接口對象的使命完成,我們將其釋放掉

		if(!(S_OK==Objects_Init(hwnd))) return E_FAIL;     //調用一次Objects_Init,進行渲染資源的初始化

	return S_OK;
}



//-----------------------------------【Object_Init( )函數】--------------------------------------
//	描述:渲染資源初始化函數,在此函數中進行要被渲染的物體的資源的初始化
//--------------------------------------------------------------------------------------------------
HRESULT Objects_Init(HWND hwnd)
{
	//創建字體
	if(FAILED(D3DXCreateFont(g_pd3dDevice, 36, 0, 0, 1, false, DEFAULT_CHARSET, 
		OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, _T("微軟雅黑"), &g_pFont)))
		return E_FAIL;
	srand(timeGetTime());      //用系統時間初始化隨機種子 

	// 物體的創建
	if(FAILED(D3DXCreateBox(g_pd3dDevice, 2, 2, 2, &g_cube, NULL)))	//立方體的創建
		return false;
	if(FAILED(D3DXCreateTeapot(g_pd3dDevice, &g_teapot, NULL)))		//茶壺的創建
		return false;	
	if(FAILED(D3DXCreateSphere(g_pd3dDevice, 1.5, 25, 25,					//球面體的創建
		&g_sphere, NULL))) return false;
	if(FAILED(D3DXCreateTorus(g_pd3dDevice, 0.5f, 1.2f, 25, 25,				//圓環體的創建
		&g_torus, NULL))) return false;

	// 設置材質
	D3DMATERIAL9 mtrl;
	::ZeroMemory(&mtrl, sizeof(mtrl));
	mtrl.Ambient  = D3DXCOLOR(0.5f, 0.5f, 0.7f, 1.0f);
	mtrl.Diffuse  = D3DXCOLOR(0.6f, 0.6f, 0.6f, 1.0f);
	mtrl.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 0.3f);
	mtrl.Emissive = D3DXCOLOR(0.3f, 0.0f, 0.1f, 1.0f);
	g_pd3dDevice->SetMaterial(&mtrl);

	// 設置光照
	Light_Set(g_pd3dDevice, 1);
	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, true);
	g_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, true);


	g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);   //開啓背面消隱

	return S_OK;
}

//-----------------------------------【Light_Set( )函數】-----------------------------
// Desc: 封裝了3種光源類型的函數,可以根據第二個參數選擇光源類型
//--------------------------------------------------------------------------------------
VOID Light_Set(LPDIRECT3DDEVICE9 pd3dDevice, UINT nType)
{
	//定義一個光照類型並初始化
	static D3DLIGHT9 light;
	::ZeroMemory(&light, sizeof(light));

	//一個switch,給3種光源選項
	switch (nType)
	{
	case 1:     //點光源
		light.Type          = D3DLIGHT_POINT;
		light.Ambient       = D3DXCOLOR(0.6f, 0.6f, 0.6f, 1.0f); 
		light.Diffuse       = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
		light.Specular      = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
		light.Position      = D3DXVECTOR3(0.0f, 200.0f, 0.0f);
		light.Attenuation0  = 1.0f;
		light.Attenuation1  = 0.0f;
		light.Attenuation2  = 0.0f;
		light.Range         = 300.0f;
		break;
	case 2:     //平行光
		light.Type          = D3DLIGHT_DIRECTIONAL;
		light.Ambient       = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
		light.Diffuse       = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
		light.Specular      = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
		light.Direction     = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
		break;
	case 3:     //聚光燈
		light.Type          = D3DLIGHT_SPOT;
		light.Position      = D3DXVECTOR3(100.0f, 100.0f, 100.0f);
		light.Direction     = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
		light.Ambient       = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
		light.Diffuse       = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
		light.Specular      = D3DXCOLOR(0.3f, 0.3f, 0.3f, 0.3f);
		light.Attenuation0  = 1.0f; 
		light.Attenuation1  = 0.0f; 
		light.Attenuation2  = 0.0f; 
		light.Range         = 300.0f;
		light.Falloff       = 0.1f;
		light.Phi           = D3DX_PI / 3.0f;
		light.Theta         = D3DX_PI / 6.0f;
		break;
	}

	pd3dDevice->SetLight(0, &light); //設置光源
	pd3dDevice->LightEnable(0, true);//啓用光照
	pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(100, 10, 10));   //設置一下環境光
}



//-----------------------------------【Matrix_Set( )函數】--------------------------------------
//	描述:封裝了Direct3D四大變換的函數,即世界變換,取景變換,投影變換,視口變換的設置
//--------------------------------------------------------------------------------------------------
VOID Matrix_Set()
{
	//--------------------------------------------------------------------------------------
	//【四大變換之一】:世界變換矩陣的設置
	//--------------------------------------------------------------------------------------


	//--------------------------------------------------------------------------------------
	//【四大變換之二】:取景變換矩陣的設置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matView; //定義一個矩陣
	D3DXVECTOR3 vEye(0.0f, 0.0f, -15.0f);  //攝像機的位置
	D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f); //觀察點的位置
	D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);//向上的向量
	D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp); //計算出取景變換矩陣
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //應用取景變換矩陣

	//--------------------------------------------------------------------------------------
	//【四大變換之三】:投影變換矩陣的設置
	//--------------------------------------------------------------------------------------
	D3DXMATRIX matProj; //定義一個矩陣
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 1000.0f); //計算投影變換矩陣
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);  //設置投影變換矩陣

	//--------------------------------------------------------------------------------------
	//【四大變換之四】:視口變換的設置
	//--------------------------------------------------------------------------------------
	D3DVIEWPORT9 vp; //實例化一個D3DVIEWPORT9結構體,然後做填空題給各個參數賦值就可以了
	vp.X      = 0;		//表示視口相對於窗口的X座標
	vp.Y      = 0;		//視口相對對窗口的Y座標
	vp.Width  = WINDOW_WIDTH;	//視口的寬度
	vp.Height = WINDOW_HEIGHT; //視口的高度
	vp.MinZ   = 0.0f; //視口在深度緩存中的最小深度值
	vp.MaxZ   = 1.0f;	//視口在深度緩存中的最大深度值
	g_pd3dDevice->SetViewport(&vp); //視口的設置

}

//-----------------------------------【Direct3D_Render( )函數】-------------------------------
//	描述:使用Direct3D進行渲染
//--------------------------------------------------------------------------------------------------
void Direct3D_Render(HWND hwnd)
{
	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之一】:清屏操作
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

	//定義一個矩形,用於獲取主窗口矩形
	RECT formatRect;
	GetClientRect(hwnd, &formatRect);
	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之二】:開始繪製
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->BeginScene();                     // 開始繪製

	Matrix_Set();//調用封裝了四大變換的函數,對Direct3D世界變換,取景變換,投影變換,視口變換進行設置

	// 根據鍵盤按下的情況設置相應的填充模式
	if (::GetAsyncKeyState(0x31) & 0x8000f)         // 若數字鍵1被按下,進行實體填充
		g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
	if (::GetAsyncKeyState(0x32) & 0x8000f)         // 若數字鍵2被按下,進行線框填充
		g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);


		// 根據鍵盤按下的情況設置相應的光照類型
	if (::GetAsyncKeyState(0x51) & 0x8000f)         // 若鍵盤上的按鍵Q被按下,光源類型設爲點光源
		Light_Set(g_pd3dDevice, 1);
	if (::GetAsyncKeyState(0x57) & 0x8000f)         // 若鍵盤上的按鍵W被按下,光源類型設爲平行光源
		Light_Set(g_pd3dDevice, 2);
	if (::GetAsyncKeyState(0x45) & 0x8000f)         // 若鍵盤上的按鍵E被按下,光源類型設爲聚光燈
		Light_Set(g_pd3dDevice, 3);

	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之三】:正式繪製,利用頂點緩存繪製圖形
	//--------------------------------------------------------------------------------------
	//物體的公轉
	D3DXMatrixRotationY(&R, ::timeGetTime() / 1440.0f);


	// 進行立方體的繪製
	D3DXMatrixTranslation(&g_WorldMatrix[0], 3.0f, -3.0f, 0.0f);
	g_WorldMatrix[0]  =  g_WorldMatrix[0]*R; 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_WorldMatrix[0]);
	g_cube->DrawSubset(0);

	//進行茶壺的繪製
	D3DXMatrixTranslation(&g_WorldMatrix[1], -3.0f, -3.0f, 0.0f);
	g_WorldMatrix[1]  =  g_WorldMatrix[1]*R; 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_WorldMatrix[1]);	
	g_teapot->DrawSubset(0);

	// 進行圓環的繪製
	D3DXMatrixTranslation(&g_WorldMatrix[2], 3.0f, 3.0f, 0.0f);
	g_WorldMatrix[2]  =  g_WorldMatrix[2]*R; 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_WorldMatrix[2]);	
	g_torus->DrawSubset(0);

	// 進行球面體的繪製
	D3DXMatrixTranslation(&g_WorldMatrix[3], -3.0f, 3.0f, 0.0f);
	g_WorldMatrix[3]  =  g_WorldMatrix[3]*R; 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_WorldMatrix[3]);
	g_sphere->DrawSubset(0);

	//在窗口右上角處,顯示每秒幀數
	int charCount = swprintf_s(g_strFPS, 20, _T("FPS:%0.3f"), Get_FPS() );
	g_pFont->DrawText(NULL, g_strFPS, charCount , &formatRect, DT_TOP | DT_RIGHT, D3DCOLOR_XRGB(255,39,136));

	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之四】:結束繪製
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->EndScene();                       // 結束繪製
	//--------------------------------------------------------------------------------------
	// 【Direct3D渲染五步曲之五】:顯示翻轉
	//--------------------------------------------------------------------------------------
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);  // 翻轉與顯示
}

//-----------------------------------【Get_FPS( )函數】------------------------------------------
//	描述:用於計算每秒幀速率的一個函數
//--------------------------------------------------------------------------------------------------
float Get_FPS()
{
	//定義四個靜態變量
	static float  fps = 0; //我們需要計算的FPS值
	static int     frameCount = 0;//幀數
	static float  currentTime =0.0f;//當前時間
	static float  lastTime = 0.0f;//持續時間

	frameCount++;//每調用一次Get_FPS()函數,幀數自增1
	currentTime = timeGetTime()*0.001f;//獲取系統時間,其中timeGetTime函數返回的是以毫秒爲單位的系統時間,所以需要乘以0.001,得到單位爲秒的時間

	//如果當前時間減去持續時間大於了1秒鐘,就進行一次FPS的計算和持續時間的更新,並將幀數值清零
	if(currentTime - lastTime > 1.0f) //將時間控制在1秒鐘
	{
		fps = (float)frameCount /(currentTime - lastTime);//計算這1秒鐘的FPS值
		lastTime = currentTime; //將當前時間currentTime賦給持續時間lastTime,作爲下一秒的基準時間
		frameCount    = 0;//將本次幀數frameCount值清零
	}

	return fps;
}

//-----------------------------------【Direct3D_CleanUp( )函數】--------------------------------
//	描述:資源清理函數,在此函數中進行程序退出前資源的清理工作
//---------------------------------------------------------------------------------------------------
void Direct3D_CleanUp()
{
//釋放COM接口對象
	SAFE_RELEASE(g_torus)
	SAFE_RELEASE(g_sphere)
	SAFE_RELEASE(g_cube)
	SAFE_RELEASE(g_teapot)
	SAFE_RELEASE(g_pFont)
	SAFE_RELEASE(g_pd3dDevice)
}

這玩意真的牛批的

1.點光源效果


2.平行光


3.聚光燈

4.線框填充


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章