1.实现一个旋转的圆柱体,体现d3d光照效果
2.程序实现
#pragma once #pragma comment(lib,"winmm.lib") #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #include<d3d9.h> #include<d3dx9.h> //自己定义顶点格式 struct CUSTOMVERTEX { D3DXVECTOR3 postion; D3DXVECTOR3 normal; }; //坐标和法向量。 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL) //函数声明 LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam); void Render(); HRESULT InitD3D(HWND hWnd); HRESULT InitGeometry(); void CleanUp(); void SetupMatrices(); void SetupLights(); //全局变量 LPDIRECT3D9 g_pd3d=NULL; LPDIRECT3DDEVICE9 g_pd3dDevice=NULL; LPDIRECT3DVERTEXBUFFER9 g_d3dVertexBuffer=NULL; //主函数入口。 INT WINAPI wWinMain(HINSTANCE,HINSTANCE,LPWSTR,INT) { //注冊窗体类。 WNDCLASSEX wcex; ZeroMemory(&wcex,sizeof(wcex)); wcex.cbSize=sizeof(wcex); wcex.hInstance=GetModuleHandle(NULL); wcex.lpfnWndProc=MsgProc; wcex.lpszClassName=L"Self001"; wcex.style=CS_CLASSDC; RegisterClassEx(&wcex); //创建窗体。 HWND hWnd=CreateWindowEx( WS_EX_OVERLAPPEDWINDOW, L"Self001", L"Self001 Window", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wcex.hInstance, NULL); //显示窗体。 ShowWindow(hWnd,SW_SHOWDEFAULT); UpdateWindow(hWnd); //初始化d3d对象。 if(SUCCEEDED(InitD3D(hWnd))) { if(SUCCEEDED(InitGeometry())) { //消息循环。 MSG msg; ZeroMemory(&msg,sizeof(msg)); while(msg.message != WM_QUIT) { if(PeekMessage(&msg,hWnd,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { Render(); } } } } //注销窗体类。 UnregisterClass(L"Self001",wcex.hInstance); return 0; } //窗体回调函数。 LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { case WM_DESTROY: CleanUp(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,msg,wParam,lParam); } //渲染。 void Render() { //清除目标。 g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,255),1.0f,0); if(SUCCEEDED(g_pd3dDevice->BeginScene())) { SetupLights(); SetupMatrices(); g_pd3dDevice->SetStreamSource(0,g_d3dVertexBuffer,0,sizeof(CUSTOMVERTEX)); g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); //绘制图元 g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2*50-2); g_pd3dDevice->EndScene(); } g_pd3dDevice->Present(NULL,NULL,NULL,NULL); } //初始化d3d对象 HRESULT InitD3D(HWND hWnd) { //创建d3d g_pd3d=Direct3DCreate9(D3D_SDK_VERSION); if(g_pd3d == NULL) { return E_FAIL; } //初始化d3d呈现參数。 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp,sizeof(d3dpp)); d3dpp.Windowed=TRUE; d3dpp.hDeviceWindow=hWnd; d3dpp.BackBufferFormat=D3DFMT_UNKNOWN; d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD; d3dpp.EnableAutoDepthStencil=TRUE; d3dpp.AutoDepthStencilFormat=D3DFMT_D16; //创建设备。 if(FAILED(g_pd3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { return E_FAIL; } //设置背面剔除和z 缓冲 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); g_pd3dDevice->SetRenderState(D3DRS_ZENABLE,TRUE); return S_OK; } //清除d3d对象。 void CleanUp() { //顶点缓冲。 if(g_d3dVertexBuffer != NULL) { g_d3dVertexBuffer->Release(); } //设备。 if(g_pd3dDevice != NULL) { g_pd3dDevice->Release(); } //d3d。 if(g_pd3d != NULL) { g_pd3d->Release(); } } //设置变换矩阵。 void SetupMatrices() { //世界变换矩阵。 D3DXMATRIXA16 matWorld; D3DXMatrixIdentity(&matWorld); D3DXMatrixRotationX(&matWorld,timeGetTime()/500.0f); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld); //视野变换矩阵。 D3DXMATRIXA16 matView; D3DXVECTOR3 vEye(0.0f,3.0f,-5.0f); D3DXVECTOR3 vLookAt(0.0f,0.0f,0.0f); D3DXVECTOR3 vUp(0.0f,1.0f,0.0f); D3DXMatrixLookAtLH(&matView,&vEye,&vLookAt,&vUp); g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView); //投影变换矩阵。 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,100.0f); g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj); } //初始化几何图元。 HRESULT InitGeometry() { //创建顶点缓冲。 if(FAILED(g_pd3dDevice->CreateVertexBuffer( sizeof(CUSTOMVERTEX)*2*50, 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_d3dVertexBuffer, NULL))) { return E_FAIL; } //坐标设定。 CUSTOMVERTEX* pVertices=NULL; if(FAILED(g_d3dVertexBuffer->Lock(0,0,(void**)&pVertices,0))) { return E_FAIL; } for(DWORD i=0;i<50;i++) { FLOAT theta=(2*D3DX_PI*i)/(50-1); pVertices[2*i+0].postion=D3DXVECTOR3(cosf(theta),-1,sinf(theta)); pVertices[2*i+0].normal=D3DXVECTOR3(cosf(theta),0,sinf(theta)); pVertices[2*i+1].postion=D3DXVECTOR3(cosf(theta),1,sinf(theta)); pVertices[2*i+1].normal=D3DXVECTOR3(cosf(theta),0,sinf(theta)); } g_d3dVertexBuffer->Unlock(); return S_OK; } //设置材料和光照。 void SetupLights() { //材料 D3DMATERIAL9 mtrl; ZeroMemory(&mtrl,sizeof(mtrl)); mtrl.Ambient.r=mtrl.Diffuse.r=1.0f; mtrl.Ambient.g=mtrl.Diffuse.g=1.0f; mtrl.Ambient.b=mtrl.Diffuse.b=0.0f; mtrl.Ambient.a=mtrl.Diffuse.a=1.0f; g_pd3dDevice->SetMaterial(&mtrl); //光照 D3DLIGHT9 light; ZeroMemory(&light,sizeof(light)); light.Type=D3DLIGHT_DIRECTIONAL; light.Diffuse.r=1.0f; light.Diffuse.g=1.0f; light.Diffuse.b=1.0f; D3DXVECTOR3 normVec=D3DXVECTOR3(0.0f,0.0f,1.0f); D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction,&normVec); light.Range=1000.0f; //环境 g_pd3dDevice->SetLight(0,&light); g_pd3dDevice->LightEnable(0,TRUE); g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE); g_pd3dDevice->SetRenderState(D3DRS_AMBIENT,D3DCOLOR_XRGB(10,0,0)); }
3.程序执行结果
4.注意事项。
理解材料是什么东西,尤其材料的漫射光和环境光。
理解光照是什么东西,尤其设置參数。
练习多了,慢慢的就熟悉了。