VC.NET的Direct3D极速入门宝典

时间:2007-06-15 来源: 作者: 【字体: 减小 增大收藏 | 投稿
  

  听说DirectX9.0发布了吗?如果没有,你现在也应该听我说过了,那就去http://download.microsoft.com/download/b/6/a/b6ab32f3-39e8-4096-9445-d38e6675de85/dx90bsdk.exe下载一个最新的DirectX9.0的SDK,因为我将使用D3D9来进行全文的讲解。其实DirectX9.0里有非常详细的教程和参考,大多数人只需要看看这些帮助就可以自己学习D3D了,我的这篇文章适合那些很懒但想快速入门、不懂英文或编程知识很欠缺的人看。装好DirectX9.0后,打开VC.net,新建一个Win32工程,在StdAfx.h里添加下面的语句: 财,软联盟,fs119.net

程序代码:

#include<d3d9.h>//D3D标准头文件
#include<D3dx9math.h>//D3D数学库头文件
#include<stdio.h>//这个不用我说了吧?
#pragmacomment(lib,"d3d9")//D3D的静态库
#pragmacomment(lib,"d3dx9")//D3D数学库的静态库

  然后把winmain所在文件的代码做如下的修改:

财管家,园,fs119.net

程序代码:


#include"stdafx.h"
#defineMAX_LOADSTRING100

HINSTANCEg_hInst;
HWNDg_hWnd;
IDirect3D9*g_pD3D;
IDirect3DDevice9*g_pd3dDevice;
IDirect3DVertexBuffer9*g_pVB;

TCHARszTitle[MAX_LOADSTRING];
TCHARszWindowClass[MAX_LOADSTRING];
ATOMMyRegisterClass(HINSTANCEhInstance);
BOOLInitInstance(HINSTANCE,int);
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
LRESULTCALLBACKAbout(HWND,UINT,WPARAM,LPARAM);
voidOnIdle(void);
voidOnCreate(HWNDhWnd);
HRESULTInitD3D(void);
HRESULTCreateObject(void);
voidReleaseD3D(void);
HRESULTSetModalMatrix(void);
HRESULTSetProjMatrix(WORDwWidth,WORDwHeight);
voidBeforePaint(void);
intAPIENTRY_tWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPTSTRlpCmdLine,intnCmdShow)
{
 MSGmsg;
 HACCELhAccelTable;

 LoadString(hInstance,IDS_APP_TITLE,szTitle,MAX_LOADSTRING);
 LoadString(hInstance,IDC_D3DTEST,szWindowClass,MAX_LOADSTRING);
财软联盟,fs119.net

 MyRegisterClass(hInstance);

 if(!InitInstance(hInstance,nCmdShow))
 {
  returnFALSE;
 }

 hAccelTable=LoadAccelerators(hInstance,(LPCTSTR)IDC_D3DTEST);

 while(true)
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   if(!TranslateAccelerator(msg.hwnd,hAccelTable,&msg))
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
  continue;
  }
  if(WM_QUIT==msg.message)
  {
   break;
  }
  OnIdle();
 } 
 UnregisterClass(szWindowClass,g_hInst);
 return(int)msg.wParam;
}

ATOMMyRegisterClass(HINSTANCEhInstance)
{
 WNDCLASSEXwcex;
 wcex.cbSize=sizeof(WNDCLASSEX);
 wcex.style=CS_HREDRAW|CS_VREDRAW;
 wcex.lpfnWndProc=(WNDPROC)WndProc;
 wcex.cbClsExtra=0;
 wcex.cbWndExtra=0;
 wcex.hInstance=hInstance;
 wcex.hIcon=LoadIcon(hInstance,(LPCTSTR)IDI_D3DTEST);
 wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
财软联盟,fs119.net

 wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW1);
 wcex.lpszMenuName=(LPCTSTR)IDC_D3DTEST;
 wcex.lpszClassName=szWindowClass;
 wcex.hIconSm=LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL);
 returnRegisterClassEx(&wcex);
}

BOOLInitInstance(HINSTANCEhInstance,intnCmdShow)
{
 g_hInst=hInstance;
 CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
 if(!g_hWnd)
 {
  returnFALSE;
 }
 ShowWindow(g_hWnd,nCmdShow);
 UpdateWindow(g_hWnd);
 returnTRUE;
}

LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{
 intwmId,wmEvent;
 switch(message)
 {
  caseWM_CREATE:
   OnCreate(hWnd);
   break;
  caseWM_COMMAND:
   wmId=LOWORD(wParam);
   wmEvent=HIWORD(wParam);
   switch(wmId)
   {
    caseIDM_EXIT:
     DestroyWindow(hWnd);
     break;

财软联盟 fs119.net


    default:
     returnDefWindowProc(hWnd,message,wParam,lParam);
   }
   break;
  caseWM_SIZE:
   SetProjMatrix(LOWORD(lParam),HIWORD(lParam));
   break;
  caseWM_DESTROY:
   ReleaseD3D();
   PostQuitMessage(0);
   break;
  default:
   returnDefWindowProc(hWnd,message,wParam,lParam);
 }
 return0;
}

voidOnCreate(HWNDhWnd)
{
 g_hWnd=hWnd;
 InitD3D();
 CreateObject();
}

voidReleaseD3D(void)
{
}

HRESULTInitD3D(void)
{
 returnS_OK;
}

voidBeforePaint(void)
{
}

HRESULTCreateObject(void)
{
 returnS_OK;
}

voidOnIdle(void)
{
}

HRESULTSetModalMatrix(void)
{
 returnS_OK;
}

HRESULTSetProjMatrix(WORDwWidth,WORDwHeight)
{
 returnS_OK;
}

  上面的代码仅是一个框架,仔细研究过上篇文章的朋友应该非常清楚这些代码的含意,不过我还是需要大至讲解一下。在InitInstance函数中,初始化程序实例的开始,我们将该实例的句柄放到全局变量中去,以便以后使用: 财软联,盟,fs119.net

g_hInst=hInstance;

  在创建窗体时,我并没有直接将CreateWindow的返回值——创建成功的窗体句柄赋给全局变量g_hWnd,因为CreateWindow函数在执行中会引发几个消息,其中有WM_CREATE,在这个消息的处理函数中OnCreate中,我执行了下面的语句:

g_hWnd=hWnd;

  这样,我们就可以早一点用到g_hWnd了。SetProjMatrix是设置投影矩阵的,投影矩形仅受窗口纵横比影响,所以在WM_SIZE事件时调用时就可以了。而SetModalMatrix是设置模型矩阵的,也就是眼睛点和视点之类的东东,所以它一定要在Rander的时候,准确的说是在Render之前执行。InitD3D在窗体创建时调用,用于初始化D3D设备。CreateObject和InitD3D一样是初始化函数,它用于创建三维对象。

财管家园.fs119.net

财软联 盟 fs119.net

财 管家园 fs119.net


财管家 园 fs119.net

财软联.盟.fs119.net

  下面我们来填写代码,首先是初始化,我们在InitD3D函数里填写下面的代码:

财,软联盟,fs119.net

程序代码:
g_pD3D=Direct3DCreate9(D3D_SDK_VERSION);

if(NULL==g_pD3D)

{

returnE_FAIL;

}



D3DPRESENT_PARAMETERSd3dpp;

ZeroMemory(&d3dpp,sizeof(d3dpp));

d3dpp.Windowed=TRUE;

d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;

d3dpp.BackBufferFormat=D3DFMT_A8R8G8B8;



g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWnd,

D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE,

&d3dpp,&g_pd3dDevice);

g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);

g_pd3dDevice->SetRenderState(D3DRS_AMBIENT,

D3DCOLOR_COLORVALUE(0.3f,0.3f,0.3f,1.0));

g_pd3dDevice->LightEnable(0,TRUE);



D3DMATERIAL9mtrl;

ZeroMemory(&mtrl,sizeof(mtrl));

mtrl.Diffuse.r=mtrl.Ambient.r=140.0f/255.0f;

mtrl.Diffuse.g=mtrl.Ambient.g=200.0f/255.0f;

mtrl.Diffuse.b=mtrl.Ambient.b=255.0f/255.0f;

财.管家园.fs119.net



mtrl.Diffuse.a=mtrl.Ambient.a=1.0f;

g_pd3dDevice->SetMaterial(&mtrl);

returnS_OK;

  Direct3DCreate9函数为我们创建了一个D3D接口指针,并将接口指针返回到全局变量中保存起来,参数必须为D3D_SDK_VERSION。D3DPRESENT_PARAMETERS是一个结构体,它就像OpenGL中的PixelFormat一样,是创建时指定设备的一些属性的。

d3dpp.Windowed=TRUE;//设备是窗口设备而不是全屏
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;//翻转缓冲区时不改动后台缓冲
d3dpp.BackBufferFormat=D3DFMT_A8R8G8B8;//ARGB颜色模式
  在这之后,我们就可以调用CreateDevice来创建设备了,第一个参数指定使用主显示驱动,第二个参数指定该设备是否使用硬件来处理显示,第三个参数当然是你的窗体句柄,第四个参数如果指定D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE效率会提高不少。 财软联盟 fs119.net

g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
g_pd3dDevice->SetRenderState(D3DRS_AMBIENT,D3DCOLOR_COLORVALUE(0.6f,0.6f,0.6f,1.0));
  这两句用于打开灯光和设置环境光照颜色。接着我设置了材质:

mtrl.Diffuse.r=mtrl.Ambient.r=140.0f/255.0f;
mtrl.Diffuse.g=mtrl.Ambient.g=200.0f/255.0f;
mtrl.Diffuse.b=mtrl.Ambient.b=255.0f/255.0f;
mtrl.Diffuse.a=mtrl.Ambient.a=1.0f;
  为了和上一篇的例程做对比,我使用了相同的材质。当CreateDevice执行成功后,我们就该创建基于D3D的三维物体了。

D3DVECTORSrcBox[]={
 {5.0f,5.0f,0.0f},{5.0f,5.0f,10.0f},
 {5.0f,-5.0f,0.0f},{5.0f,-5.0f,10.0f},
 {-5.0f,-5.0f,0.0f},{-5.0f,-5.0f,10.0f},
 {-5.0f,5.0f,0.0f},{-5.0f,5.0f,10.0f},

财软联盟 fs119.net

};

WORDwIndex[]={
 0,4,6,0,2,4,
 0,6,7,0,7,1,
 0,3,2,0,1,3,
 5,2,3,5,4,2,
 5,6,4,5,7,6,
 5,1,7,5,3,1,
};
  要说明的是D3D为我们准备了很好用的结构体D3DVECTOR,封装了三维座标的X、Y和Z。我们还需要再定义一个我们自己的结构体来存放我们的三维座标信息:

structCUSTOMVERTEX
{
 D3DVECTORpos;
 D3DVECTORnormal;
};
  第一个成员pos用来存储顶点座标数据,第二个成员normal用来存储这个点所在平面的法向量——这个概念我在上一篇讲过的。和OpenGL一样,我们同样需要按索引序展开顶点数组:

CUSTOMVERTEXExpandBox[sizeof(wIndex)/sizeof(WORD)];
for(inti=0;i<36;i)
{
 ExpandBox[i].pos=SrcBox[wIndex[i]];
}
  然后用下面的代码为顶点计算法向量。 财 管家园 fs119.net

for(i=0;i<12;i)
{
 D3DVECTORTri[3];
 Tri[0]=ExpandBox[i*30].pos;
 Tri[1]=ExpandBox[i*31].pos;
 Tri[2]=ExpandBox[i*32].pos;
 ExpandBox[i*30].normal.x=0.0f;
 ExpandBox[i*30].normal.y=0.0f;
 ExpandBox[i*30].normal.z=1.0f;
 CalcNormal(Tri,&(ExpandBox[i*30].normal));
 ExpandBox[i*31].normal=ExpandBox[i*30].normal;
 ExpandBox[i*32].normal=ExpandBox[i*30].normal;
}

  在这里我需要花点篇幅讲一个概念,一个仅在D3D中存在的概念FVF。D3D在处理显示数据时和OpenGL的方式不大一样,OpenGL是指定独立的数组,比如VertexBuffer、IndexBuffer、NormalBuffer等,而D3D是把每一个顶点的这些数据放在一起,组成一个单元进行处理,也就是说只有一个数组,而在数组的每一个元素中都包括了单个顶点的所有数据,所以他被称为FlexibleVertexFormat,我刚才定义的结构体CUSTOMVERTEX也就是做为数组的一个单元。每一个单元可以包含你所需要的信息,比如你只需要顶点座标数据和颜色,那么你只需要对那个结构体稍加修改就可以了,但是怎么让D3D知道你的结构体里包含哪些数据呢?当然,我们可以在CreateVertexBuffer的时候指定一个参数来告诉D3D:D3DFVF_XYZ|D3DFVF_NORMAL,在很多地方我们都可能用到这个值,所以为了方便使用和维护我们定义一个宏来表示它: 财管家.园.fs119.net

#defineD3DFVF_CUSTOMVERTEX(D3DFVF_XYZ|D3DFVF_NORMAL) 财管家.园.fs119.net

财软联.盟.fs119.net

财软联 盟 fs119.net

财管家园 fs119.net


财软联,盟,fs119.net

财管家 园 fs119.net

  那么到这里你可以会问另一个问题,也许D3D可以知道我们的元素里包含顶点的哪些数据,但D3D又是怎样得知这些数据在结构体里,也就是在内存中的排列顺序的呢?很不幸,D3D无法得知你的排列顺序,但D3D指定了这些数据的排列顺序,比如法向量一定在顶点后面,而颜色又一定要放在法向量后面。关于这个排列顺序表你得去看看MSDN里关于VertexFormats的详细说明了。下面我们来创建顶点数组:

if(FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(ExpandBox),
0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&g_pVB,NULL)))
{
 returnE_FAIL;
}
  这些参数上面都提到过,相信你一看就会明白,我就不多说了。怎样把我们的方盒数据存储进这创建好的顶点缓冲区呢?DirectX有自己的内存管理方式,这一点我在前面写的一篇《Winamp详解》里提到过,也就是Lock和UnLock的模式:

财 软联盟 fs119.net


VOID*pVertices;

if(FAILED(g_pVB->Lock(0,sizeof(ExpandBox),(void**)&pVertices,0)))

returnE_FAIL;

MoveMemory(pVertices,ExpandBox,sizeof(ExpandBox));

g_pVB->Unlock();
  和OpenGL一样,在初始化工作结束后,必须要做的另一件事就是设置矩阵,首先是投影矩阵,我们把这些代码加到SetProjMatrix函数中去:

D3DXMATRIXmatProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,(float)wWidth/(float)wHeight,1.0f,100.0f);

returng_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
  然后是视图矩阵,把下面的代码加到SetModalMatrix中

staticfloatfRadius=0.5f;
fRadius-=0.003f;
if(fRadius<0)
{
 fRadius=D3DX_PI*2;
} 财,管家园,fs119.net

D3DXMATRIXmatWorld;
D3DXMatrixRotationZ(&matWorld,0.0f);
if(FAILED(g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld)))
{
 returnE_FAIL;
}

D3DXMATRIXmatView;
D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(cosf(fRadius)*40.0f,sinf(fRadius)*40.0f,30.0),&D3DXVECTOR3(0.0f,0.0f,0.0f),&D3DXVECTOR3(0.0f,0.0f,1.0f));

g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
returnS_OK;
  我想我不说你也可以理解这些代码的含义,是不是和OpenGL非常相似呢?好的,现在一切准备工作就续,现在我们可以开始绘制方盒了。找到OnIdel处理函数,然后在这里添加下面的代码:

if(g_pd3dDevice!=NULL)
{
 g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(255,255,200),1.0f,0);
 if(SUCCEEDED(g_pd3dDevice->BeginScene()))
 {
  BeforePaint();
  if(FAILED(SetModalMatrix()))
财软联 盟 fs119.net

  {
   return;
  }
  g_pd3dDevice->SetStreamSource(0,g_pVB,0,sizeof(CUSTOMVERTEX));
  g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
  g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,12);
  g_pd3dDevice->EndScene();
  g_pd3dDevice->Present(NULL,NULL,NULL,NULL);
 }
}
  g_pd3dDevice->Clear相当于glClear,g_pd3dDevice->BeginScene和g_pd3dDevice->EndScene相当于glBegin和glEnd,g_pd3dDevice->SetStreamSource相当于glSet**Pointer,g_pd3dDevice->DrawPrimitive相当于glDrawArray,g_pd3dDevice->Present相当于SwapBuffer,这里和OpenGL的不同之处在于D3D在这里要设备FVF,一个很简单的过程:

g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);

  另外,D3D的背景色是在Clear的时候指定的。现在你可以运行你的程序了,但是你会发现,盒子是黑色的一片,那是因为你没有打开任何光源。而OpenGL在没有打开任何光源时物体是纯白色的,呵呵,具有一定的迷惑性哦~现在我们来打开一个灯,来照亮这个物体。就在BeforePaint里:
财软联 盟 fs119.net


D3DLIGHT9light;
ZeroMemory(&light,sizeof(light));
light.Position=D3DXVECTOR3(30.0f,30.0f,30.0f);
light.Attenuation1=0.05f;
light.Diffuse.r=1.0f;
light.Diffuse.g=1.0f;
light.Diffuse.b=1.0f;
light.Range=1000.0f;
light.Type=D3DLIGHT_POINT;
g_pd3dDevice->SetLight(0,&light);
g_pd3dDevice->LightEnable(0,TRUE);

  为什么要放在BeforePaint里呢?因为我们在后面还可以实现动态光影的效果,也就是让光源动起来。这里要格外注意的时,这个顶不是方向光源,是一个点光源,D3DLIGHT_POINT,它的光是没有方向,从座标点向四周任何方向发散的,他也具有衰减性,你可以设置三个衰减分量,在D3D里的衰减公式是:Atten=1/(att0att1*datt2*d*d)所以,当你的三个衰减值都为0时,就会出错。在这里我们用到了att1,让它等于0.05,很小的值对吗?越小表示衰减越小,光照也就越强。

财软联盟 fs119.net



  现在你的代码应该是这样样子:

#include"stdafx.h"
#include"D3DTest.h"
#defineMAX_LOADSTRING100
#defineD3DFVF_CUSTOMVERTEX(D3DFVF_XYZ|D3DFVF_NORMAL)

structCUSTOMVERTEX
{
 D3DVECTORpos;
 D3DVECTORnormal;
};

HINSTANCEg_hInst;
HWNDg_hWnd;
IDirect3D9*g_pD3D;
IDirect3DDevice9*g_pd3dDevice;
IDirect3DVertexBuffer9*g_pVB;

TCHARszTitle[MAX_LOADSTRING];
TCHARszWindowClass[MAX_LOADSTRING];
ATOMMyRegisterClass(HINSTANCEhInstance);
BOOLInitInstance(HINSTANCE,int);
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
LRESULTCALLBACKAbout(HWND,UINT,WPARAM,LPARAM);
voidOnIdle(void);
voidOnCreate(HWNDhWnd);
HRESULTInitD3D(void);
HRESULTCreateObject(void);
voidReleaseD3D(void);
HRESULTSetModalMatrix(void);
HRESULTSetProjMatrix(WORDwWidth,WORDwHeight);
voidBeforePaint(void);
voidCalcNormal(constD3DVECTOR*pVertices,D3DVECTOR*pNormal)
{ 财管家 园 fs119.net
 D3DVECTORv1,v2;
 v1.x=pVertices[0].x-pVertices[1].x;
 v1.y=pVertices[0].y-pVertices[1].y;
 v1.z=pVertices[0].z-pVertices[1].z;
 v2.x=pVertices[1].x-pVertices[2].x;
 v2.y=pVertices[1].y-pVertices[2].y;
 v2.z=pVertices[1].z-pVertices[2].z;
 D3DXVECTOR3Temp(v1.y*v2.z-v1.z*v2.y,v1.z*v2.x-v1.x*v2.z,v1.x*v2.y-v1.y*v2.x);
 D3DXVec3Normalize((D3DXVECTOR3*)pNormal,&Temp);

}

classCTimer
{
 public:
  CTimer(){QueryPerformanceFrequency(&m_Frequency);Start();}
  voidStart(){QueryPerformanceCounter(&m_StartCount);}
  doubleEnd(){LARGE_INTEGERCurrentCount;QueryPerformanceCounter(&CurrentCount);returndouble(CurrentCount.LowPart-m_StartCount.LowPart)/(double)m_Frequency.LowPart;}

 private:
  LARGE_INTEGERm_Frequency;
  LARGE_INTEGERm_StartCount;
};

intAPIENTRY_tWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{
 MSGmsg;
 HACCELhAccelTable; 财软.联盟.fs119.net
 LoadString(hInstance,IDS_APP_TITLE,szTitle,MAX_LOADSTRING);
 LoadString(hInstance,IDC_D3DTEST,szWindowClass,MAX_LOADSTRING);
 MyRegisterClass(hInstance);
 if(!InitInstance(hInstance,nCmdShow))
  returnFALSE;
 hAccelTable=LoadAccelerators(hInstance,(LPCTSTR)IDC_D3DTEST);

 while(true)
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   if(!TranslateAccelerator(msg.hwnd,hAccelTable,&msg))
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
   continue;
  }
  if(WM_QUIT==msg.message)
   break;
  OnIdle();
 }

 UnregisterClass(szWindowClass,g_hInst);
 return(int)msg.wParam;
}

ATOMMyRegisterClass(HINSTANCEhInstance)
{
 WNDCLASSEXwcex;
 wcex.cbSize=sizeof(WNDCLASSEX);
 wcex.style=CS_HREDRAW|CS_VREDRAW;
 wcex.lpfnWndProc=(WNDPROC)WndProc;
 wcex.cbClsExtra=0;
 wcex.cbWndExtra=0;
 wcex.hInstance=hInstance; 财管家园,fs119.net
 wcex.hIcon=LoadIcon(hInstance,(LPCTSTR)IDI_D3DTEST);
 wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
 wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW1);
 wcex.lpszMenuName=(LPCTSTR)IDC_D3DTEST;
 wcex.lpszClassName=szWindowClass;
 wcex.hIconSm=LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL);
 returnRegisterClassEx(&wcex);
}

BOOLInitInstance(HINSTANCEhInstance,intnCmdShow)
{
 g_hInst=hInstance;
 CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
 if(!g_hWnd)
 {
  returnFALSE;
 }
 ShowWindow(g_hWnd,nCmdShow);
 UpdateWindow(g_hWnd);
 returnTRUE;
}

LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{
 intwmId,wmEvent;
 switch(message)
 {
  caseWM_CREATE:
   OnCreate(hWnd);
   break;
  caseWM_COMMAND:
   wmId=LOWORD(wParam);
   wmEvent=HIWORD(wParam);
   switch(wmId)
财管家园.fs119.net

   {
    caseIDM_EXIT:
     DestroyWindow(hWnd);
     break;
    default:
     returnDefWindowProc(hWnd,message,wParam,lParam);
   }
   break;
  caseWM_SIZE:
   SetProjMatrix(LOWORD(lParam),HIWORD(lParam));
   break;
  caseWM_DESTROY:
   ReleaseD3D();
   PostQuitMessage(0);
   break;
  default:
   returnDefWindowProc(hWnd,message,wParam,lParam);
 }
 return0;
}

voidOnCreate(HWNDhWnd)
{
 g_hWnd=hWnd;
 InitD3D();
 CreateObject();
}

voidReleaseD3D(void)
{
 if(g_pVB!=NULL)
 {
  g_pVB->Release();
 }
 if(g_pd3dDevice!=NULL)
 {
  g_pd3dDevice->Release();
 }
 if(g_pD3D!=NULL)
 {
  g_pD3D->Release();
 }
}
HRESULTInitD3D(void)
{
g_pD3D=Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERSd3dpp;
ZeroMemory(&d3dpp,sizeof(d3dpp)); 财软联盟 fs119.net
d3dpp.Windowed=TRUE;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat=D3DFMT_A8R8G8B8;
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE,
&d3dpp,&g_pd3dDevice);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
g_pd3dDevice->SetRenderState(D3DRS_AMBIENT,
D3DCOLOR_COLORVALUE(0.6f,0.6f,0.6f,1.0));
g_pd3dDevice->LightEnable(0,TRUE);
D3DMATERIAL9mtrl;
ZeroMemory(&mtrl,sizeof(mtrl));
mtrl.Diffuse.r=mtrl.Ambient.r=140.0f/255.0f;
mtrl.Diffuse.g=mtrl.Ambient.g=200.0f/255.0f;
mtrl.Diffuse.b=mtrl.Ambient.b=255.0f/255.0f;
mtrl.Diffuse.a=mtrl.Ambient.a=1.0f;
g_pd3dDevice->SetMaterial(&mtrl);
returnS_OK;
}
voidBeforePaint(void)
{
D3DLIGHT9light;
ZeroMemory(&light,sizeof(light));
light.Position=D3DXVECTOR3(30.0f,30.0f,30.0f);
light.Attenuation1=0.05f;
light.Diffuse.r=1.0f;
light.Diffuse.g=1.0f;
light.Diffuse.b=1.0f;
light.Range=1000.0f;
财管家园.fs119.net

light.Type=D3DLIGHT_POINT;
g_pd3dDevice->SetLight(0,&light);
g_pd3dDevice->LightEnable(0,TRUE);
}
HRESULTCreateObject(void)
{
D3DVECTORSrcBox[]={
{5.0f,5.0f,0.0f},{5.0f,5.0f,10.0f},
{5.0f,-5.0f,0.0f},{5.0f,-5.0f,10.0f},
{-5.0f,-5.0f,0.0f},{-5.0f,-5.0f,10.0f},
{-5.0f,5.0f,0.0f},{-5.0f,5.0f,10.0f},
};
WORDwIndex[]={
0,4,6,0,2,4,
0,6,7,0,7,1,
0,3,2,0,1,3,
5,2,3,5,4,2,
5,6,4,5,7,6,
5,1,7,5,3,1,
};
CUSTOMVERTEXExpandBox[sizeof(wIndex)/sizeof(WORD)];
for(inti=0;i<36;i)
ExpandBox[i].pos=SrcBox[wIndex[i]];
for(i=0;i<12;i)
{
D3DVECTORTri[3];
Tri[0]=ExpandBox[i*30].pos;
Tri[1]=ExpandBox[i*31].pos;
Tri[2]=ExpandBox[i*32].pos;
ExpandBox[i*30].normal.x=0.0f;
ExpandBox[i*30].normal.y=0.0f;
ExpandBox[i*30].normal.z=1.0f;
CalcNormal(Tri,&(ExpandBox[i*30].normal));
ExpandBox[i*31].normal=ExpandBox[i*30].normal;
ExpandBox[i*32].normal=ExpandBox[i*30].normal;
}
g_pd3dDevice->CreateVertexBuffer(sizeof(ExpandBox),

财管家,园,fs119.net


0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&g_pVB,NULL);
VOID*pVertices;
g_pVB->Lock(0,sizeof(ExpandBox),(void**)&pVertices,0);
MoveMemory(pVertices,ExpandBox,sizeof(ExpandBox));
g_pVB->Unlock();
returnS_OK;
}
voidOnIdle(void)
{
staticCTimert;
staticdoubledt=t.End();
doubletemp=t.End();
charszValue[256];
sprintf(szValue,"当前帧率:%f",1/(temp-dt));
SetWindowText(g_hWnd,szValue);
dt=temp;
if(g_pd3dDevice!=NULL)
{
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(255,255,200),1.0f,0);
if(SUCCEEDED(g_pd3dDevice->BeginScene()))
{
BeforePaint();
if(FAILED(SetModalMatrix()))
{
return;
}
g_pd3dDevice->SetStreamSource(0,g_pVB,0,sizeof(CUSTOMVERTEX));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,12);
g_pd3dDevice->EndScene();
g_pd3dDevice->Present(NULL,NULL,NULL,NULL);
}
}
}
HRESULTSetModalMatrix(void)
{
staticfloatfRadius=0.5f;

财软联盟 fs119.net


fRadius-=0.003f;
if(fRadius<0)
{
fRadius=D3DX_PI*2;
}
D3DXMATRIXmatWorld;
D3DXMatrixRotationZ(&matWorld,0.0f);
if(FAILED(g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld)))
{
returnE_FAIL;
}
D3DXMATRIXmatView;
D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(cosf(fRadius)*40.0f,sinf(fRadius)*40.0f,30.0),
&D3DXVECTOR3(0.0f,0.0f,0.0f),
&D3DXVECTOR3(0.0f,0.0f,1.0f));
g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
returnS_OK;
}
HRESULTSetProjMatrix(WORDwWidth,WORDwHeight)
{
D3DXMATRIXmatProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,(float)wWidth/(float)wHeight,1.0f,100.0f);
returng_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
}  

  看看和OpenGL做出来的哪个效果更好一些呢?我想使用D3D来做这些事会很方便吧。
财软联.盟.fs119.net

财管 家园 fs119.net

财软,联盟,fs119.net


相关文章
  • VCGDI编程的字体和文本绘制
  • 用VisualC.NET进行GDI编程
  • VC.NET实现应用程序XP风格
  • 用VisualC.NET实现XML解析
  • VC.NET中使用Windows.Forms
  • VC.NET2003代码优化方法
  • VisualC.NET中的字符串转换方法
  • 在managedC应用中使用ADO.NET
  • VISUALC6.0在MDI主框架窗口中添
  • VisualC2005中混合代码的初始化
  • 体验VisualC.NET2005中的STL
  • 用VC.NET制作启动屏幕的新方法
  • VisualStudio2005中C的变化
  • VC.NET中定义和使用MFCDLL
  • VC.NET的Direct3D极速入门宝典
  • VC.NET开发环境整合技巧
  • VisualC.NETDirectShow编程
  • 基于VC.NET的GDI编程之CImage
  • 基于VC.NET的GDI图像处理
  • 利用VisualC实现AVI文件的图像截
  • VisualC.NETGDI编程基础
  • VisualC.NET编程讲座之八
  • VisualC.NET编程讲座之七
  • VisualC.NET编程讲座之六
  • Google.cn搜索关键字: 宝典 入门 void return ExpandBox NULL hInstance if
    Google.cn搜索相关文章:
    谷歌中搜索全球网 VC.NET的Direct3D极速入门宝典
    百度中搜索 VC.NET的Direct3D极速入门宝典
    谷歌中搜索www.fs119.net VC.NET的Direct3D极速入门宝典
    上一篇:VC.NET开发环境整合技巧
    下一篇:VC.NET中定义和使用MFCDLL

    精品课程推荐


    相关栏目
    热点专题
    最新主题
    推荐大折扣培训课程