| 
LRESULT CALLBACK WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
			 switch ( msg )
			 {
			 			 case WM_DESTROY:
																				
			 			 			 //...这里将调用一个是收尾函数来释放所有界面指针
     
			 			 			 PostQuitMessage(0);
			 			 			 DestroyWindow(hWnd);
			 			 			 break;
			 			 default:
			 			 			 break;
			 }
			 return ( DefWindowProc( hWnd, msg, wParam, lParam ) );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
			 //create a main window:
			 WNDCLASSEX mainwnd;
   
			 mainwnd.cbSize=sizeof(WNDCLASSEX); 
									
			 mainwnd.cbClsExtra=0;
			 mainwnd.cbWndExtra=0;
			 mainwnd.hbrBackground=NULL;//这将是一个没有背景
			 mainwnd.hCursor=NULL;//鼠标是沙漏
			 mainwnd.hIcon=NULL;//没有图标
			 mainwnd.hIconSm=NULL;
			 mainwnd.hInstance=hInstance;
			 mainwnd.lpfnWndProc=WinProc;//没有标题栏
			 mainwnd.lpszClassName="main window";
			 mainwnd.lpszMenuName=NULL;//没有菜单
			 mainwnd.style=CS_OWNDC;//的窗口
			 RegisterClassEx(&mainwnd);
   
			 HWND hWnd = CreateWindowEx( NULL,"main window","only a demo",
																				WS_POPUP|WS_VISIBLE, 0, 0, 800, 600, NULL, NULL, hInstance, NULL); 
									
			 //在此初始化D3D设备,物体
			 //Init_D3D();
			 //主事件循环:
									
			 MSG msg;
			 ZeroMemory(&msg,sizeof(msg));
			 while (msg.message!=WM_QUIT)
			 {
			 			 //proc message:
			 			 if ( PeekMessage( &msg, hWnd, 0, 0, PM_REMOVE ) )
			 			 {
			 			 			 TranslateMessage( &msg );
			 			 			 DispatchMessage( &msg );
			 			 }
			 			 else
			 			 {
			 			 			 //每帧一次的渲染就在这里
			 			 			 //Render();
			 			 }
			 }
   
			 //UnRegiste the window:
			 UnregisterClass( "main window", mainwnd.hInstance );
			 return ( msg.wParam);
}//end winmain 
 Direct3D是DirectX中极其重要的组建,提供了一套完整的用来设置场景、操作3D物体、渲染画面的方法。来复习一下D3D程序的一般流程:首先得有个要渲染的物体,你得给出它的顶点、贴图、材质信息。然后把它的坐标(3D的)转换为屏幕坐标,再添加一些灯光信息,然后调用一个渲染方法,它所做的就是根据各个顶点的位置(已是屏幕坐标),用灯光和材质信息计算亮度,把贴图“填”进去,这样你看起来就是个立体的东西。渲染方法函数把图画在后备缓冲,因此最后别忘了把它换到前缓冲。你要有个Dirext3D的接口作为创建一切的基础。像这样: LPDIRECT3D9 g_lpd3d9;//全局的
g_lpd3d9 = Direct3DCreate9( D3D_SDK_VERSION );//参数代表了你的D3D SDK版本。必须要这样写 
然后通过它来创建一个Direct3D设备接口,其他所有创建物体、灯光,以及渲染等方法都要通过这个设备接口指针来调用: 
LPDIRECT3DDEVICE9 g_lpd3ddevice;//全局的 
HRESULT InitD3D(HWND hWnd)
{ 
				 D3DPRESENT_PARAMETERS m_d3dpp;  
			 //我们要把当前适配器(显卡)的信息读到这个结构体里,它将被用于创建设备
			 D3DDISPLAYMODE m_d3ddm;
			 g_lpd3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&m_d3ddm);
			 //D3DADAPTER_DEFAULT表示默认显卡 
			 ZeroMemory(&m_d3dpp,sizeof(m_d3dpp)); 
			 m_d3dpp.Windowed=false;//要建立一个全屏程序,则置此项为FALSE
			 m_d3dpp.BackBufferWidth=m_d3ddm.Width;
			 m_d3dpp.BackBufferHeight=m_d3ddm.Height;
			 m_d3dpp.BackBufferFormat=m_d3ddm.Format;//此项记录色深信息
			 m_d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
			 m_d3dpp.EnableAutoDepthStencil = TRUE;//让D3D管理深度缓冲
			 m_d3dpp.AutoDepthStencilFormat=D3DFMT_D16;//设置深度缓冲为16位
			 m_d3dpp.hDeviceWindow=hWnd; 
			 //create the device:
			 g_lpd3d9->CreateDevice(D3DADAPTER_DEFAULT,//适配器标识符,大多数情况使用默认的
        D3DDEVTYPE_HAL,//硬件抽象层
        hWnd,//这是一个当前窗口的句柄,使用刚才CreateWindowEx()的返回值就行了
        D3DCREATE_HARDWARE_VERTEXPROCESSING,//顶点处理类型,这里使用硬件处理
        &m_d3dpp,//描述设备的结构体
        &g_lpd3ddevice);//最后给一个要被创建的设备的指针
  
			 //启用Z缓冲
			 g_lpd3ddevice->SetRenderState(D3DRS_ZENABLE,TRUE); 
			 return S_OK;
} 
Z缓冲是深度缓冲的一种。深度缓冲是一块与屏幕大小相同的区域,记录着屏幕上每个点的“最近像素”有多“近”。比如说程序要画一个三角形中的某个点,但它发现深度缓冲中记录的距离比这个点要近,也就是说其他物体的某点挡在它前面,自然也就不会去画它;否则就画它,然后把该点的深度信息写进缓冲。现在我们把Z-Buffer打开,就是把这些事交给系统处理。调节缓冲数据位数是在较精确的数据与较大的空间之间作个权衡。 
该用到刚刚做完的那个东西了。在D3D中,可以说所有物体的外形位置由顶点构成;材质决定着物体如何反射光线;贴图的作用自不言而喻。任何3D程序首先要做的就是创建一套这些信息。刚才说道,现在这些信息都包含在现成的mesh物体中,我们要做的就是把它从文件中提取出来。D3D中的IDirect3DMesh界面提供了这些方法。 LPD3DXMESH g_lpmesh;//全局的 
mesh物体的定点信息都存放在g_lpmesh里,而材质和贴图还要单独提取出。D3D里,材质和贴图分别用D3DMATERIAL9结构体和ID3DTexture9界面描述。一般来说,mesh中都含有多种贴图和材质,我们要将其声明为数组。 D3DMATERIAL9 *g_meshmtrl;
LPDIRECT3DTEXTURE9 *g_meshtex; 
数组的大小事先并不知道,取决于mesh物体的SebSet的数量。在一个mesh物体中,拥有相同材质贴图属性的一组三角形叫它的一个SubSet。因为转换当前材质和贴图是十分耗时的,因此在D3D中是按照一个SubSet组接着另一个去渲染的,这样就避免了材质贴图的频繁转变。我们用一个DWOD型的全局变量g_meshmtrlnum记录这个mesh中的SubSet数量。 
HRESULT InitGeometry() 
{
			 LPD3DXBUFFER lpmeshmtrlbuffer;//材质贴图的临时缓冲
                  //从文件装载一个mesh物体:
			 D3DXLoadMeshFromX("c:\\",   //文件路径
			 			 			 			 			 			 D3DXMESH_SYSTEMMEM,//g_lpmesh被创建的位置,这里它被创建在系统内存而非显示内存
			 			 			 			 			 			 g_lpd3ddevice,NULL,&lpmeshmtrlbuffer,NULL, 										
			 			 			 			 			 			 &g_meshmtrlnum,//一个用于存放SubSet数量的变量指针
			 			 			 			 			 			 &g_lpmesh);//最后是要被创建的mesh指针  
			 //我们要一次性读取出全部材质和贴图信息,并都存放在这里:
			 D3DXMATERIAL *pd3dxmtrl=(D3DXMATERIAL*)lpmeshmtrlbuffer->GetBufferPointer(); 
			 //然后再细分:
			 g_meshmtrl=new D3DMATERIAL9[g_meshmtrlnum];
			 g_meshtex=new LPDIRECT3DTEXTURE9[g_meshmtrlnum]; 
			 //对每个SubSet,我们分别提取它的材质和贴图
			 for(DWORD i=0;i<g_meshmtrlnum;i++)
			 {
			 			 g_meshmtrl=pd3dxmtrl.MatD3D;
			 			 //实际上,pd3dxmtrl.pTextureFilename只是个文件名
			 			 TCHAR texname[512];//存放完整的贴图文件路径
			 			 strcpy(texname,"c:\\");
			 			 strcat(texname, pd3dxmtrl.pTextureFilename);
			 			 D3DXCreateTextureFromFile(g_lpd3ddevice,texname,&g_meshtex);
			 }
			 lpmeshmtrlbuffer->Release();
			 lpmeshmtrlbuffer = NULL;
			 return S_OK;
} 
打开*.x文件(如果是文本模式的)你会看到贴图在文件中只被记录该图片的文件名。而CreateTextureFromFile()所需要的参数是一个完整路径,所以如果这些图不在程序同一目录下,就要在代码中做些处理。否则我敢保证你什么也看不见。这里,我只是简单的使用了绝对路径。 
好,所有信息都被从文件中摘抄了出来,但现在还不是渲染的时候。没有进行坐标转换,目前所有顶点使用的,都是其局部的3D坐标,并非渲染函数能够直接使用的屏幕坐标。通常需要经过以下三种坐标转换:  |