DirectX游戏编程学习(一)初始化Direct3D

//-----------------------------------------------------------------------------
// File: CreateDevice.cpp
//
// Desc: This is the first tutorial for using Direct3D. In this tutorial, all
//       we are doing is creating a Direct3D device and using it to clear the
//       window.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <d3d9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 )




//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9         g_pD3D = NULL; //Direct3d对象
LPDIRECT3DDEVICE9   g_pd3dDevice = NULL; // Direct3D渲染设备对象
/*
说明,一个Direct3D对象可以创建多个Direct3d设备对象,但是D3D对象创建的所有渲染设备对象共享相同的物理资源,
所以会导致严重的性能下降
*/



//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // 创建D3D对象,该对象用于创建D3D设备对象
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    //设置D3DPRESENT_PARAMETERS结构,准备创建D3D设备对象
	/*说明 在DX对窗口进行渲染之前,必须先根据渲染需要对窗口进行设置,比如是使用硬件渲染还是软件渲染,渲染是使用单缓冲还是双缓冲
	  是否需要进行深度缓存,是否需要模板、Alpha缓存等。当你为窗口设置了这些参数之后,就不能改变了,除非销毁再根据需要创建另外的窗口。
	  窗口的3d特征是一次性设置的,通常就在创建窗口之后,这些设置的集合的名称就是D3DPRESENT_PARAMETERS
	*/
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;	//全屏或窗口
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//指定表面在交换链中是如何被交换的。D3DSWAPEFFECT_DISCARD:后备缓存的内容被复制到屏幕上后,后备缓存的内容失效,可以丢弃
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;//后备缓冲的格式,若不熟悉,可设置为D3DFMT_UNKNOWN,这时它将使用桌面的格式

	/*
	当准备工作结束后,就可以创建DX设备对象罗,因为DX对象是整个DX程序的最顶层对象,其他的对象都将通过它的接口函数调用来创建
	参数1:指定对象要表示的物理显示设备,即使用哪个显卡来创建设备对象
	参数2:设备类型,这里选的是HAL设备。最主要的设备就是硬件抽象层(HAL)设备,它支持硬件光栅化加速和软硬件顶点处理。D3D通过HAL访问硬件。应用程序
	如果在支持HAL的计算机上运行,那么通过使用HAL设备将获得最佳性能。另一个是参考设备,它支持所有D3D特性,但是用软件实现,所以对于硬件来说,较慢。
	参数3:指定DX程序从前台变换到后台时的提示窗口。
	参数4:指定D3D进行3D运算的工作方式,此处参数含义:DX软件进行顶点运算
	参数5:制定一个已经初始化的D3DPRESENT_PARAMETERS实例
	参数6:返回创建的设备,创建好的设备对象指针存储在该参数中
	*/
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // Device state would normally be set here

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
// 清空之前引用的资源
//-----------------------------------------------------------------------------
/*
D3D对象和D3D设备对象都是系统资源,若只申请不释放,必定造成资源泄露,在整个过程,申请的对象一定要手动释放。
因为D3D设备对象是D3D对象创建的,所以先释放D3D设备对象。最先创建的最后释放,创建、释放的过程和栈结构一样
*/
VOID Cleanup()
{
    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
    if( NULL == g_pd3dDevice )
        return;

    // 清空后台缓存
	/*
	参数1:pRects组中的矩形个数,若第二个参数(*pRects)为空,则此处必须为0,若不为空,则必须是非0值
	参数2:将要清除的屏幕矩形数组,是一个指向D3DRECT结构数组的指针,这使我们可以清除屏幕的某一部分
	参数3:指定在哪些表面上执行清除表面操作,D3DCLEAR_TARGET表示清空颜色缓存
	参数4:使用什么颜色填充清除的表面
	参数5:设置深度缓冲的值
	参数6:设置模板缓冲的值
	*/
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 255, 255 ), 1.0f, 0 );

    // 开始在后台缓存绘制图形
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // Rendering of scene objects can happen here

        // End the scene
        g_pd3dDevice->EndScene();
    }

    // 将在后台缓存绘制的图形提交到前台缓存显示
	/*
	参数1:是你想要显示的后备缓存的一个矩形区域,设为NULL表示要将整个后备缓存的内容显示
	参数2:表示一个显示区域,设为NULL表示整个客户显示区域
	参数3:可以通过它来将内容显示到不同的窗口中。设为NULL则表示显示到当前主窗口。
	参数4:是最小更新区域指针,一般设为NULL
	*/
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}




//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
// 消息处理函数 回调函数
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
		//窗口关闭
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;
		//窗口绘制
        case WM_PAINT:
            Render();
            ValidateRect( hWnd, NULL );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}




//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: 这是整个工程的入口函数,从这里开始理结构,,
/*
注意,InitializeD3D是完成DX整个框架的资源需求,如果该函数不成功,这个程序就不能继续运行,但
如果Windows框架资源没有申请成功,这个程序也不能继续运行。应该先申请Windows框架资源,然后再判断
InitializeD3D是否创建成功,若成功,则进入消息循环
-----------------------------
wWinMain可以处理unicode字符,
而WinMain却会把Unicode字符直接转换成ANSI字符来处理(

如果使用了中文,就可能出错)
第一个参数:应用程序当前句柄
第二个:这一个应用程序实例的前一个句柄(同时运行了一个以上)
第三:不包含应用程序的命令行,可以用CMD向应用程序传入一条字符串指令
第四:制定窗口如何显示的ID
*/
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    UNREFERENCED_PARAMETER( hInst );
	/*
		Win32中的宏UNREFERENCED_PARAMETER,
		可以使用它来避免编译器对在函数体中未引用的参数的警告。
		虽然从技术上讲是没有必要的,但是努力地构建0个警告的代码是一种良好的编程习惯。
		由于这个特殊的宏没有做任何事情,编译器会将对其进行优化。
	*/

    //定义窗口类
	/*
	这个窗口类被定义为结构体WNDCLASSEX,它包含Win32窗口的各种属性,
	其中包括窗口的图标,菜单,窗口所属的应用实例,光标的外观等等
	*/
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
	//注册窗口类
	/*
	把我们创建的WNDCLASSEX结构发送给函数RegisterClassEx(),向系统注册窗口类。
	函数RegisterClassEx()必须在创建窗口前调用,该函数需要窗口类结构的地址作为
	参数才能进行注册。如果该函数执行后,返回值是0就表示注册失败,
	读者就要检查这个窗口类各成员的值,看看是否有错误,确保它们都是有效值。
	*/
    RegisterClassEx( &wc );     
	/*
	下一步是创建实际的窗口
	CreateWindow接受Unicode字符。如果使用的是Unicode版本,
	我们必须始终要把字符串用引号括起来,然后加一个L做前缀,
	以表明我们提供的是Unicode字符。
	-----
	参数:
	lpClassName(可选的)——窗口类的名称(与窗口类结构使用相同的名称)。
	lpWindowName (可选的)——窗口的标题栏文字。
	dwStyle——窗口风格的标志。
	X——窗口的水平位置。
	Y——窗口的垂直位置。
	nWidth——窗口的宽度。
	hHeight——窗口的高度。
	hWndParent(可选的)——指向父窗口的句柄(比如这个新的窗口是一个弹出窗口或子窗口)。
	hMenu (可选的)——窗口菜单资源句柄。
	hInstance (可选)——应用程序实例ID(函数wWinMain的第一个参数)
	lpParam (optional)——作为窗口回调函数proc的参数,向窗口传递数据
	---
	函数CreateWindow(A)的返回值是一个非空的句柄
	*/
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              NULL, NULL, wc.hInstance, NULL );

    // Initialize Direct3D   初始化D3D设备
	/*如果创建成功,则进入消息循环*/
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // 展示窗口
        ShowWindow( hWnd, SW_SHOWDEFAULT );
        UpdateWindow( hWnd );

        // Enter the message loop
		/*
		MSG是一个Win32结构,用于保存窗口消息,其中一些消息是来自操作系统的,
		应用程序将会响应这些消息
		*/
        MSG msg;
        while( GetMessage( &msg, NULL, 0, 0 ) )//提取消息
        {
			/*
			我们可以通过调用TranslateMessage函数和DispatchMessage函数对这一消息作出回应
			函数TranslateMessage是将虚拟键消息转换为字符消息,
			函数DispatchMessage是派发这个消息到窗口程序的回调函数中去,这个将在下一节中讨论
			*/
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }

    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}



运行效果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值