c#

位置:IT落伍者 >> c# >> 浏览文章

VC.NET的Direct3D极速入门宝典


发布日期:2021年02月25日
 
VC.NET的Direct3D极速入门宝典

听说DirectX发布了吗?如果没有你现在也应该听我说过了那就去edede/dxbsdkexe下载一个最新的DirectX的SDK因为我将使用DD来进行全文的讲解其实DirectX里有非常详细的教程和参考大多数人只需要看看这些帮助就可以自己学习DD了我的这篇文章适合那些很懒但想快速入门不懂英文或编程知识很欠缺的人看装好DirectX打开新建一个Win工程在StdAfxh里添加下面的语句

#include // DD标准头文件

#include // DD数学库头文件

#include // 这个不用我说了吧?

#pragma comment( lib dd ) // DD的静态库

#pragma comment( lib ddx ) // DD数学库的静态库

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

#include stdafxh

#define MAX_LOADSTRING

HINSTANCE g_hInst;

HWND g_hWnd;

IDirectD *g_pDD;

IDirectDDevice *g_pddDevice;

IDirectDVertexBuffer *g_pVB;

TCHAR szTitle[MAX_LOADSTRING];

TCHAR szWindowClass[MAX_LOADSTRING];

ATOM MyRegisterClass(HINSTANCE hInstance);

BOOL InitInstance(HINSTANCE int);

LRESULT CALLBACK WndProc(HWND UINT WPARAM LPARAM);

LRESULT CALLBACK About(HWND UINT WPARAM LPARAM);

void OnIdle( void );

void OnCreate( HWND hWnd );

HRESULT InitDD( void );

HRESULT CreateObject( void );

void ReleaseDD( void );

HRESULT SetModalMatrix( void );

HRESULT SetProjMatrix( WORD wWidth WORD wHeight );

void BeforePaint( void );

int APIENTRY _tWinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPTSTR lpCmdLine int nCmdShow)

{

MSG msg;

HACCEL hAccelTable;

LoadString(hInstance IDS_APP_TITLE szTitle MAX_LOADSTRING);

LoadString(hInstance IDC_DDTEST szWindowClass MAX_LOADSTRING);

MyRegisterClass(hInstance);

if (!InitInstance (hInstance nCmdShow))

{

return FALSE;

}

hAccelTable = LoadAccelerators(hInstance (LPCTSTR)IDC_DDTEST);

while ( true )

{

if ( PeekMessage( &msg NULL PM_REMOVE ) )

{

if (!TranslateAccelerator(msghwnd hAccelTable &msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

continue;

}

if ( WM_QUIT == ssage )

{

break;

}

OnIdle();

}

UnregisterClass( szWindowClass g_hInst );

return (int)msgwParam;

}

ATOM MyRegisterClass( HINSTANCE hInstance )

{

WNDCLASSEX wcex;

wcexcbSize = sizeof(WNDCLASSEX);

wcexstyle = CS_HREDRAW | CS_VREDRAW;

wcexlpfnWndProc = (WNDPROC)WndProc;

wcexcbClsExtra = ;

wcexcbWndExtra = ;

wcexhInstance = hInstance;

wcexhIcon = LoadIcon(hInstance (LPCTSTR)IDI_DDTEST);

wcexhCursor = LoadCursor(NULL IDC_ARROW);

wcexhbrBackground = (HBRUSH)(COLOR_WINDOW+);

wcexlpszMenuName = (LPCTSTR)IDC_DDTEST;

wcexlpszClassName = szWindowClass;

wcexhIconSm = LoadIcon(wcexhInstance (LPCTSTR)IDI_SMALL);

return RegisterClassEx(&wcex);

}

BOOL InitInstance( HINSTANCE hInstance int nCmdShow )

{

g_hInst = hInstance;

CreateWindow( szWindowClass szTitle WS_OVERLAPPEDWINDOWCW_USEDEFAULT CW_USEDEFAULT NULL NULL hInstance NULL );

if ( !g_hWnd )

{

return FALSE;

}

ShowWindow( g_hWnd nCmdShow );

UpdateWindow( g_hWnd );

return TRUE;

}

LRESULT CALLBACK WndProc(HWND hWnd UINT message WPARAM wParam LPARAM lParam)

{

int wmId wmEvent;

switch (message)

{

case WM_CREATE:

OnCreate( hWnd );

break;

case WM_COMMAND:

wmId = LOWORD(wParam);

wmEvent = HIWORD(wParam);

switch (wmId)

{

case IDM_EXIT:

DestroyWindow(hWnd);

break;

default:

return DefWindowProc(hWnd message wParam lParam);

}

break;

case WM_SIZE:

SetProjMatrix( LOWORD( lParam ) HIWORD( lParam ) );

break;

case WM_DESTROY:

ReleaseDD();

PostQuitMessage();

break;

default:

return DefWindowProc(hWnd message wParam lParam);

}

return ;

}

void OnCreate( HWND hWnd )

{

g_hWnd = hWnd;

InitDD();

CreateObject();

}

void ReleaseDD( void )

{

}

HRESULT InitDD( void )

{

return S_OK;

}

void BeforePaint( void )

{

}

HRESULT CreateObject( void )

{

return S_OK;

}

void OnIdle( void )

{

}

HRESULT SetModalMatrix( void )

{

return S_OK;

}

HRESULT SetProjMatrix( WORD wWidth WORD wHeight )

{

return S_OK;

}

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

g_hInst = hInstance;

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

g_hWnd = hWnd;

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

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

g_pDD = DirectDCreate( DD_SDK_VERSION );

if( NULL == g_pDD )

{

return E_FAIL;

}

DDPRESENT_PARAMETERS ddpp;

ZeroMemory( &ddpp sizeof(ddpp) );

ddppWindowed = TRUE;

ddppSwapEffect = DDSWAPEFFECT_DISCARD;

ddppBackBufferFormat = DDFMT_ARGB;

g_pDD>CreateDevice( DDADAPTER_DEFAULT DDDEVTYPE_HAL g_hWnd

DDCREATE_HARDWARE_VERTEXPROCESSING | DDCREATE_PUREDEVICE

&ddpp &g_pddDevice );

g_pddDevice>SetRenderState( DDRS_LIGHTING TRUE );

g_pddDevice>SetRenderState( DDRS_AMBIENT

DDCOLOR_COLORVALUE( f f f ) );

g_pddDevice>LightEnable( TRUE);

DDMATERIAL mtrl;

ZeroMemory( &mtrl sizeof(mtrl) );

mtrlDiffuser = mtrlAmbientr = f / f;

mtrlDiffuseg = mtrlAmbientg = f / f;

mtrlDiffuseb = mtrlAmbientb = f / f;

mtrlDiffusea = mtrlAmbienta = f;

g_pddDevice>SetMaterial( &mtrl );

return S_OK;

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

ddppWindowed = TRUE; // 设备是窗口设备而不是全屏

ddppSwapEffect = DDSWAPEFFECT_DISCARD; // 翻转缓沖区时不改动后台缓沖

ddppBackBufferFormat = DDFMT_ARGB; // ARGB颜色模式

在这之后我们就可以调用CreateDevice来创建设备了第一个参数指定使用主显示驱动第二个参数指定该设备是否使用硬件来处理显示第三个参数当然是你的窗体句柄第四个参数如果指定DDCREATE_HARDWARE_VERTEXPROCESSING | DDCREATE_               

上一篇:用C#轻松地在DOTNET中实现缩略图

下一篇:C#中的数组和C++中数组的区别