|
先把源代码弄上了大家先看一遍,我在就我觉得难的地方和大家讨论一下下。 /**----------------------------------------------------------------------------- * \brief 创建顶点缓冲 * 文件: Vertices.cpp * * 说明: 下面讲解顶点渲染的内容。这里我们可以看到顶点缓冲(vertex buffer)的概念. * 所谓顶点缓冲是指储存顶点的D3D对象, 用户可以使用FVF(Flexible Vertex Format) * 随意定义格式. 这里将要使用的顶点是完成变换和光源处理的顶点. * *------------------------------------------------------------------------------ */ #include <d3d9.h>
/**----------------------------------------------------------------------------- * 全局参数 *------------------------------------------------------------------------------ */ LPDIRECT3D9 g_pD3D = NULL; /// 创建D3D设备的D3D对象参数 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; /// 渲染中使用的D3D设备 LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; /// 储存顶点的顶点缓冲
/// 定义用户顶点的结构体 struct CUSTOMVERTEX { FLOAT x, y, z, rhw; /// 顶点的变换坐标(具有rhw值是完成变换的顶点). DWORD color; /// 顶点的颜色 };
/// 表现用户顶点结构体信息的FVF值 /// 结构体由X、Y、Z、RHW值和Diffuse颜色值组成. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|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; }
/// 这里对设备状态信息进行处理.
return S_OK; }
/**----------------------------------------------------------------------------- * 创建顶点缓冲,设置顶点值. * 顶点缓冲就是基本包含顶点数据的存储器块. * 创建顶点缓冲之后,必须调用Lock()函数和Unlock()函数来定义指针 * 将顶点数据写入顶点缓冲. * D3D可以使用索引缓冲. * 基本系统存储器之外,顶点缓冲和索引缓冲也可以在设备存储器(显卡存储器)创建, * 不过,这种情况下,大部分显卡的速度会受到很大的影响. * *------------------------------------------------------------------------------ */ HRESULT InitVB() { /// 渲染三角形的三个顶点声明 CUSTOMVERTEX vertices[] = { { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, }, { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, };
/// 创建顶点缓冲 /// 分配储存三个用户顶点的存储器. /// 指定储存FVF的数据格式. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; }
/// 将数据写入顶点缓冲. /// 调用顶点缓冲的Lock()函数,定义指针. VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, vertices, sizeof(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 Render() { /// 将后置缓冲清除,同时设置为蓝色(0,0,255). g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
/// 开始渲染 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { /// 绘制顶点缓冲的三角形. /// 1. 使包含顶点信息的顶点缓冲绑定一个设备数据流. g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); /// 2. 向D3D指定顶点着色信息,大多数情况下只指定FVF格式. g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); /// 3. 调用输出几何信息的DrawPrimitive()函数 g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 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 02: Vertices", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL );
/// Direct3D初始化 if( SUCCEEDED( InitD3D( hWnd ) ) ) { /// 顶点缓冲初始化 if( SUCCEEDED( InitVB() ) ) { /// 显示窗口 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()函数 Render(); } } }
/// 删除注册的类 UnregisterClass( "D3D Tutorial", wc.hInstance ); return 0; }
顶点需要缓冲区 if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; }
这条语句就是用来创建三个顶点的缓冲区的,但此时内容还没有给g_pVB。所以后面用 VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, vertices, sizeof(vertices) ); g_pVB->Unlock(); 这段代码来把内容写进去,倒底是什么意思呢? 先声明一个指针 pVertices,然后让这个指针和g_pVB的缓冲区绑定,我的理解是共用同一地址,然后用memcpy方法来把vertices里的内容写到pVertices里面去,也就写进了g_pVB建立的缓冲区里面了,最后解除绑定。(个人理解)
在渲染画图里面,首先要将缓冲里面的数据和设备数据流绑定,然后设定一些效果,最后调用输出信息函数,这也是Direct编程画图里的一般过程。 运行代码,你就会看到你用Direct编出来的第一个图形了,还凑合,有些人运行时会报错,你得检查你是否装了Directx9 SDK. 然后VC里的include添加了指向没有,最后你的工程设置里面link里添加你用到的库文件,如:d3d9.h d3dx9.h之类 今天就说到这里了,我一会还得帮别人写个算法,明天我们再让今天这个三角型动起来。
|
一共有 0 条评论