从0到第一个D3D程序

 //下面是一个简单的小例子
class CSimpleD3DProcess
{
public:

	CSimpleD3DProcess(HWND hWnd)
	{

		memset(this,0,sizeof CSimpleD3DProcess);

		m_hWnd = hWnd;

		Init();
	}

	~CSimpleD3DProcess()
	{
		Destroy();
	}

	//第一步,初始化
	void Init()
	{
		m_pD3D = ::Direct3DCreate9(D3D_SDK_VERSION);
		if (m_pD3D == NULL)
		{
			return;
		}

		D3DPRESENT_PARAMETERS d3dPrePara;
		memset(&d3dPrePara,0, sizeof d3dPrePara);
		d3dPrePara.BackBufferCount = 1;
		d3dPrePara.BackBufferFormat = D3DFMT_UNKNOWN;
		d3dPrePara.Windowed = TRUE;
		d3dPrePara.SwapEffect = D3DSWAPEFFECT_DISCARD;

        m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
			                 D3DDEVTYPE_HAL,
							 m_hWnd,
							 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
							 &d3dPrePara,
							 &m_pDevice);
	}

	void Draw()
	{
		m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0,0);

		m_pDevice->BeginScene();

		m_pDevice->EndScene();

		m_pDevice->Present(NULL,NULL,NULL,NULL);
	}

	void Destroy()
	{
		m_pDevice->Release();
		m_pD3D->Release();
	}

private:
	HWND m_hWnd;

	LPDIRECT3D9 m_pD3D;
	LPDIRECT3DDEVICE9 m_pDevice;
};


 

1.directX 基本概念
    我们首先应该安装 directX sdk这个程序。
    directX是以COM组件的形式提供给程序员使用的。虽然COM组件的实现很复杂,但是在经过层层抽象之后程序员的使用很简单。
   
   
2.构建一个完整的程序
    (1).需要的库
        #pragma comment(lib,"d3d9.lib")
        #pragma comment(lib,"d3dx9.lib")
    (2).初始化的工作
        初始化的工作需要建立一个D3D的对象和一个device对象。 device对象的作用是建立hwnd和d3d的链接。
        下面是相关的代码:
        void Init()
       {
        m_pD3D = ::Direct3DCreate9(D3D_SDK_VERSION);
        if (m_pD3D == NULL)
        {
         return;
        }
       
        D3DPRESENT_PARAMETERS d3dPrePara;
        memset(&d3dPrePara,0, sizeof d3dPrePara);
        d3dPrePara.BackBufferCount = 1;
        d3dPrePara.BackBufferFormat = D3DFMT_UNKNOWN;
        d3dPrePara.Windowed = TRUE;
        d3dPrePara.SwapEffect = D3DSWAPEFFECT_DISCARD;
       
              m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                          D3DDEVTYPE_HAL,
              m_hWnd,
              D3DCREATE_SOFTWARE_VERTEXPROCESSING,
              &d3dPrePara,
              &m_pDevice);
       }
      
       下面是对 D3DPRESENT_PARAMETERS 对象的说明:
       D3DPRESENT_PARAMETERS可以翻译为d3d的显示参数设置,这样就比较好理解了。
        typedef struct _D3DPRESENT_PARAMETERS_ {
            UINT BackBufferWidth, BackBufferHeight;
            D3DFORMAT BackBufferFormat;
            UINT BackBufferCount;
            D3DMULTISAMPLE_TYPE MultiSampleType;
            DWORD MultiSampleQuality;
            D3DSWAPEFFECT SwapEffect;
            HWND hDeviceWindow;
            BOOL Windowed;
            BOOL EnableAutoDepthStencil;
            D3DFORMAT AutoDepthStencilFormat;
            DWORD Flags;
            UINT FullScreen_RefreshRateInHz;
            UINT PresentationInterval;
        } D3DPRESENT_PARAMETERS;
               
        BackBufferWidth和BackBufferHeight:后备缓冲的宽度和高度。在全屏模式下,这两者的值必需符合显卡所支持的分辨率。例如(800,600),(640,480)。
             
        BackBufferFormat:后备缓冲的格式。这个参数是一个D3DFORMAT枚举类型,它的值有很多种,例如D3DFMT_R5G6B5、D3DFMT_X8R8G8B8为游戏后备缓冲常用格式,这说明后备缓冲的格式是每个像素16位,其实红色(R)占5位,绿色(G)占6位,蓝色(B)占5位,为什么绿色会多一位呢?据说是因为人的眼睛对绿色比较敏感。DX9只支持16位和32位的后备缓冲格式,24位并不支持。如果对这D3DFORMAT不熟悉的话,可以把它设为D3DFMT_UNKNOWN,这时候它将使用桌面的格式。
       
        BackBufferCount:后备缓冲的数目,范围是从0到3,如果为0,那就当成1来处理。大多数情况我们只使用一个后备缓冲。使用多个后备缓冲可以使画面很流畅,但是却会造成输入设备响应过慢,还会消耗很多内存。
       
        MultiSampleType 和MultiSampleQuality:前者指的是全屏抗锯齿的类型,后者指的是全屏抗锯齿的质量等级。这两个参数可以使你的渲染场景变得更好看,但是却消耗你很多内存资源,而且,并不是所有的显卡都支持这两者的所设定的功能的。在这里我们分别把它们设为D3DMULTISAMPLE_NONE和0。
       
        可以通过CheckDeviceMultiSampleType 来检测当前装置是否支持某个抗锯齿类型
        typedef enum _D3DMULTISAMPLE_TYPE
        {
            D3DMULTISAMPLE_NONE               = 0,
            D3DMULTISAMPLE_2_SAMPLES       = 2,
            D3DMULTISAMPLE_3_SAMPLES       = 3,
            D3DMULTISAMPLE_4_SAMPLES       = 4,
            D3DMULTISAMPLE_5_SAMPLES       = 5,
            D3DMULTISAMPLE_6_SAMPLES       = 6,
            D3DMULTISAMPLE_7_SAMPLES       = 7,
            D3DMULTISAMPLE_8_SAMPLES       = 8,
            D3DMULTISAMPLE_9_SAMPLES       = 9,
            D3DMULTISAMPLE_10_SAMPLES      = 10,
            D3DMULTISAMPLE_11_SAMPLES      = 11,
            D3DMULTISAMPLE_12_SAMPLES      = 12,
            D3DMULTISAMPLE_13_SAMPLES      = 13,
            D3DMULTISAMPLE_14_SAMPLES      = 14,
            D3DMULTISAMPLE_15_SAMPLES      = 15,
            D3DMULTISAMPLE_16_SAMPLES      = 16,
            D3DMULTISAMPLE_FORCE_DWORD     = 0x7fffffff
        } D3DMULTISAMPLE_TYPE;
        //type 为以上的枚举值
        D3DMULTISAMPLE_TYPE type;
        int quality; //获取相对于type的最大质量等级(设置type抗拒值类型时,设置的质量等级只能小于这个数)
        //m_d3dBackFmt 为后备缓冲格式,m_bWindowed 是否为窗口模式,
        m_pD3D9->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,m_d3dBackFmt, m_bWindowed,type,&quality );
       
        SwapEffect:交换缓冲支持的效果类型,指定表面在交换链中是如何被交换的。它是D3DSWAPEFFECT枚举类型,可以设定为以下三者之一:D3DSWAPEFFECT_DISCARD,D3DSWAPEFFECT_FLIP,D3DSWAPEFFECT_COPY。
        如果设定为D3DSWAPEFFECT_DISCARD,则后备缓冲区的东西被复制到屏幕上后,后备缓冲区的东西就没有什么用了,可以丢弃(discard 是否丢弃由显卡决定,但不再等待)了。
        如果设定为D3DSWAPEFFECT_FLIP,后备缓冲拷贝到前台缓冲,保持后备缓冲内容不变。当后备缓冲大于1个时使用
        设定D3DSWAPEFFECT_COPY的话, 后备缓冲拷贝到前台缓冲,保持后备缓冲内容不变。当后备缓冲等于1个时使用
        一般我们是把这个参数设为D3DSWAPEFFECT_DISCARD。如果想使用GetBackBuffer 获得后备缓冲内容打印屏幕画面。则不能使用DISCARD.
        很怀疑用DISCARD效率会好的说法。在我的8600GT 上_COPY 明显好于DISCARD. discard 做法是再次使用后备缓冲时 new 一个新的缓冲,旧的缓冲内容遗弃,如果还有使用旧的缓冲地方,不会影响新的内容,如使用抗锯齿必须是DISCARD。这样不用等待硬件同步。不过大部分是一次Present操作。用COPY在新机器上面反倒效率好些。毕竟new 一个 1440*900 的后台缓冲也是有消耗的。(对于DISCARD 做法仅仅是猜测。不同显卡可能不同。)
       
        hDeviceWindow:显示设备输出窗口的句柄
       
        Windowed:如果为FALSE,表示要渲染全屏。如果为TRUE,表示要渲染窗口。渲染全屏的时候,BackBufferWidth和BackBufferHeight的值就得符合显示模式中所设定的值。
       
        EnableAutoDepthStencil:如果要使用Z缓冲或模板缓冲,则把它设为TRUE。
       
        AutoDepthStencilFormat:如果不使用深度缓冲,那么这个参数将没有用。如果启动了深度缓冲,那么这个参数将为深度缓冲设定缓冲格式。常用值D3DFMT_24S8 (24 深度缓冲,8模板缓冲),D3DFMT_24X8(24 深度缓冲),D3DFMT_16(16深度缓冲)等等。
        //深度缓存和模板缓存的象素格式,如 D3DFMT_D24S8 , 24 位表示深度,8位为模板缓存。一般不会用到32位深度:D3DFMT_32
        //注意如果设置模板缓冲在Clear() 函数中也要清楚模板缓冲:设置参数 D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL
       
        Flags:通常为0 或D3DPRESENTFLAG_LOCKABLE_BACKBUFFER。不太清楚是用来做什么的,看字面好像是一个能否锁定后备缓冲区的标记。D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL 丢弃模板缓冲区
       
        FullScreen_RefreshRateInHz:显示器的刷新率,单位是HZ,如果设定了一个显示器不支持的刷新率,将会不能创建设备或发出警告信息。为了方便,一般设为D3DPRESENT_RATE_DEFAULT就行了。
       
        PresentationInterval:如果设置为D3DPRENSENT_INTERVAL_DEFAULT,则说明在显示一个渲染画面的时候必要等候显示器刷新完一次屏幕。例如你的显示器刷新率设为80HZ的话,则一秒内你最多可以显示80个渲染画面。另外你也可以设置在显示器刷新一次屏幕的时间内显示1到4个画面。如果设置为 D3DPRENSENT_INTERVAL_IMMEDIATE,则表示可以以实时的方式来显示渲染画面,虽然这样可以提高帧速(FPS),如果速度过快却会产生图像撕裂的情况,但当游戏完成时,帧速度一般不会过快。
 
        下面是对CreateDevice的说明:
        HRESULT CreateDevice(
        UINT Adapter,
        D3DDEVTYPE DeviceType,
        HWND hFocusWindow,
        DWORD BehaviorFlags,
        D3DPRESENT_PARAMETERS *pPresentationParameters,
        IDirect3DDevice9** ppReturnedDeviceInterface
        );
       
        2参数:编辑Adapter:
        序数所指示的显示器适配器。D3DADAPTER_DEFAULT始终是主要的显示器适配器。
        DeviceType:
        在D3DDEVTYPE列举的成员,表示预设类型的驱动器类型,在HAL(Hardware Accelerator,硬件加速)和REF(Reference Rasterizer,一调试工具)之间选择。这里有第三个选项,软件渲染,作用是设计能支持自定义渲染的插件。DirectX DDK(驱动程序开发工具包)就能做到,但如果你能自己写出3D渲染器的话,是不太可能使用VB的J……请指定参数D3DDEVTYPE_HAL(硬件加速)或D3DDEVTYPE_REF(软件模拟) 。,如果预设的设备类型是无效的,即如果不支持硬件加速,调用此函数就会失败,你就不能创建设备。
        hFocusWindow:
        与设备相关的窗口句柄,你想在哪个窗口绘制就写那个窗口的句柄
        BehaviorFlags:
        设定为D3DCREATE_SOFTWARE_VERTEXPROCESSING(软件顶点处理) 或者D3DCREATE_HARDWARE_VERTEXPROCESSING(硬件顶点处理) ,使用前应该用d3dcaps来检测用户计算机是否支持硬件顶点处理功能。使用硬件处理的意思就是说使用显卡处理,当然要检查是否有显卡,而且使用硬件处理速度要快一些。
        PresentationParameters:
        一个D3DPRESENT_PARAMETERS 类型的变量,用于指定将要创建设备的各种信息
        ppReturnedDeviceInterface:
        一个DIRECT3DDEVICE9类型的指针用来返回创建的设备
        
    (3)开始绘制
        void Draw()
     {
     //第一步清空depth和stencil缓冲器,并且设置背景色
      m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0,0);
      //开始绘制图形,绘制图形必须是 BeginScene 和 EndScene 搭配使用
      m_pDevice->BeginScene();
     
      m_pDevice->EndScene();
     
      //显示绘制的图形
      m_pDevice->Present(NULL,NULL,NULL,NULL);
     }

 

        m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0,0);的详解:
        IDirect3DDevice9::Clear的前两个参数,告知Direct3D所要清除一系列矩形的大小和地址。这些矩形描述了那些在渲染目标表面的,即将被清除的区域。
        大多数情况下,你仅仅使用一个覆盖整个渲染目标的矩形。为了达到这个目的,需要将第一个参数设置为0,同时第二个参数设置为NULL。第三个参数决定了此方法的行为。你可以指定不同的标志位,从而来清理渲染目标表面,关联的深度缓冲,模板缓冲,或者是他们三者的任意组合。
        渲染目标(render target)指的是一个缓存区。
       
        g_pd3dDevice->Present( NULL, NULL, NULL, NULL ) 详解:
        前两个参数分别代表了源矩形和目标矩形。由于此示例中是将整个后备缓冲提交到前台缓冲中,所以这两个参数设置为NULL。第三个参数用来设置接受呈现的目标窗口。由于这个参数被设置为NULL,则会默认使用D3DPRESENT_PARAMETERS中的hWndDeviceWindow成员所代表的窗口。第四个参数代表了“脏矩形区域”,在大多数情况下都应该设置为NULL。

 

 

    (4).程序结束,释放资源
        void Destroy()
       {
        m_pDevice->Release();
        m_pD3D->Release();
       }


   

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值