|
今天看了一下动态的作图,感觉里面好多东西都难看明白,觉得这样做下去不行,需要的是了解其内部含义,就看了一天的directx9 sdk文档,全英文的,头都看晕了,不过反正这段时间公司也没事我做,耐着性子看了很多,终于明白了以前只看代码不明白的地方,觉得那才是真正应该学习的,基础得先打好了再来学代码,所以以下的部分我只贴出代码来(方便已有基础的人看),我还是先了解D3D运行机制和原理。以下是代码: /**---------------------------------------------------------------------------- * \brief 使用矩阵 * 文件: Matrices.cpp * * 说明 : 熟悉创建设备和顶点的方法. * 想要自由创建三维顶点,必须使用4X4大小的矩阵. * 基本的矩阵变换包括移动(transition)、旋转(rotation)和缩放(scaling)三种. * the geometry with translations, rotations, scaling, and setting up our * camera. * * 几何信息为模型坐标系, 必须变换为三维世界坐标系. * 这时使用世界矩阵. * 再次将世界坐标系的集合信息变换为摄像机坐标系. 这时使用的是视图矩阵. * 只有将视图矩阵的集合信息投影到二维平面,才能在窗口绘图. * 也就是说:经过world -> view -> proejction的变换才能进行绘图. * (当然,还需要进行裁剪等处理工作.) * * OpenGL必须直接制定矩阵运算函数,D3D中大多数为效用(utility)函数. * 这里使用D3DX系列函数. **----------------------------------------------------------------------------- */ #include <Windows.h> #include <mmsystem.h> /// 使用TimeGetTime()函数包含的首部 #include <d3dx9.h>
/**----------------------------------------------------------------------------- * 全局参数 *------------------------------------------------------------------------------ */ LPDIRECT3D9 g_pD3D = NULL; /// 创建D3D设备的D3D对象参数 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; /// 渲染中使用的D3D设备 LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; /// 储存顶点的顶点缓冲
/// 定义用户顶点的结构体 struct CUSTOMVERTEX { FLOAT x, y, z; /// 顶点的三维坐标 DWORD color; /// 顶点的颜色 };
/// 表现用户顶点结构体相关信息的FVF值 /// 结构体由X,Y,Z,RHW值和Diffuse颜色值组成. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
/**----------------------------------------------------------------------------- * Direct3D初始化 *------------------------------------------------------------------------------ */ HRESULT InitD3D( HWND hWnd ) { /// 创建一个用来创建设备的D3D对象 if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL;
/// 创建设备的结构体 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
/// 创建设备 if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; }
/// 起到卷起功能. 对三角形的前面、后面进行渲染. g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
/// 顶点具有颜色值,能起到光源功能. g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
return S_OK; }
/**----------------------------------------------------------------------------- * 几何信息初始化 *------------------------------------------------------------------------------ */ HRESULT InitGeometry() { /// 渲染三角形的三个顶点声明 CUSTOMVERTEX g_Vertices[] = { { -1.0f,-1.0f, 0.0f, 0xffff0000, }, { 1.0f,-1.0f, 0.0f, 0xff0000ff, }, { 0.0f, 1.0f, 0.0f, 0xffffffff, }, };
/// 创建顶点缓冲 if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; }
/// 将数据写入顶点缓冲. VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, g_Vertices, sizeof(g_Vertices) ); g_pVB->Unlock();
return S_OK; }
/**----------------------------------------------------------------------------- * 删除初始化对象 *------------------------------------------------------------------------------ */ VOID Cleanup() { if( g_pVB != NULL ) g_pVB->Release();
if( g_pd3dDevice != NULL ) g_pd3dDevice->Release();
if( g_pD3D != NULL ) g_pD3D->Release(); }
/**----------------------------------------------------------------------------- * 创建矩阵 * 矩阵分为世界矩阵、视图矩阵、投影矩阵三种. *------------------------------------------------------------------------------ */ VOID SetupMatrices() { /// 世界矩阵 D3DXMATRIXA16 matWorld;
UINT iTime = timeGetTime() % 1000; /// 运行1000的余数运算,以保证Float运算的精确度. FLOAT fAngle = iTime * (2.0f * D3DX_PI) / 1000.0f; /// 创建每1000毫秒旋转一圈(2 * pi)的旋转矩阵. D3DXMatrixRotationY( &matWorld, fAngle ); /// 创建Y轴为旋转轴的旋转矩阵 g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); /// 在设备中将创建的矩阵设定为世界矩阵
/// 定义视图矩阵需要三个值. D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f ); /// 1. 眼睛的位置(0,3.0,﹣5) D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); /// 2. 眼睛观察的位置(0,0,0) D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); /// 3. 表现顶点方向的上方向量(0,1,0) D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); /// 由1,2,3值创建视图矩阵 g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); /// 在设备中设定创建的视图矩阵
/// 定义投影矩阵需要视角(FOV=Field Of View)、长宽比(aspect ratio)和裁剪平面的值. D3DXMATRIXA16 matProj; /// matProj : 设定值的矩阵 /// D3DX_PI/4 : FOV(D3DX_PI/4=45度) /// 1.0f : 长宽比 /// 1.0f : 近裁剪面(near clipping plane) /// 100.0f : 远裁剪面(far clipping plane) D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); /// 在设备中设定创建的投影矩阵 }
/**----------------------------------------------------------------------------- * 绘图 *------------------------------------------------------------------------------ */ VOID Render() { /// 将后置缓冲清除,同时设置为黑色(0,0,255). g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
/// 开始渲染 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { /// 创建世界矩阵、视图矩阵和投影矩阵. SetupMatrices();
/// 绘制顶点缓冲内容. g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 1 );
/// 结束渲染 g_pd3dDevice->EndScene(); }
/// 显示后置缓冲的画面! g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); }
/**----------------------------------------------------------------------------- * 窗口过程 *------------------------------------------------------------------------------ */ LRESULT WINAPI 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 ); }
/**----------------------------------------------------------------------------- * 程序的起始地址 *------------------------------------------------------------------------------ */ INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { /// 注册窗口类 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "D3D Tutorial", NULL }; RegisterClassEx( &wc );
/// 创建窗口 HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 03: Matrices", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL );
/// Direct3D初始化 if( SUCCEEDED( InitD3D( hWnd ) ) ) { /// 场景中使用的几何信息初始化 if( SUCCEEDED( InitGeometry() ) ) { /// 显示窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd );
/// 消息循环 MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else Render(); } } }
UnregisterClass( "D3D Tutorial", wc.hInstance ); return 0; }
/**---------------------------------------------------------------------------- * \brief 创建光源 * 文件: Lights.cpp * * 说明: 使用光照需要大量的运算. * 使用光照必须创建光源和材质. * 几何信息中必须包含法线向量信息. * 以颜色、方向等信息为基础,创建光源. *------------------------------------------------------------------------------ */ #include <Windows.h> #include <mmsystem.h> #include <d3dx9.h>
/**----------------------------------------------------------------------------- * 全局参数 *------------------------------------------------------------------------------ */ LPDIRECT3D9 g_pD3D = NULL; /// 创建D3D 设备的D3D对象参数 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; /// 渲染中使用的D3D设备 LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; /// 储存顶点的顶点缓冲
/// 定义用户顶点的结构体 /// 使用光源必须要有法线向量. struct CUSTOMVERTEX { D3DXVECTOR3 position; /// 顶点的三维坐标 D3DXVECTOR3 normal; /// 顶点的法线向量 };
/// 表现用户顶点结构体信息的FVF值 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
/**----------------------------------------------------------------------------- * Direct3D初始化 *------------------------------------------------------------------------------ */ HRESULT InitD3D( HWND hWnd ) { /// 创建一个用来创建设备的D3D对象 if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL;
/// 创建设备的结构体 /// 绘制复杂对象时需要Z-缓冲. D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; 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; }
/// 起到卷起功能. g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
/// 起到Z-缓冲功能. g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
return S_OK; }
/**----------------------------------------------------------------------------- * 几何信息初始化 *------------------------------------------------------------------------------ */ HRESULT InitGeometry() { /// 创建顶点缓冲 if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; }
/// 使用算法(algorithm)绘制气缸(钻好的圆筒,同上). CUSTOMVERTEX* pVertices; if( FAILED( g_pVB->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].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) ); /// 气缸的下方圆筒坐标 pVertices[2*i+0].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) ); /// 气缸的下方圆筒法线向量 pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) ); /// 气缸的上方圆筒坐标 pVertices[2*i+1].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) ); /// 气缸的上方圆筒法线向量 } g_pVB->Unlock();
return S_OK; }
/**----------------------------------------------------------------------------- * 删除初始化对象 *------------------------------------------------------------------------------ */ VOID Cleanup() { if( g_pVB != NULL ) g_pVB->Release();
if( g_pd3dDevice != NULL ) g_pd3dDevice->Release();
if( g_pD3D != NULL ) g_pD3D->Release(); }
/**----------------------------------------------------------------------------- * 创建矩阵 *------------------------------------------------------------------------------ */ VOID SetupMatrices() { /// 世界矩阵 D3DXMATRIXA16 matWorld; D3DXMatrixIdentity( &matWorld ); /// 设定世界矩阵为单位矩阵 D3DXMatrixRotationX( &matWorld, timeGetTime()/500.0f ); /// 创建以X轴为中心的旋转矩阵 g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); /// 在设备中创建世界矩阵
/// 创建视图矩阵 D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); 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 ); }
/**----------------------------------------------------------------------------- * 创建光源 *------------------------------------------------------------------------------ */ VOID SetupLights() { /// 创建材质(material) /// 在设备中创建一个材质. D3DMATERIAL9 mtrl; ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; g_pd3dDevice->SetMaterial( &mtrl );
/// 创建光源 D3DXVECTOR3 vecDir; /// 方向光源(directional light)照射的方向 D3DLIGHT9 light; /// 光源结构体 ZeroMemory( &light, sizeof(D3DLIGHT9) ); /// 将结构体清零. light.Type = D3DLIGHT_DIRECTIONAL; /// 光源类型(点光源、方向光源、聚光光源) light.Diffuse.r = 1.0f; /// 光源的颜色和亮度 light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f), /// 光源的方向 1.0f, sinf(timeGetTime()/350.0f) ); D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); /// 光源的方向设定为单位向量. light.Range = 1000.0f; /// 光源能够照射到的最远距离 g_pd3dDevice->SetLight( 0, &light ); /// 在设备设置0号光源 g_pd3dDevice->LightEnable( 0, TRUE ); /// 打开0号光源 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); /// 打开光源设置
g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 ); /// 设定环境光源(ambient light)的值 }
/**----------------------------------------------------------------------------- * 绘图 *------------------------------------------------------------------------------ */ VOID Render() { /// 清除后置缓冲和Z-缓冲. 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_pVB, 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 ); }
/**----------------------------------------------------------------------------- * 窗口过程 *------------------------------------------------------------------------------ */ LRESULT WINAPI 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 ); }
/**----------------------------------------------------------------------------- * 本程序的起始地址 *------------------------------------------------------------------------------ */ INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { /// 注册窗口类 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "D3D Tutorial", NULL }; RegisterClassEx( &wc );
/// 创建窗口 HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 04: Lights", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL );
/// Direct3D初始化 if( SUCCEEDED( InitD3D( hWnd ) ) ) { /// 几何信息初始化 if( SUCCEEDED( InitGeometry() ) ) { /// 显示窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd );
/// 消息循环 MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else Render(); } } }
UnregisterClass( "D3D Tutorial", wc.hInstance ); return 0; }
先只发这两个例子,后面的例子需要图片资源。
|
一共有 2 条评论