大家好,欢迎来到IT知识分享网。
1、d3d9的介绍
Direct3D 9(简称 D3D9)是 Microsoft 提供的一种 API,用于在 Windows 操作系统上进行 3D 图形渲染。它是 DirectX 套件的一部分,被广泛应用于游戏开发和其他需要图形渲染的应用程序。以下是对 D3D9 的详细解释:
1. 概述
D3D9 提供了一组 API,允许开发者使用 C++ 编写高性能的 3D 应用程序。通过 D3D9,可以直接访问图形硬件(GPU),以实现复杂的图形效果和高效的渲染。
2. 核心概念
Direct3D 对象:
- IDirect3D9 是 D3D9 的核心对象,所有的 D3D9 操作都从这个对象开始。你可以使用 Direct3DCreate9 函数来创建这个对象。
设备对象:
- IDirect3DDevice9 是渲染的核心,它代表了与图形硬件的一个连接。你可以通过 IDirect3D9::CreateDevice 函数来创建设备对象。
交换链:
- 交换链(Swap Chain)负责管理渲染缓冲区(Back Buffer),并将其呈现到显示器上。IDirect3DSwapChain9 接口表示一个交换链。
顶点缓冲区和索引缓冲区:
- 顶点缓冲区(Vertex Buffer)和索引缓冲区(Index Buffer)分别存储顶点数据和顶点索引数据,用于描述几何图形。
纹理:
- 纹理(Texture)是应用于几何图形表面的图像。IDirect3DTexture9 接口表示一个 2D 纹理。
着色器:
- 着色器(Shader)是用于在 GPU 上运行的小程序,可以控制顶点处理和像素处理。D3D9 支持 HLSL(高阶着色语言)。
3. 初始化和渲染流程
初始化 Direct3D:
#include <d3d9.h> // 初始化 Direct3D 对象 LPDIRECT3D9 d3d = Direct3DCreate9(D3D_SDK_VERSION); if (d3d == NULL) {
// 错误处理 return; } // 设置设备参数 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; // 窗口模式 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 交换效果 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // 后备缓冲区格式 // 创建 Direct3D 设备 LPDIRECT3DDEVICE9 d3ddev; if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev))) {
// 错误处理 d3d->Release(); return; }
// 清空缓冲区 d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); // 开始渲染 d3ddev->BeginScene(); // 渲染代码 // ... // 结束渲染 d3ddev->EndScene(); // 显示渲染结果 d3ddev->Present(NULL, NULL, NULL, NULL);
释放资源:
d3ddev->Release(); d3d->Release();
4. 常见用法
渲染三角形:
struct CUSTOMVERTEX {
FLOAT x, y, z; DWORD color; }; #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE) // 创建顶点缓冲区 LPDIRECT3DVERTEXBUFFER9 v_buffer; d3ddev->CreateVertexBuffer(3 * sizeof(CUSTOMVERTEX), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL); // 定义顶点数据 CUSTOMVERTEX vertices[] = {
{
0.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0) }, {
1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0) }, {
-1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255) }, }; // 填充顶点缓冲区 void* pVoid; v_buffer->Lock(0, 0, (void**)&pVoid, 0); memcpy(pVoid, vertices, sizeof(vertices)); v_buffer->Unlock(); // 渲染顶点缓冲区 d3ddev->SetFVF(CUSTOMFVF); d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX)); d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
5. 先进特性
光照和材质:
- D3D9 支持多种光照模型(如点光源、平行光源)和材质属性,可以实现逼真的光影效果。
着色器和效果:
- 通过使用 HLSL 编写自定义的顶点着色器和像素着色器,可以实现复杂的图形效果。
多线程渲染:
- D3D9 提供了一些多线程支持,允许在多个线程中执行图形命令,提高渲染效率。
6. 总结
- DirectX SDK
- Microsoft Docs – Direct3D 9
D3D9 是一个功能强大的图形 API,通过它,你可以创建各种复杂的 3D 图形效果和高性能的图形应用程序。希望这些详细的解释和代码示例能帮助你更好地理解和使用 D3D9。
2、d3d9demo详解
- 以下是对这段代码的详细解释。这段代码主要实现了一个 Direct3D 9 的应用程序框架,使用 DXUT 框架来管理 Direct3D 设备和窗口。代码还集成了一个名为 IGW 的组件,用于登录和支付功能。
代码如下:
//-------------------------------------------------------------------------------------- // File: EmptyProject.cpp // // Empty starting point for new Direct3D applications // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- #include "dxstdafx.h" #include "resource.h" #include <xstring> #include "interface.h" #include "DXUTgui.h" #include "Oleauto.h" #include "comutil.h" #include <time.h> //#pragma comment(lib, "comsupp.lib") #include "SDOA4Client.h" #include "SDOADx9.h" /* 接入相关全局变量 */ HINSTANCE g_hInstIGWDll = 0; LPigwInitialize igwInitialize = NULL; LPigwGetModule igwGetModule = NULL; LPigwTerminal igwTerminal = NULL; ISDOADx9* g_SDOADx9 = NULL; ISDOAApp3* g_SDOAApp = NULL; ISDOLLogin4* g_SDOLogin = NULL; ISDOAAppUtils* g_SDOAAppUtils = NULL; ISDOAClientService* g_SDOAClientService = NULL; extern HMODULE LoadModuleEx(LPCWSTR lpszPath); /* 释放IGW */ void CloseIGW() {
if (g_SDOADx9) {
g_SDOADx9->Release(); g_SDOADx9 = NULL; } if (g_SDOAApp) {
g_SDOAApp->Release(); g_SDOAApp = NULL; } if (g_SDOAAppUtils) {
g_SDOAAppUtils->Release(); g_SDOAAppUtils = NULL; } if (g_SDOAClientService) {
g_SDOAClientService->Release(); g_SDOAClientService = NULL; } if(g_SDOLogin) {
g_SDOLogin->Release(); g_SDOLogin = NULL; } if (igwTerminal) {
// 释放DLL前总是先调用igwTerminal igwTerminal(); igwTerminal = NULL; } if (g_hInstIGWDll) {
FreeLibrary(g_hInstIGWDll); g_hInstIGWDll = 0; } igwInitialize = NULL; } /* 加载IGW */ void OpenIGW() {
WCHAR strExePath[MAX_PATH] = {
0}; WCHAR strExeName[MAX_PATH] = {
0}; WCHAR* strLastSlash = NULL; GetModuleFileNameW( NULL, strExePath, MAX_PATH ); strExePath[MAX_PATH-1]=0; strLastSlash = wcsrchr( strExePath, TEXT('\\') ); if( strLastSlash ) {
// 得到EXE所在路径 StringCchCopyW( strExeName, MAX_PATH, &strLastSlash[1] ); *strLastSlash = 0; strLastSlash = wcsrchr( strExeName, TEXT('.') ); if( strLastSlash ) *strLastSlash = 0; } WCHAR strGameWidgetDll[MAX_PATH] = {
0}; #ifdef _WIN64 StringCchPrintfW( strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry64.dll", strExePath ); #else StringCchPrintfW( strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry.dll", strExePath ); #endif // if ( !(GetFileAttributesW(strGameWidgetDll) != 0xFFFFFFFF) ) {
// StringCchPrintfW( strGameWidgetDll, MAX_PATH, L"%s\\GameWidget.dll", strExePath ); // }; /* if ( !(GetFileAttributesW(strGameWidgetDll) != 0xFFFFFFFF) ) { // 如果程序运行路径中不存在则换个路径再试 StringCchPrintfW( strGameWidgetDll, MAX_PATH, L"%s\\..\\..\\..\\..\\bin\\GameWidget.dll", strExePath ); } if ( !(GetFileAttributesW(strGameWidgetDll) != 0xFFFFFFFF) ) { // 如果程序运行路径中不存在则换个路径再试 StringCchPrintfW( strGameWidgetDll, MAX_PATH, L"E:\\Worke\\Ez\\IGP\\demo&prototype\\allsnap\\bin\\GameWidget.dll" ); } */ CloseIGW(); if ( GetFileAttributesW(strGameWidgetDll) != 0xFFFFFFFF ) {
// 找到组件则加载 g_hInstIGWDll = LoadModuleEx(strGameWidgetDll); if (g_hInstIGWDll) {
igwInitialize = (LPigwInitialize)GetProcAddress( g_hInstIGWDll, "igwInitialize" ); igwGetModule = (LPigwGetModule)GetProcAddress( g_hInstIGWDll, "igwGetModule" ); igwTerminal = (LPigwTerminal)GetProcAddress( g_hInstIGWDll, "igwTerminal" ); if ( igwInitialize && igwGetModule && igwTerminal) {
// 加载成功 // 调试方便,可从配置中读取 int appId = 88; FILE* f = fopen("./appid.txt", "r"); if (f != NULL) {
char value[1024] = {
0}; if (fgets(value, 1024, f)) {
appId = atoi(value); }; fclose(f); }; // 注意AppInfo类型所有字段必须填 AppInfo tmpAppInfo = {
sizeof(AppInfo), // 结构体大小,方便扩展 appId, // 接入应用ID,从开发者网站中申请 L"龙潭虎穴OnLine", // 应用名称 L"0.1.2.0", // 应用客户端当前版本号 SDOA_RENDERTYPE_D3D9, // 客户端支持的图形引擎类型,这里同时支持d3d9和d3d8 1, // 可同时在一台机器上游戏的最大人数(通常为1,例如:KOF应该是2) 1, // 游戏区ID,不可用时传入-1 1 // 游戏组ID,不可用时传入-1 }; if (igwInitialize(SDOA_SDK_VERSION, &tmpAppInfo) == SDOA_OK) {
// 初始化组件成功 // 获取组件接口 igwGetModule(__uuidof(ISDOADx9), (void**)&g_SDOADx9); igwGetModule(__uuidof(ISDOAApp3), (void**)&g_SDOAApp); igwGetModule(__uuidof(ISDOAAppUtils), (void**)&g_SDOAAppUtils); igwGetModule(__uuidof(ISDOAClientService), (void**)&g_SDOAClientService); igwGetModule(__uuidof(ISDOLLogin4), (void**)&g_SDOLogin); if ( (!g_SDOADx9) || (!g_SDOAApp) || (!g_SDOAAppUtils) || (!g_SDOAClientService)) CloseIGW(); } else // 初始化失败清除环境 CloseIGW(); } else // 加载DLL失败清除环境 CloseIGW(); } } } #define IDC_BUTTON_SHOWLOGINDIALOG 1 #define IDC_BUTTON_DOLOGIN 2 #define IDC_BUTTON_LOGOUT 3 #define IDC_BUTTON_CODEPAY 4 #define IDC_BUTTON_CODEPAY2 5 #define IDC_STATIC_LOG 100 #define LOG_LINE_COUNT 5 #define LOG_LINE_HEIGHT 20 void Trace(LPCWSTR format, ...); BOOL onSDOLogin = false; BOOL isSDOLogin = false; // 注意一定要是BOOL类型,不能为bool否则可能会导致问题 LoginResult loginResult; /* 显示SDOLogin登录窗口 */ void Logout() {
if (g_SDOLogin) {
int code = g_SDOLogin->Logout(); Trace(L"ISDOLLoginEx::Logout result[%d]\n", code); } } void DoLogin() {
if(g_SDOLogin) {
int code = g_SDOLogin->DoLogin(); Trace(L"ISDOLLoginEx::DoLogin result[%d]\n", code); } } void OpenWindow(LPCWSTR pwcsWinType, LPCWSTR pwcsWinName, LPCWSTR pwcsSrc, int nLeft, int nTop, int nWidth, int nHeight, LPCWSTR pwcsMode) {
if (g_SDOLogin) {
int code = g_SDOLogin->OpenWindow(pwcsWinType,pwcsWinName,pwcsSrc,nLeft,nTop,nWidth,nHeight,pwcsMode); Trace(L"ISDOLLoginEx::OpenWindow result[%d]\n", code); } } /* 登录回调函数 */ int CALLBACK OnLogin(int nErrorCode, const SDOLLoginResult* pLoginResult, int nUserData, int nReserved) {
SDOLLoginResult loginResult; if (SDOL_ERRORCODE_OK == nErrorCode) {
Trace(L"Login success. SessionId[%s] Sndaid[%s] IdentityState[%s] Appendix[%s]\n", pLoginResult->SessionId, pLoginResult->Sndaid, pLoginResult->IdentityState, pLoginResult->Appendix); loginResult = *pLoginResult; ShowWindow( DXUTGetHWND(), SW_SHOW ); SetForegroundWindow(DXUTGetHWND()); } else if (SDOL_ERRORCODE_LOGINCANCEL == nErrorCode) {
Logout(); CloseIGW(); ExitProcess(0); } return SDOL_LOGINRESULT_CLOSE; //关闭登录窗口 } BOOL CALLBACK OnLogin2(int nErrorCode, const LoginResult* pLoginResult, int nUserData, int nReserved) {
// 注意该回调返回true则关闭登录对话框,否则登录对话框仍然显示 isSDOLogin = (SDOA_ERRORCODE_OK == nErrorCode); if (isSDOLogin) {
loginResult = *pLoginResult; // 登录成功后,把用户使用的游戏角色信息传入IGW if (g_SDOAApp) {
RoleInfo tmpRoleInfo = {
sizeof(RoleInfo), L"美貌仙子", 0 } ; g_SDOAApp->SetRoleInfo(&tmpRoleInfo); // 设置角色信息,可多次调用,只要用户切换了角色就调用通知IGW } onSDOLogin = false; } if (SDOA_ERRORCODE_CANCEL == nErrorCode) {
onSDOLogin = false; // ExitProcess(0); } if (SDOA_ERRORCODE_SHOWMESSAGE == nErrorCode) {
// 登录错误消息处理 if (nReserved != 0) {
LoginMessage* pCurLoginMsg = (LoginMessage*)nReserved; if (pCurLoginMsg->dwSize >= sizeof(LoginMessage)) {
// 兼容性处理 // 修改错误提示对话框标题 //SysReAllocString(pCurLoginMsg->pbstrTitle, L"[测试游戏错误提示]"); // 此时返回FALSE则使用默认提示 // 此时返回TRUE则使用自定义的提示 //isSDOLogin = TRUE; //::MessageBox(0, *pCurLoginMsg->pbstrContent, *pCurLoginMsg->pbstrTitle, MB_OK); } } onSDOLogin = false; } return isSDOLogin; // 常规逻辑,登录成功则关闭登录对话框 } /* 显示SDOLogin登录窗口 */ void ShowLoginDialog() {
//if (g_SDOLogin) //{
// HWND hMainWin = DXUTGetHWND(); // ::SendMessage(hMainWin, WM_ACTIVATEAPP, 0, 0); // g_SDOLogin->SetOwnerWindow(hMainWin); // g_SDOLogin->ShowLoginDialog(OnLogin, 0, 0); //} onSDOLogin = true; g_SDOAApp->ShowLoginDialog(OnLogin2, 0, 0); } CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs CDXUTDialog g_LoginDialog; CDXUTDialog g_LogDialog; //-------------------------------------------------------------------------------------- // Rejects any devices that aren't acceptable by returning false //-------------------------------------------------------------------------------------- bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext ) {
// Typically want to skip backbuffer formats that don't support alpha blending IDirect3D9* pD3D = DXUTGetD3DObject(); if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) ) return false; return true; } //-------------------------------------------------------------------------------------- // Before a device is created, modify the device settings as needed //-------------------------------------------------------------------------------------- bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext ) {
// pDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; return true; } //-------------------------------------------------------------------------------------- // Create any D3DPOOL_MANAGED resources here //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) {
HRESULT hr; V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) ); if (g_SDOADx9) {
// 初始化IGW内部图形引擎 D3DPRESENT_PARAMETERS d3dpp = DXUTGetPresentParameters (); g_SDOADx9->Initialize( pd3dDevice, &d3dpp, FALSE ); } return S_OK; } //-------------------------------------------------------------------------------------- // Create any D3DPOOL_DEFAULT resources here //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) {
HRESULT hr; V_RETURN( g_DialogResourceManager.OnResetDevice() ); g_LoginDialog.SetLocation( 10, 10 ); g_LoginDialog.SetSize( 180, 180 ); RECT rect; GetClientRect(DXUTGetHWND(), &rect); g_LogDialog.SetLocation(0, rect.bottom - LOG_LINE_COUNT * LOG_LINE_HEIGHT); g_LogDialog.SetSize(rect.right, LOG_LINE_COUNT * LOG_LINE_HEIGHT); //g_LogDialog.SetBackgroundColors(D3DCOLOR_ARGB(255, 0, 0, 0)); for(int i=0; i<LOG_LINE_COUNT; i++) {
CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + i); pStatic->SetLocation(0, LOG_LINE_HEIGHT * i); pStatic->SetSize(g_LogDialog.GetWidth(), LOG_LINE_HEIGHT); } if(g_SDOADx9) {
// 通知IGW d3d设备重置成功 D3DPRESENT_PARAMETERS d3dpp = DXUTGetPresentParameters () ; g_SDOADx9->OnDeviceReset ( &d3dpp ) ; } return S_OK; } //-------------------------------------------------------------------------------------- // Handle updates to the scene //-------------------------------------------------------------------------------------- void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) {
} //-------------------------------------------------------------------------------------- // Render the scene //-------------------------------------------------------------------------------------- void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) {
HRESULT hr; // Clear the render target and the zbuffer V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) ); // Render the scene if( SUCCEEDED( pd3dDevice->BeginScene() ) ) {
g_LoginDialog.OnRender( fElapsedTime ); g_LogDialog.OnRender(fElapsedTime); /* 绘制IGW界面 */ if (g_SDOADx9) g_SDOADx9->RenderEx(); V( pd3dDevice->EndScene() ); } } //-------------------------------------------------------------------------------------- // Handle messages to the application //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ) {
if(g_SDOADx9) {
// 把消息交给IGW模块处理 LRESULT lResult; if (g_SDOADx9->OnWindowProc( hWnd, uMsg, wParam, lParam, &lResult ) == SDOA_OK ) {
*pbNoFurtherProcessing = true;// 不让自身再处理消息 return lResult; } } if ( (UINT)SDOA_WM_CLIENT_RUN == uMsg ) {
// 此刻可以开始登录 if (g_SDOAApp) {
onSDOLogin = true; g_SDOAApp->ShowLoginDialog(OnLogin2, 0, 0); SDOAWinProperty tmpWinPro; tmpWinPro.nLeft = 10; tmpWinPro.nTop = 10; if ( g_SDOAApp->GetWinProperty(L"igwUserLoginDialog", &tmpWinPro) == SDOA_OK) {
if ( g_SDOAApp->SetWinProperty(L"igwUserLoginDialog", &tmpWinPro) == SDOA_OK) {
tmpWinPro.nTop = 10; } else {
tmpWinPro.nTop = 20; } } } } if (uMsg == WM_KEYDOWN && wParam == 'F') {
DXUTToggleFullScreen(); }; if (uMsg == WM_TIMER) {
}; // Always allow dialog resource manager calls to handle global messages // so GUI state is updated correctly *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; *pbNoFurtherProcessing = g_LoginDialog.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; *pbNoFurtherProcessing = g_LogDialog.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; return 0; } //-------------------------------------------------------------------------------------- // Release resources created in the OnResetDevice callback here //-------------------------------------------------------------------------------------- void CALLBACK OnLostDevice( void* pUserContext ) {
g_DialogResourceManager.OnLostDevice(); /* 通知IGW d3d设备丢失 */ if(g_SDOADx9) g_SDOADx9->OnDeviceLost(); } //-------------------------------------------------------------------------------------- // Release resources created in the OnCreateDevice callback here //-------------------------------------------------------------------------------------- void CALLBACK OnDestroyDevice( void* pUserContext ) {
g_DialogResourceManager.OnDestroyDevice(); /* 释放IGW图形引擎 */ if (g_SDOADx9) g_SDOADx9->Finalize(); } int g_LogIndex = 0; void Trace(LPCWSTR format, ...) {
if(g_LogIndex >= LOG_LINE_COUNT) {
for(int i=0;i<LOG_LINE_COUNT - 1;i++) {
CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + i); CDXUTStatic* pStatic1 = g_LogDialog.GetStatic(IDC_STATIC_LOG + i + 1); pStatic->SetText(pStatic1->GetText()); } g_LogIndex = LOG_LINE_COUNT - 1; } CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + g_LogIndex++); if(pStatic) {
WCHAR buffer[1024] = {
0}; va_list args; va_start(args, format); ::_vsnwprintf(buffer, _countof(buffer) - 1, format, args); va_end(args); pStatic->SetText(buffer); } } void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) {
switch( nControlID ) {
case IDC_BUTTON_SHOWLOGINDIALOG: Logout(); ShowLoginDialog(); break; case IDC_BUTTON_DOLOGIN: DoLogin(); break; case IDC_BUTTON_LOGOUT: Logout(); break; case IDC_BUTTON_CODEPAY: OpenWindow(L"",L"Pay",L"http://cas.sdo.com/cas/login?service=http://qrcode.sdo.com/qrcode/index?appId=$gid$",0,0,444,490,L"center|showmodal"); // width+10,height+45 break; case IDC_BUTTON_CODEPAY2: OpenWindow(L"", L"扫码支付", L"http://cas.sdo.com/cas/login?gateway=true&service=http%3a%2f%2fqrcode.sdo.com%2fqrcode%2findex%3fappId%3d$gid$%26areaId%3d$gaid$", 0, 0, 449, 460, L"center"); // width+10,height+45 break; } } //-------------------------------------------------------------------------------------- // Initialize the app //-------------------------------------------------------------------------------------- void InitApp() {
g_LoginDialog.Init( &g_DialogResourceManager ); g_LoginDialog.SetCallback( OnGUIEvent ); g_LogDialog.Init( &g_DialogResourceManager ); g_LogDialog.SetCallback( OnGUIEvent ); int iY = 10; g_LoginDialog.AddButton(IDC_BUTTON_SHOWLOGINDIALOG, L"显示登陆框", 10, iY, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_DOLOGIN, L"登录", 10, iY += 30, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_LOGOUT, L"注销", 10, iY += 30, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_CODEPAY, L"扫码支付", 10, iY += 30, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_CODEPAY2, L"扫码支付(包含区ID)", 10, iY += 30, 80, 26); for(int i=0; i<LOG_LINE_COUNT; i++) {
g_LogDialog.AddStatic(IDC_STATIC_LOG + i, L"", 0, 0, 0, 0); } } INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
// Enable run-time memory check for debug builds. #if defined(DEBUG) | defined(_DEBUG) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif /* 加载IGW */ OpenIGW(); // Set the callback functions DXUTSetCallbackDeviceCreated( OnCreateDevice ); DXUTSetCallbackDeviceReset( OnResetDevice ); DXUTSetCallbackDeviceLost( OnLostDevice ); DXUTSetCallbackDeviceDestroyed( OnDestroyDevice ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackFrameRender( OnFrameRender ); DXUTSetCallbackFrameMove( OnFrameMove ); // TODO: Perform any application-level initialization here InitApp(); // Initialize DXUT and create the desired Win32 window and Direct3D device for the application DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen DXUTCreateWindow( L"EmptyProject" ); DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 1024, 768, IsDeviceAcceptable, ModifyDeviceSettings ); HWND hMainWin = DXUTGetHWND(); SetTimer(hMainWin, 1, 500, 0); if (igwInitialize) {
// 说明加载成功,表示下...... SetWindowTextW(hMainWin, L"EmptyProject [加载IGW组件成功]"); } // Start the render loop DXUTMainLoop(); // TODO: Perform any application-level cleanup here if (isSDOLogin && g_SDOAApp) {
// 登录成功,退出时要登出 g_SDOAApp->Logout(); } /* 释放IGW */ CloseIGW(); return DXUTGetExitCode(); }
- 这段代码是一个使用 Direct3D 9 和 DXUT 框架的简单演示程序,包含了与 IGW(一个游戏组件接口)的集成。代码展示了一个完整的 Direct3D 应用程序从初始化到渲染的过程。下面将详细解释代码中的各个部分。
1.头文件和全局变量
#include "dxstdafx.h" #include "resource.h" #include <xstring> #include "interface.h" #include "DXUTgui.h" #include "Oleauto.h" #include "comutil.h" #include <time.h> //#pragma comment(lib, "comsupp.lib") #include "SDOA4Client.h" #include "SDOADx9.h"
这些头文件引入了必要的库和声明,例如 DXUT 框架、OLE 自动化、COM 实用程序等。
2.IGW 相关全局变量
HINSTANCE g_hInstIGWDll = 0; LPigwInitialize igwInitialize = NULL; LPigwGetModule igwGetModule = NULL; LPigwTerminal igwTerminal = NULL; ISDOADx9* g_SDOADx9 = NULL; ISDOAApp3* g_SDOAApp = NULL; ISDOLLogin4* g_SDOLogin = NULL; ISDOAAppUtils* g_SDOAAppUtils = NULL; ISDOAClientService* g_SDOAClientService = NULL;
这些全局变量用于保存 IGW 的接口指针和 DLL 模块句柄。
3.函数:CloseIGW
void CloseIGW() {
if (g_SDOADx9) {
g_SDOADx9->Release(); g_SDOADx9 = NULL; } if (g_SDOAApp) {
g_SDOAApp->Release(); g_SDOAApp = NULL; } if (g_SDOAAppUtils) {
g_SDOAAppUtils->Release(); g_SDOAAppUtils = NULL; } if (g_SDOAClientService) {
g_SDOAClientService->Release(); g_SDOAClientService = NULL; } if (g_SDOLogin) {
g_SDOLogin->Release(); g_SDOLogin = NULL; } if (igwTerminal) {
igwTerminal(); igwTerminal = NULL; } if (g_hInstIGWDll) {
FreeLibrary(g_hInstIGWDll); g_hInstIGWDll = 0; } igwInitialize = NULL; }
这个函数用于释放所有 IGW 相关的资源和接口。
4.函数:OpenIGW
void OpenIGW() {
// 获取当前程序路径 WCHAR strExePath[MAX_PATH] = {
0}; WCHAR strExeName[MAX_PATH] = {
0}; WCHAR* strLastSlash = NULL; GetModuleFileNameW(NULL, strExePath, MAX_PATH); strExePath[MAX_PATH-1] = 0; strLastSlash = wcsrchr(strExePath, TEXT('\\')); if (strLastSlash) {
StringCchCopyW(strExeName, MAX_PATH, &strLastSlash[1]); *strLastSlash = 0; strLastSlash = wcsrchr(strExeName, TEXT('.')); if (strLastSlash) *strLastSlash = 0; } WCHAR strGameWidgetDll[MAX_PATH] = {
0}; #ifdef _WIN64 StringCchPrintfW(strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry64.dll", strExePath); #else StringCchPrintfW(strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry.dll", strExePath); #endif CloseIGW(); if (GetFileAttributesW(strGameWidgetDll) != 0xFFFFFFFF) {
g_hInstIGWDll = LoadModuleEx(strGameWidgetDll); if (g_hInstIGWDll) {
igwInitialize = (LPigwInitialize)GetProcAddress(g_hInstIGWDll, "igwInitialize"); igwGetModule = (LPigwGetModule)GetProcAddress(g_hInstIGWDll, "igwGetModule"); igwTerminal = (LPigwTerminal)GetProcAddress(g_hInstIGWDll, "igwTerminal"); if (igwInitialize && igwGetModule && igwTerminal) {
int appId = 88; FILE* f = fopen("./appid.txt", "r"); if (f != NULL) {
char value[1024] = {
0}; if (fgets(value, 1024, f)) {
appId = atoi(value); }; fclose(f); }; AppInfo tmpAppInfo = {
sizeof(AppInfo), appId, L"龙潭虎穴OnLine", L"0.1.2.0", SDOA_RENDERTYPE_D3D9, 1, 1, 1 }; if (igwInitialize(SDOA_SDK_VERSION, &tmpAppInfo) == SDOA_OK) {
igwGetModule(__uuidof(ISDOADx9), (void**)&g_SDOADx9); igwGetModule(__uuidof(ISDOAApp3), (void**)&g_SDOAApp); igwGetModule(__uuidof(ISDOAAppUtils), (void**)&g_SDOAAppUtils); igwGetModule(__uuidof(ISDOAClientService), (void**)&g_SDOAClientService); igwGetModule(__uuidof(ISDOLLogin4), (void**)&g_SDOLogin); if ((!g_SDOADx9) || (!g_SDOAApp) || (!g_SDOAAppUtils) || (!g_SDOAClientService)) CloseIGW(); } else {
CloseIGW(); } } else {
CloseIGW(); } } } }
这个函数用于加载 IGW 组件 DLL,并初始化必要的接口。
5.UI 控件和日志处理
#define IDC_BUTTON_SHOWLOGINDIALOG 1 #define IDC_BUTTON_DOLOGIN 2 #define IDC_BUTTON_LOGOUT 3 #define IDC_BUTTON_CODEPAY 4 #define IDC_BUTTON_CODEPAY2 5 #define IDC_STATIC_LOG 100 #define LOG_LINE_COUNT 5 #define LOG_LINE_HEIGHT 20 void Trace(LPCWSTR format, ...);
定义了一些 UI 控件的 ID 和日志的相关参数。
6.登录和登出相关函数
void Logout() {
if (g_SDOLogin) {
int code = g_SDOLogin->Logout(); Trace(L"ISDOLLoginEx::Logout result[%d]\n", code); } } void DoLogin() {
if (g_SDOLogin) {
int code = g_SDOLogin->DoLogin(); Trace(L"ISDOLLoginEx::DoLogin result[%d]\n", code); } } void ShowLoginDialog() {
onSDOLogin = true; g_SDOAApp->ShowLoginDialog(OnLogin2, 0, 0); }
这些函数用于处理登录和登出的操作,以及显示登录对话框。
7.登录回调函数
int CALLBACK OnLogin(int nErrorCode, const SDOLLoginResult* pLoginResult, int nUserData, int nReserved) {
SDOLLoginResult loginResult; if (SDOL_ERRORCODE_OK == nErrorCode) {
Trace(L"Login success. SessionId[%s] Sndaid[%s] IdentityState[%s] Appendix[%s]\n", pLoginResult->SessionId, pLoginResult->Sndaid, pLoginResult->IdentityState, pLoginResult->Appendix); loginResult = *pLoginResult; ShowWindow(DXUTGetHWND(), SW_SHOW); SetForegroundWindow(DXUTGetHWND()); } else if (SDOL_ERRORCODE_LOGINCANCEL == nErrorCode) {
Logout(); CloseIGW(); ExitProcess(0); } return SDOL_LOGINRESULT_CLOSE; // 关闭登录窗口 } BOOL CALLBACK OnLogin2(int nErrorCode, const LoginResult* pLoginResult, int nUserData, int nReserved) {
isSDOLogin = (SDOA_ERRORCODE_OK == nErrorCode); if (isSDOLogin) {
loginResult = *pLoginResult; if (g_SDOAApp) {
RoleInfo tmpRoleInfo = {
sizeof(RoleInfo), L"美貌仙子", 0 }; g_SDOAApp->SetRoleInfo(&tmpRoleInfo); } onSDOLogin = false; } if (SDOA_ERRORCODE_CANCEL == nErrorCode) {
onSDOLogin = false; } if (SDOA_ERRORCODE_SHOWMESSAGE == nErrorCode) {
if (nReserved != 0) {
LoginMessage* pCurLoginMsg = (LoginMessage*)nReserved; if (pCurLoginMsg->dwSize >= sizeof(LoginMessage)) {
// 错误消息处理 } } onSDOLogin = false; } return isSDOLogin; // 登录成功则关闭对话框 }
这些函数是登录操作的回调函数,用于处理登录成功或失败的情况。
8.DXUT 相关回调函数
bool CALLBACK IsDeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext) {
IDirect3D9* pD3D = DXUTGetD3DObject(); if (FAILED(pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat))) return false; return true; } bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext) {
return true; } HRESULT CALLBACK OnCreateDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext) {
HRESULT hr; V_RETURN(g_DialogResourceManager.OnCreateDevice(pd3dDevice)); if (g_SDOADx9) {
D3DPRESENT_PARAMETERS d3dpp = DXUTGetPresentParameters(); g_SDOADx9->Initialize(pd3dDevice, &d3dpp, FALSE); } return S_OK; } HRESULT CALLBACK OnResetDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext) {
HRESULT hr; V_RETURN(g_DialogResourceManager.OnResetDevice()); g_LoginDialog.SetLocation(10, 10); g_LoginDialog.SetSize(180, 180); RECT rect; GetClientRect(DXUTGetHWND(), &rect); g_LogDialog.SetLocation(0, rect.bottom - LOG_LINE_COUNT * LOG_LINE_HEIGHT); g_LogDialog.SetSize(rect.right, LOG_LINE_COUNT * LOG_LINE_HEIGHT); for (int i = 0; i < LOG_LINE_COUNT; i++) {
CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + i); pStatic->SetLocation(0, LOG_LINE_HEIGHT * i); pStatic->SetSize(g_LogDialog.GetWidth(), LOG_LINE_HEIGHT); } if (g_SDOADx9) {
D3DPRESENT_PARAMETERS d3dpp = DXUTGetPresentParameters(); g_SDOADx9->OnDeviceReset(&d3dpp); } return S_OK; } void CALLBACK OnFrameMove(IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext) {
} void CALLBACK OnFrameRender(IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext) {
HRESULT hr; V(pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0)); if (SUCCEEDED(pd3dDevice->BeginScene())) {
g_LoginDialog.OnRender(fElapsedTime); g_LogDialog.OnRender(fElapsedTime); if (g_SDOADx9) g_SDOADx9->RenderEx(); V(pd3dDevice->EndScene()); } } LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext) {
if (g_SDOADx9) {
LRESULT lResult; if (g_SDOADx9->OnWindowProc(hWnd, uMsg, wParam, lParam, &lResult) == SDOA_OK) {
*pbNoFurtherProcessing = true; return lResult; } } if ((UINT)SDOA_WM_CLIENT_RUN == uMsg) {
if (g_SDOAApp) {
onSDOLogin = true; g_SDOAApp->ShowLoginDialog(OnLogin2, 0, 0); SDOAWinProperty tmpWinPro; tmpWinPro.nLeft = 10; tmpWinPro.nTop = 10; if (g_SDOAApp->GetWinProperty(L"igwUserLoginDialog", &tmpWinPro) == SDOA_OK) {
if (g_SDOAApp->SetWinProperty(L"igwUserLoginDialog", &tmpWinPro) == SDOA_OK) {
tmpWinPro.nTop = 10; } else {
tmpWinPro.nTop = 20; } } } } if (uMsg == WM_KEYDOWN && wParam == 'F') {
DXUTToggleFullScreen(); } if (uMsg == WM_TIMER) {
} *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; *pbNoFurtherProcessing = g_LoginDialog.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; *pbNoFurtherProcessing = g_LogDialog.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; return 0; } void CALLBACK OnLostDevice(void* pUserContext) {
g_DialogResourceManager.OnLostDevice(); if (g_SDOADx9) g_SDOADx9->OnDeviceLost(); } void CALLBACK OnDestroyDevice(void* pUserContext) {
g_DialogResourceManager.OnDestroyDevice(); if (g_SDOADx9) g_SDOADx9->Finalize(); }
这些函数是 DXUT 框架的回调函数,用于处理设备的创建、重置、丢失和销毁等事件,以及渲染和消息处理。
9.日志和 UI 控件初始化
void Trace(LPCWSTR format, ...) {
if (g_LogIndex >= LOG_LINE_COUNT) {
for (int i = 0; i < LOG_LINE_COUNT - 1; i++) {
CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + i); CDXUTStatic* pStatic1 = g_LogDialog.GetStatic(IDC_STATIC_LOG + i + 1); pStatic->SetText(pStatic1->GetText()); } g_LogIndex = LOG_LINE_COUNT - 1; } CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + g_LogIndex++); if (pStatic) {
WCHAR buffer[1024] = {
0}; va_list args; va_start(args, format); ::_vsnwprintf(buffer, _countof(buffer) - 1, format, args); va_end(args); pStatic->SetText(buffer); } } void CALLBACK OnGUIEvent(UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext) {
switch (nControlID) {
case IDC_BUTTON_SHOWLOGINDIALOG: Logout(); ShowLoginDialog(); break; case IDC_BUTTON_DOLOGIN: DoLogin(); break; case IDC_BUTTON_LOGOUT: Logout(); break; case IDC_BUTTON_CODEPAY: OpenWindow(L"", L"Pay", L"http://cas.sdo.com/cas/login?service=http://qrcode.sdo.com/qrcode/index?appId=$gid$", 0, 0, 444, 490, L"center|showmodal"); break; case IDC_BUTTON_CODEPAY2: OpenWindow(L"", L"扫码支付", L"http://cas.sdo.com/cas/login?gateway=true&service=http%3a%2f%2fqrcode.sdo.com%2fqrcode%2findex%3fappId%3d$gid$%26areaId%3d$gaid$", 0, 0, 449, 460, L"center"); break; } } void InitApp() {
g_LoginDialog.Init(&g_DialogResourceManager); g_LoginDialog.SetCallback(OnGUIEvent); g_LogDialog.Init(&g_DialogResourceManager); g_LogDialog.SetCallback(OnGUIEvent); int iY = 10; g_LoginDialog.AddButton(IDC_BUTTON_SHOWLOGINDIALOG, L"显示登陆框", 10, iY, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_DOLOGIN, L"登录", 10, iY += 30, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_LOGOUT, L"注销", 10, iY += 30, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_CODEPAY, L"扫码支付", 10, iY += 30, 80, 26); g_LoginDialog.AddButton(IDC_BUTTON_CODEPAY2, L"扫码支付(包含区ID)", 10, iY += 30, 80, 26); for (int i = 0; i < LOG_LINE_COUNT; i++) {
g_LogDialog.AddStatic(IDC_STATIC_LOG + i, L"", 0, 0, 0, 0); } }
这些函数用于初始化 UI 控件和处理 GUI 事件。
10.程序入口点
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
#if defined(DEBUG) | defined(_DEBUG) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif OpenIGW(); DXUTSetCallbackDeviceCreated(OnCreateDevice); DXUTSetCallbackDeviceReset(OnResetDevice); DXUTSetCallbackDeviceLost(OnLostDevice); DXUTSetCallbackDeviceDestroyed(OnDestroyDevice); DXUTSetCallbackMsgProc(MsgProc); DXUTSetCallbackFrameRender(OnFrameRender); DXUTSetCallbackFrameMove(OnFrameMove); InitApp(); DXUTInit(true, true, true); DXUTSetCursorSettings(true, true); DXUTCreateWindow(L"EmptyProject"); DXUTCreateDevice(D3DADAPTER_DEFAULT, true, 1024, 768, IsDeviceAcceptable, ModifyDeviceSettings); HWND hMainWin = DXUTGetHWND(); SetTimer(hMainWin, 1, 500, 0); if (igwInitialize) {
SetWindowTextW(hMainWin, L"EmptyProject [加载IGW组件成功]"); } DXUTMainLoop(); if (isSDOLogin && g_SDOAApp) {
g_SDOAApp->Logout(); } CloseIGW(); return DXUTGetExitCode(); }
这是程序的入口点,初始化 DXUT 和 IGW,并进入渲染循环。
11.总结
这段代码展示了一个完整的 Direct3D 9 和 IGW 集成的应用程序框架,包括设备管理、消息处理、UI 控件和登录操作的完整流程。
3、Direct3D 9 相关的部分,包括设备创建、重置、丢失和销毁的完整流程。
1.Direct3D 9 设备创建和管理
在 Direct3D 应用程序中,设备(Device)是一个核心对象,负责与 GPU 进行交互和渲染操作。下面是 D3D9 设备创建和管理的详细流程。
1. 初始化 Direct3D 和创建设备
设备创建的回调函数:
- 在 WinMain 函数中,设置了设备创建的回调函数:
DXUTSetCallbackDeviceCreated(OnCreateDevice); DXUTSetCallbackDeviceReset(OnResetDevice); DXUTSetCallbackDeviceLost(OnLostDevice); DXUTSetCallbackDeviceDestroyed(OnDestroyDevice);
- 这些回调函数会在设备创建、重置、丢失和销毁时被调用。
设备是否可接受的回调函数:
bool CALLBACK IsDeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext) {
// Typically want to skip backbuffer formats that don't support alpha blending IDirect3D9* pD3D = DXUTGetD3DObject(); if (FAILED(pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat))) return false; return true; }
- 这个函数用于判断设备是否可接受。通常会检查后备缓冲区(BackBuffer)的格式是否支持 Alpha 混合。
修改设备设置的回调函数:
bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext) {
// 可在此处修改设备设置,例如禁用垂直同步 // pDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; return true; }
- 这个函数在设备创建之前被调用,可以在此修改设备设置,例如禁用垂直同步等。
设备创建和重置的回调函数:
HRESULT CALLBACK OnCreateDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext) {
HRESULT hr; V_RETURN(g_DialogResourceManager.OnCreateDevice(pd3dDevice)); if (g_SDOADx9) {
D3DPRESENT_PARAMETERS d3dpp = DXUTGetPresentParameters(); g_SDOADx9->Initialize(pd3dDevice, &d3dpp, FALSE); } return S_OK; }
- 这个函数在设备创建时被调用。这里主要做了以下工作:
- 调用 g_DialogResourceManager.OnCreateDevice 来初始化对话框资源管理器。
- 如果 g_SDOADx9 非空,则初始化 IGW 内部的图形引擎。
设备创建和重置的回调函数:
HRESULT CALLBACK OnResetDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext) {
HRESULT hr; V_RETURN(g_DialogResourceManager.OnResetDevice()); g_LoginDialog.SetLocation(10, 10); g_LoginDialog.SetSize(180, 180); RECT rect; GetClientRect(DXUTGetHWND(), &rect); g_LogDialog.SetLocation(0, rect.bottom - LOG_LINE_COUNT * LOG_LINE_HEIGHT); g_LogDialog.SetSize(rect.right, LOG_LINE_COUNT * LOG_LINE_HEIGHT); for (int i = 0; i < LOG_LINE_COUNT; i++) {
CDXUTStatic* pStatic = g_LogDialog.GetStatic(IDC_STATIC_LOG + i); pStatic->SetLocation(0, LOG_LINE_HEIGHT * i); pStatic->SetSize(g_LogDialog.GetWidth(), LOG_LINE_HEIGHT); } if (g_SDOADx9) {
D3DPRESENT_PARAMETERS d3dpp = DXUTGetPresentParameters(); g_SDOADx9->OnDeviceReset(&d3dpp); } return S_OK; }
- 这个函数在设备重置时被调用。主要做了以下工作:
- 调用 g_DialogResourceManager.OnResetDevice 来重置对话框资源管理器。
- 0 设置登录对话框和日志对话框的位置和大小。
- 如果 g_SDOADx9 非空,则通知 IGW 图形引擎设备已重置。
处理设备丢失回调函数:
void CALLBACK OnLostDevice(void* pUserContext) {
g_DialogResourceManager.OnLostDevice(); if (g_SDOADx9) g_SDOADx9->OnDeviceLost(); }
- 这个函数在设备丢失时被调用。主要做了以下工作:
- 调用 g_DialogResourceManager.OnLostDevice 来处理对话框资源管理器中的设备丢失。
- 如果 g_SDOADx9 非空,则通知 IGW 图形引擎设备已丢失。
释放设备资源回调函数:
void CALLBACK OnDestroyDevice(void* pUserContext) {
g_DialogResourceManager.OnDestroyDevice(); if (g_SDOADx9) g_SDOADx9->Finalize(); }
- 这个函数在设备销毁时被调用。主要做了以下工作:
- 调用 g_DialogResourceManager.OnDestroyDevice 来释放对话框资源管理器中的资源。
- 如果 g_SDOADx9 非空,则调用 g_SDOADx9->Finalize 来释放 IGW 图形引擎的资源。
2. 渲染流程
帧移动更新回调函数:
void CALLBACK OnFrameMove(IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext) {
// 可在此处更新场景逻辑 }
- 这个函数在每帧移动时被调用,可用于更新场景逻辑。
渲染场景的回调函数帧渲染:
void CALLBACK OnFrameRender(IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext) {
HRESULT hr; V(pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0)); if (SUCCEEDED(pd3dDevice->BeginScene())) {
g_LoginDialog.OnRender(fElapsedTime); g_LogDialog.OnRender(fElapsedTime); if (g_SDOADx9) g_SDOADx9->RenderEx(); V(pd3dDevice->EndScene()); } }
- 这个函数在每帧渲染时被调用。主要做了以下工作:
- 清除渲染目标和 Z 缓冲区。
- 开始渲染场景。
- 渲染登录对话框和日志对话框。
- 如果 g_SDOADx9 非空,则调用 g_SDOADx9->RenderEx 渲染 IGW 图形界面。
- 结束渲染场景。
3.消息处理
LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext) {
if (g_SDOADx9) {
LRESULT lResult; if (g_SDOADx9->OnWindowProc(hWnd, uMsg, wParam, lParam, &lResult) == SDOA_OK) {
*pbNoFurtherProcessing = true; return lResult; } } if ((UINT)SDOA_WM_CLIENT_RUN == uMsg) {
if (g_SDOAApp) {
onSDOLogin = true; g_SDOAApp->ShowLoginDialog(OnLogin2, 0, 0); SDOAWinProperty tmpWinPro; tmpWinPro.nLeft = 10; tmpWinPro.nTop = 10; if (g_SDOAApp->GetWinProperty(L"igwUserLoginDialog", &tmpWinPro) == SDOA_OK) {
if (g_SDOAApp->SetWinProperty(L"igwUserLoginDialog", &tmpWinPro) == SDOA_OK) {
tmpWinPro.nTop = 10; } else {
tmpWinPro.nTop = 20; } } } } if (uMsg == WM_KEYDOWN && wParam == 'F') {
DXUTToggleFullScreen(); } if (uMsg == WM_TIMER) {
} *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; *pbNoFurtherProcessing = g_LoginDialog.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; *pbNoFurtherProcessing = g_LogDialog.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; return 0; }
- 这个函数用于处理窗口消息。主要做了以下工作:
- 如果 g_SDOADx9 非空,则将消息传递给 IGW 模块处理。
- 处理自定义的 SDOA_WM_CLIENT_RUN 消息,显示登录对话框。
- 处理按键事件(例如切换全屏)。
- 让对话框资源管理器和各个对话框处理消息。
4. 主程序入口点
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
#if defined(DEBUG) | defined(_DEBUG) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif OpenIGW(); DXUTSetCallbackDeviceCreated(OnCreateDevice); DXUTSetCallbackDeviceReset(OnResetDevice); DXUTSetCallbackDeviceLost(OnLostDevice); DXUTSetCallbackDeviceDestroyed(OnDestroyDevice); DXUTSetCallbackMsgProc(MsgProc); DXUTSetCallbackFrameRender(OnFrameRender); DXUTSetCallbackFrameMove(OnFrameMove); InitApp(); DXUTInit(true, true, true); DXUTSetCursorSettings(true, true); DXUTCreateWindow(L"EmptyProject"); DXUTCreateDevice(D3DADAPTER_DEFAULT, true, 1024, 768, IsDeviceAcceptable, ModifyDeviceSettings); HWND hMainWin = DXUTGetHWND(); SetTimer(hMainWin, 1, 500, 0); if (igwInitialize) {
SetWindowTextW(hMainWin, L"EmptyProject [加载IGW组件成功]"); } DXUTMainLoop(); if (isSDOLogin && g_SDOAApp) {
g_SDOAApp->Logout(); } CloseIGW(); return DXUTGetExitCode(); }
- 这个函数是程序的入口点。主要做了以下工作:
- 初始化内存调试标志(在调试模式下)。
- 调用 OpenIGW 加载 IGW 组件。
- 设置 DXUT 的各种回调函数。
- 初始化应用程序的 UI 控件。
- 初始化 DXUT 并创建窗口和 Direct3D 设备。
- 设置定时器。
- 如果 IGW 初始化成功,设置窗口标题。
- 进入 DXUT 的主循环。
- 如果登录成功,退出时登出。
- 释放 IGW 组件。
- 通过这些步骤,程序完成了 Direct3D 设备的创建、管理和渲染流程,以及与 IGW 组件的集成。
这段代码展示了如何使用 Direct3D 9 和 DXUT 框架来创建一个基本的图形应用程序,并集成了一个名为 IGW 的组件进行登录和支付操作。它涵盖了设备管理、窗口消息处理、资源创建和释放等方面的内容。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112717.html