文档章节

初始化Direct3D(4)

rise-worlds
 rise-worlds
发布于 2016/06/20 13:39
字数 1618
阅读 0
收藏 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

没有更多内容

加载失败,请刷新页面

加载更多

RS-232、RS422和RS-485的区别和各自的实现方式

一、殊途同归 RS-232、RS422和RS-485 均属于UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),仅用两根信号线(Rx 和Tx)就可以完成通信过程; 而由于各自使用的电...

rainbowcode
36分钟前
0
0
spring 本类中方法调用另外一个方法事务不生效

1、在spring配置文件中添加 <aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true" />声明自动代理 <!-- 标识通过aop框架暴露该代理,aopContext能够访问. --> proxy-targe......

重城重楼
42分钟前
5
0
项目 banner 乱弹

------------------------------------------ 村上春树 ------------------------------------- 如果我爱你,而你也正巧爱我,你头发乱了的时候,我会笑笑地替你拨一拨,然后手还留恋地在你...

宿小帅
54分钟前
3
0
PHP获取未来七天的日期和星期

php获取未来七天的日期和星期代码 第一步:获取需要天数的日期,然后调用函数 //获取未来七天的日期 for($i=1;$i<8;$i++){ $dateArray[$i]=date('Y-m-d',strtotime(d...

一只懒猫-
今天
2
0
总结:IO模型

分类 多路复用 参考文章: https://www.jianshu.com/p/6a6845464770 https://www.cnblogs.com/zingp/p/6863170.html https://blog.csdn.net/sehanlingfeng/article/details/78920423......

浮躁的码农
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部