这是个令人十分激动的时刻,用Directx3D去渲染出一些形状,还有会动的形状。感觉就跟中了彩票一样的心情。
好了,以上都是废话。在上一次的文章中学会了如何初始化Directx3D环境,now!开始真正的干事情了,首先要渲染一个三维三角形。在前面的代码的基础上其实添加小量代码就可以实现渲染了,不过还是要了解几个东西。
1.可变定点格式FVF(Flexible Vertex Format),Directx3D用这种方法来定义顶点结构,以满足各种不同情况的需求。用户可以根据自己程序的不同需要来定义相应的顶点对象,忽略某些对象,这样实现了在渲染模型是节省内存和最小化流水线宽度的目的。在此并不打算详细的说明FVF,因为其实我也不懂。。。简单来说FVF是Directx3D提供给用户灵活的定义自己的顶点结构的方式,你的顶点结构可以很复杂也可以很简单,只有x, y, z三个坐标,这完全看你的需要。在此我们要渲染一个彩色的三角形,所以我们为我们的顶点结构添加了除坐标之外的一个属性color。
struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw;
DWORD color;
};
HRESULT IDirect3Ddevice9::CreateVetexBuffer(
UINT Length, //分配给缓冲区的字节数
DWORD Usage, //标识缓冲区将会被怎样使用,设为0,标识没有附加属性
DWORD FVF, //缓冲区存储的顶点的可变顶点格式FVF
D3DPOOL pool, //缓冲区的内存池类型
IDirect3DVertexBuffer9** ppVertexBuffer, //返回被创建的顶点缓冲区指针
HANDLE* pShareHandle //暂时未使用,扩展部分,设为0
);
在创建顶点缓冲区后,需要用我们预先定义好的顶点数据去填充这个缓冲区,由于缓冲区有可能在显存或系统内存中,首先调用Lock()方法锁定获取缓冲区的首地址:
HRESULT IDirect3DVertexBuffer9::Lock(
UNIT offsetToLock, //以字节计算的偏移地址,从缓冲区首部开始偏移地质处开始锁定
UNIT sizeToLock, //锁定的字节数
BYTE** ppData, //返回被锁定的缓冲区区域的头指针
DWORD Flags, //描述缓冲区锁定方式的标识
);
最后还要调用Unlock()解除锁定。
索引缓冲区的创建:和定点缓冲区类似
HRESULT IDirect3DDevice9::CreateIndexBuffer(
//参数含义基本和CreateVertexBuffer一样,只有Format不同
UINT Length,
DWORD Usage,
D3DFORMAT Format, //确定哪种索引格式,有16位,和32位,它们可以容纳的最大索引不同
D3DPOOL Pool,
IDirect3DIndexBuffer** ppIndexBuffer,
HANDLE* pShareHandle
);
HRESULT IDirect3DIndexBuffer9::Lock(
UNIT offsetToLock, //以字节计算的偏移地址,从缓冲区首部开始偏移地质处开始锁定
UNIT sizeToLock, //锁定的字节数
BYTE** ppData, //返回被锁定的缓冲区区域的头指针
DWORD Flags, //描述缓冲区锁定方式的标识
);
同样的Unlock()方法
到此渲染的数据已经准备完毕,在渲染之前还需要做几件事情:
1、设定数据源,也就是顶点缓冲区,把数据挂接到渲染流水线上等待渲染。
HRESULT IDirect3DDevice9::SetStreamSource(
UINT StreamNumber, //根据显卡能力不同,可以支持多条流水线同时工作
IDirect3DVertexBuffer9* pStreamData, //顶点缓冲区数据指针
UINT offsetInBytes, //设置从缓冲区第几个字节开始挂接
UINT Stride, //顶点缓冲区的顶点大小,以字节计算
);
2、设置顶点格式:
SetFVF();
3、设置索引缓冲区:
SetIndices(IndexBuffer);
//----------------------------------------------------------------------------
//---------渲染一个一个基本的三维三角形
//---------by coderLing 2013.3.29
//----------------------------------------------------------------------------
#include
//------Some gobal variables---------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; //用于创建D3DDevice 对象
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //指向顶点缓冲区
//------自定义顶点类型---------------------------------------------------------
struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw;
DWORD color;
};
//------自定义的FVF------------------------------------------------------------
#define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
//------常量-------------------------------------------------------------------
#define WND_NAME L"vertexBuffer"
#define WND_TITLE L"Directx3D深入详解之——创建使用定点缓冲区"
//------初始化Directx3D--------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
//创建 D3D 对象
if( NULL == ( g_pD3D = Direct3DCreate9 ( D3D_SDK_VERSION) ) )
return E_FAIL;
//设置D3DPRESENT_PRAMETERS参数
D3DPRESENT_PARAMETERS d3dpp;
SecureZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
//创建 D3DDevice
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
return S_OK;
}
//------初始化顶点缓冲区--------------------------------------------------------
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, },
};
//创建顶点缓冲区,要申请足够的内存空间
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(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()
{
//把背景缓冲区变为蓝色
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
//开始渲染
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
//绘制三角形
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); //设置数据源
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); //设置顶点格式
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 );
}
//---------WinMain()函数----------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
WND_NAME, NULL};
RegisterClassEx( &wc );
HWND hWnd = CreateWindow( WND_NAME, WND_TITLE, WS_OVERLAPPEDWINDOW,
100, 100, 300, 300, GetDesktopWindow(),
NULL, wc.hInstance, NULL );
if( SUCCEEDED( InitD3D(hWnd) ) )
{
if( SUCCEEDED( InitVB() ) )
{
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
//消息循环
MSG msg;
SecureZeroMemory( &msg, sizeof(MSG) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &msg, NULL,0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
Render();
}
}
}
UnregisterClass( WND_NAME, wc.hInstance );
return 0;
}
旋转立方体:
//--------ColorfulCube----------------------------------------------------------------
//--------by coderLing 2013.3.30
//------------------------------------------------------------------------------------
#include
#include //如果要使用D3DX库就必须加入这个头文件
//定义使用到的顶点结构
struct CUSTOMVERTEX
{
FLOAT x,y,z; //顶点坐标信息
DWORD color; //顶点颜色信息
};
//定义顶点的FVF结构
#define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE)
#define WND_NAME L"ColorfulCube"
#define WND_TITLE L"Directx3D游戏开发之-ColorfulCube"
//some gobal variables
LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象指针,LP开头便是指针
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; //Direct3D 设备
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //顶点缓冲区指针
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; //索引缓冲区指针
//初始化Direct3D设备
HRESULT InitD3D( HWND hWnd)
{
//创建Directx3D对象
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
//填写创建Direct3D设备的结构体
D3DPRESENT_PARAMETERS d3dpp;
SecureZeroMemory( &d3dpp, sizeof( d3dpp ));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
//创建Direct3D设备
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pD3DDevice) ) )
{
return E_FAIL;
}
return S_OK;
}
//初始化绘图相关数据,顶点缓冲区,索引缓冲区
HRESULT InitDraw()
{
//创建顶点缓冲区
g_pD3DDevice->CreateVertexBuffer(
8 * sizeof(CUSTOMVERTEX),
D3DUSAGE_WRITEONLY,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_MANAGED,
&g_pVB,
0);
//创建索引缓冲区
g_pD3DDevice->CreateIndexBuffer(
36 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&g_pIB,
0);
//创建立方体的8个顶点,每个顶点的颜色都不同
//在绘制是,Direct3D会根据顶点的颜色对三角形内部像素进行插值,所以立方体看起来是彩色的
CUSTOMVERTEX source_vertices[] ={
{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255,0,0) },
{ -1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0,255,0) },
{ 1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0,0,255) },
{ 1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255,255,0) },
{ -1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(255,0,255) },
{ -1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0,255,255) },
{ 1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0,0,0) },
{ 1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(255,255,255) }
};
//把上面的顶点数据复制到所创建的缓冲区中
CUSTOMVERTEX* pVertices;
if( FAILED( g_pVB->Lock(0, 8*sizeof(CUSTOMVERTEX), (VOID**)&pVertices, 0) ) )
return E_FAIL;
memcpy( pVertices, source_vertices, 8*sizeof(CUSTOMVERTEX) );
g_pVB->Unlock();
//定义索引缓冲区的内容
WORD* indices = 0;
g_pIB->Lock(0, 0, (VOID**)&indices, 0);
//正面
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 2; indices[5] = 3;
//背面
indices[6] = 4; indices[7] = 6; indices[8] = 5;
indices[9] = 4; indices[10] = 7; indices[11] = 6;
//左面
indices[12] = 4; indices[13] = 5; indices[14] = 1;
indices[15] = 4; indices[16] = 1; indices[17] = 0;
//右面
indices[18] = 3; indices[19] = 2; indices[20] = 6;
indices[21] = 3; indices[22] = 6; indices[23] = 7;
//顶面
indices[24] = 1; indices[25] = 5; indices[26] = 6;
indices[27] = 1; indices[28] = 6; indices[29] = 2;
//顶面
indices[30] = 4; indices[31] = 0; indices[32] = 3;
indices[33] = 4; indices[34] = 3; indices[35] = 7;
g_pIB->Unlock();
//设置摄像机
D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX V;
D3DXMatrixLookAtLH(&V, &position, &target, &up);
g_pD3DDevice->SetTransform(D3DTS_VIEW, &V);
//设置投影矩阵
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI * 0.5f,
(float)800 / (float)600,
1.0f,
1000.0f
);
g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &proj);
//没有材质,纹理信息,关闭灯光显示出本身颜色
g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
return S_OK;
}
//------释放资源------------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pVB != NULL )
g_pVB->Release();
if( g_pIB != NULL )
g_pIB->Release();
if( g_pD3DDevice != NULL )
g_pD3DDevice->Release();
if( g_pD3D != NULL)
g_pD3D->Release();
}
//--------渲染函数------------------------------------------------------------------
VOID Render()
{
//清除屏幕缓冲区到蓝色屏幕
g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255),1.0f, 0);
//开始绘制
if( SUCCEEDED( g_pD3DDevice->BeginScene() ) )
{
//创建沿3个轴的矩阵
D3DXMATRIXA16 matWorld_X;
D3DXMatrixIdentity( &matWorld_X);
D3DXMatrixRotationX( &matWorld_X, timeGetTime()/500.0f);
D3DXMATRIXA16 matWorld_Y;
D3DXMatrixIdentity( &matWorld_Y);
D3DXMatrixRotationY( &matWorld_Y, timeGetTime()/500.0f);
D3DXMATRIXA16 matWorld_Z;
D3DXMatrixIdentity( &matWorld_Z);
D3DXMatrixRotationZ( &matWorld_Z, timeGetTime()/500.0f);
//设置物体的世界矩阵
g_pD3DDevice->SetTransform( D3DTS_WORLD,
&(matWorld_X*matWorld_Y*matWorld_Z) );
g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pD3DDevice->SetIndices( g_pIB );
g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0,12);
//结束绘制
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 );
}
//Main函数
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
//创建及注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
WND_NAME, NULL};
RegisterClassEx( &wc );
//创建窗口
HWND hWnd = CreateWindow( WND_NAME, WND_TITLE, WS_OVERLAPPEDWINDOW,
100, 100, 800, 600, GetDesktopWindow(),
NULL, wc.hInstance, NULL );
if( SUCCEEDED( InitD3D(hWnd) ) )
{
if( SUCCEEDED( InitDraw() ) )
{
//显示窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
//消息循环
MSG msg;
SecureZeroMemory( &msg, sizeof(msg) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
Render();
}
}
}
UnregisterClass( WND_NAME, wc.hInstance );
return 0;
}
The End ~~~~~~