文档章节

初始化Direct3D(4)

rise-worlds
 rise-worlds
发布于 2016/06/20 13:39
字数 1618
阅读 2
收藏 0

1.5初始化Direct3D实例

在本例程中,初始化了一个Direct3D应用程序并用黑色填充显示窗口(如图1.7)。

图1.7

所有的应用程序都包含了d3dUtility.h和d3dUtility.cpp这两个文件,它们所包含的函数实现了所有Direct3D应用程序都要去做的一些常见的功能。例如:创建一个窗口、初始化Direct3D、进入程序的消息循环等。

1.5.1d3dUtility.h/cpp

让我们先熟悉一下d3dUtility.h/cpp所提供的函数。d3dUtility.h如下:

#include <d3dx9.h>
    template<typename T>
void safe_release(T obj)
    {
if(obj == NULL)
return;
        obj->Release();
        obj = NULL;
    }
    template<typename T>
void safe_delete(T obj)
    {
if(obj == NULL)
return;
        delete obj;
        obj = NULL;
    }
///////////////////////////////////////////////////////////////////////////////////
    typedef bool (*DISPLAY_FUNC_PTR)(float timeDelta);
bool init_d3d(HINSTANCE instance,            // application instance
int width, int height,        // backbuffer dimensions
bool is_window,                // true - windowed mode, false - full screen mode.
              D3DDEVTYPE device_type,        // HAL or REF
                  IDirect3DDevice9** device);    // the create device
int enter_msg_loop(DISPLAY_FUNC_PTR display);
    LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

init_d3d——初始化一个应用程序主窗口并进行Direct3D的初始化。如果成功,则输出IDirect3DDevice9接口指针。从它的参数我们可以发现,我们能够设置窗口的大小和以窗口模式运行还是全屏模式运行。要知道它实现的细节,请看示例代码。

//-----------------------------------------------------------------------
    // Initialize windows and direct 3D.
    //-----------------------------------------------------------------------
bool init_d3d(HINSTANCE instance,            // application instance
int width, int height,        // backbuffer dimensions
bool is_window,                // true - windowed mode, false - full screen mode.
              D3DDEVTYPE device_type,        // HAL or REF
                  IDirect3DDevice9** device)    // the create device
{
const char* classname = "Direct3D9App";
        WNDCLASS wc;
        wc.style         = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   = wnd_proc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = instance;
        wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName  = NULL;
        wc.lpszClassName = classname;
if(! RegisterClass(&wc))
        {
            MessageBox(NULL, "RegisterClass() - failed.", NULL, MB_OK);
return false;
        }
        HWND hwnd = CreateWindow(classname, "Direct3D9App", WS_EX_TOPMOST,
                                 0, 0, width, height, NULL, NULL, instance, NULL);
if(hwnd == NULL)
        {
            MessageBox(NULL, "CreateWindow() - failed.", NULL, MB_OK);
return false;
        }
        ShowWindow(hwnd, SW_SHOW);
        UpdateWindow(hwnd);
// initialize D3D
        // step 1: Create the IDirect3D9 object.
        IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d9 == NULL)
        {
            MessageBox(NULL, "Direct3DCreate9() - failed.", NULL, MB_OK);
return false;
        }
// step 2: check for hardware vertex presentation.
        D3DCAPS9 caps;   
        d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, device_type, &caps);
int vp = 0;
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
            vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
            vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
// step 3: fill out the D3DPRESENT_PARAMETERS structure.
        D3DPRESENT_PARAMETERS d3dpp;
        d3dpp.BackBufferWidth                = width;
        d3dpp.BackBufferHeight                = height;
        d3dpp.BackBufferFormat                = D3DFMT_A8R8G8B8;
        d3dpp.BackBufferCount                = 1;
        d3dpp.MultiSampleType                = D3DMULTISAMPLE_NONE;
        d3dpp.MultiSampleQuality            = 0;
        d3dpp.SwapEffect                    = D3DSWAPEFFECT_DISCARD;
        d3dpp.hDeviceWindow                    = hwnd;
        d3dpp.Windowed                        = is_window;
        d3dpp.EnableAutoDepthStencil        = true;
        d3dpp.AutoDepthStencilFormat        = D3DFMT_D24S8;
        d3dpp.Flags                            = 0;
        d3dpp.FullScreen_RefreshRateInHz    = D3DPRESENT_RATE_DEFAULT;
        d3dpp.PresentationInterval            = D3DPRESENT_INTERVAL_IMMEDIATE;
// step 4: create the device.
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, device_type, hwnd, vp, &d3dpp, device)))
        {
// try again using a 16-bit depth buffer
            d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, device_type, hwnd, vp, &d3dpp, device)))
            {
                d3d9->Release();    // done with d3d9 object
            MessageBox(NULL, "CreateDevice() - failed.", NULL, MB_OK);
return false;
            }
        }
        d3d9->Release();        // done with d3d9 object
return true;
    }

enter_msg_loop——这个函数封装了应用程序的消息循环。它需要输入一个显示函数的函数指针,显示函数为程序中绘制图形的代码块,这样做是为了使显示函数能够在空闲的时候被调用并显示场景,它的实现如下:

//-----------------------------------------------------------------------
    // Enter windows message loop and render game frames if there is no message
    // comes from thread message queue.
    //-----------------------------------------------------------------------
int enter_msg_loop(DISPLAY_FUNC_PTR display)
    {
        MSG msg;
        ZeroMemory(&msg, sizeof(MSG));
// The timeGetTime function retrieves the system time, in milliseconds.
        // The system time is the time elapsed since Windows was started.   
static float last_time = (float) timeGetTime();
while(msg.message != WM_QUIT)
        {
// The PeekMessage function dispatches incoming sent messages, checks the thread message queue for a
            // posted message, and retrieves the message (if any exist).
            //
            // If a message is available, the return value is nonzero.
            // If no messages are available, the return value is zero.
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
else
            {
float curr_time  = (float) timeGetTime();
float time_delta = (curr_time - last_time) * 0.001f;
                display(time_delta);
                last_time = curr_time;
            }
        }
return (int) msg.wParam;
    }

与“time”有关的代码用于计算每次调用显示函数的时间间隔,即是每帧的时间。

safe_release——这个模版函数能方便的释放COM接口并将它们的值设为NULL

safe_delete——这个模版函数能方便的删除一个对象并将指向其的指针设为NULL

wnd_proc——应用程序主窗口的回调函数

1.5.2 实例框架

通过实例框架,我们形成了一种通用的方法去构造示例程序。每一个例程都含有三个函数的实现,当然这不包括回调函数和WinMain主函数。这三个函数用特定的代码实现特定的功能。这三个函数是:

bool setup()——在这个函数里,我们将准备一切该程序需要用到的东西,包括资源的分配,检查设备能力,设置应用程序的状态

void clearup()——这个函数将释放Setup()中分配的资源,如分配的内存。

bool display(float time_delta)——这个函数包含所有与我们绘图和显示有关的代码。参数timeDelta为每一帧的间隔时间,用来控制每秒的帧数。

这个示例程序将创建并初始化一个Direct3D应用程序,并用黑色填充屏幕。注意,我们使用了通用函数简化了初始化过程。

/*********************************************************************************
    PURPOISE:
        Demonstrates how to initialize Direct3D, how to use framework functions,
        and how to clear the screen to black.    
    *********************************************************************************/
    #include "D3DUtility.h"
    IDirect3DDevice9* g_device = NULL;
bool setup()
    {
// nothing to setup in this sample
return true;
    }
void cleanup()
    {
// nothing to cleanup in this sample
}
bool display(float timeDelta)
    {
// Only use Device methods if we have a valid device.
if(g_device == NULL)
return false;
// Instruct the device to set each pixel on the back buffer black - D3DCLEAR_TARGET: 0x00000000 (black);
        // and to set each pixel on the depth buffer to a value of 1.0 - D3DCLEAR_ZBUFFER: 1.0f.
    g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
// swap the back and front buffers
    g_device->Present(NULL, NULL, NULL, NULL);
return true;
    }
    LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
switch(msg)
        {
case WM_DESTROY:
            PostQuitMessage(0);
break;
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
                DestroyWindow(hwnd);
break;
        }
return DefWindowProc(hwnd, msg, wParam, lParam);
    }
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
    {
if(! init_d3d(inst, 640, 480, true, D3DDEVTYPE_HAL, &g_device))
        {
            MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
return 0;
        }
if(! setup())
        {
            MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
return 0;
        }
        enter_msg_loop(display);
        cleanup();
        g_device->Release();
return 0;
    }

Display方法调用了IDirect3DDevice::Clear方法,分别用黑色和1.0填充后备表面和深度/模版缓冲。如果应用程序不停止的话,我们会一直执行这个操作。IDirect3DDevice::Clear声明如下:

HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil );

Count——pRects 组中的矩形的个数

pRects——将要清除的屏幕矩形的数组,这使我们可以清除屏幕的某一部分

Flags——指定在哪些表面上执行清除表面的操作

         D3DCLEAR_TARGET——目的表面,通常为后备表面

         D3DCLEAR_ZBUFFER——深度缓冲

         D3DCLEAR_STENCIL——模版缓冲

Color——使用什么颜色填充清除的表面

Z——设置深度缓冲的值

Stencil——设置模版缓冲的值

屏幕被填充后,要调用IDirecte3DDevice9::Present方法进行后备表面的交换。

Windows 回调函数为一组事件集,即,我们可按ESC键让程序退出。

最后,WinMain按如下步骤运行:

1. 初始化主显示窗口和Direct3D

2. 调用setup进行程序的准备工作

3. 使用display函数作为参数进入消息循环

4. 清除应用程序最后释放IDirecte3DDevice9对象

注意:不要忘了在你的工程中加入d3d9.lib、d3dx9.lib、winmm.lib这三个库!

下载源码

本文转载自:http://www.cnblogs.com/flying_bat/archive/2008/03/16/1108364.html

共有 人打赏支持
rise-worlds

rise-worlds

粉丝 2
博文 1755
码字总数 0
作品 0
深圳
程序员
私信 提问
SDL2源代码分析3:渲染器(SDL_Renderer)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/40723085 ===================================================== SDL源代码......

雷霄骅
2014/11/04
0
0
SDL2源代码分析6:复制到渲染器(SDL_RenderCopy())

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/40895593 ===================================================== SDL源代码......

雷霄骅
2014/11/08
0
0
【 Visual C++】游戏开发笔记之二——最简单的DirectX,vc窗口的编写

笔记一中我们介绍了如何用代码创建空的win32窗口,然而创建空的win32窗口只完成了一半的工作,接下来要做的工作是设置Direct3D,从而可以在屏幕上渲染图形。 Direct3D要调用很多函数才能成功...

长平狐
2012/11/12
158
0
【Visual C++】游戏开发笔记三十二 浅墨DirectX提高班之一 DirectX大局观认知篇

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 文章链接: http://blog.csdn.net/zhmxy555/article/details/8172615 作者:毛星云(浅墨) 邮箱: happylifemxy@163.com 这篇文章作...

长平狐
2012/11/12
928
0
SDL2源代码分析7:显示(SDL_RenderPresent())

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/40895797 ===================================================== SDL源代码......

雷霄骅
2014/11/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Vue.js开发环境搭建说明(mac)

vue开发环境搭建(mac) 投影放大:cmd + + 安装Node 下载Node 官网下载 https://nodejs.org/en/download/ 安装Node 双击安装包,选择安装目录,比如: /usr/local/bin 安装成功后最好记录一...

Danni3
25分钟前
2
0
Qt编写自定义控件3-速度仪表盘

前言 速度仪表盘,写作之初的本意是用来展示当前测试的网速用的,三色圆环+数码管显示当前速度,Qt自带了数码管控件QLCDNumber,直接集成即可,同时还带有动画功能,其实也可以用在汽车+工业...

飞扬青云
30分钟前
1
0
【论文阅读】Image Super-Resolution via Deep Recursive Residual Network

题目:通过深度递归残差网络实现图像的超分辨率 摘要: 近年来,基于卷积神经网络的模型在单张图像的超分辨率上已经取得了巨大的成功。由于深度网络的强大,这些CNN模型学习了从低分辨率输入...

云烟成雨forever
32分钟前
2
0
为什么强烈建议大家使用枚举来实现单例

关于单例模式,我的博客中有很多文章介绍过。作为23种设计模式中最为常用的设计模式,单例模式并没有想象的那么简单。因为在设计单例的时候要考虑很多问题,比如线程安全问题、序列化对单例的...

群星纪元
51分钟前
14
0
Confluence 6 超过当前许可证期限进行升级

这个页面将会对你在进行 Confluence 升级的时候超过了当前许可证的期限进行升级的情况。 许可证警告 在升级的过程中,你将会在 Confluence 的应用程序日志(log file)中看到类似下面的错误提...

honeymoose
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部