admin 管理员组

文章数量: 1184232

Direct3D技术在图像处理、游戏开发等领域用得非常广泛,这里给大家讲解怎么用Direct3D API开发一个简单的图片浏览器。这个图片浏览器的功能有:图像显示,在视图区拖动图层、改变图层大小、图层旋转。先提醒一下,阅读该篇文章的读者最好具有一点D3D的开发基础,因为这篇文章不会讲Directshow的基础知识。如果你完全没有学过Direct3D,建议先学习一下一些Direct3D的入门教程(比如:《DirectX 9.0 3D游戏开发编程基础》 )。

Direct3D概述

Direct3D(简称:D3D)是微软公司开发出来的一套3D绘图编程接口,是DirectX的一部份,是一种更高效的绘图API,支持直接在显存中操作图像,目前广被各家显卡厂商所支援。

Direct3D封装了一个硬件抽象层(HAL),硬件厂商遵守这个硬件层的接口标准,对外以统一的接口形式为用户提供图形图像功能,也就是说开发者可以在无视于设备差异的情况下访问底层的硬件。DirectX 封装了一些 COM(Component Object Model)对象,这些 COM 对象为访问系统硬件提供了一个主要的接口。下面是Direct3D的架构图:

开发Direct3D程序的流程

Driect3D功能非常强大,但是Direct3D程序的结构非常简单清晰,一个Direct3D程序的基本结构如图1所示:

                    

开发Direct3D程序大概可以细分为以下几个步骤:
1. 创建窗口

2. 初始化Direct3D
创建D3D接口对象 -》获取设备性能信息 -》填充D3DPRESENT_PARAMETERS结构 -》创建D3D设备接口对象

3. 处理系统消息循环
 获取、转换并调度消息 -》重画客户区

4. 渲染与显示

5. 释放所有D3D对象
 

例子解析

这个例子功能很简单,从磁盘加载图片进来,显示到中央的视图窗口,接着可以对图像进行一些操作。界面是用Win32 API开发的,上面有个菜单栏。我们打开一张图片后,图片以缩略图形式显示到中间,这时候图片被D3D作为一个图层(即Texture)显示,我们可以对图层进行放大、拖动、旋转和删除操作。目前最多支持两个图层显示(这个读者可以修改)。程序的运行示意图如下:

我们先看看这个例子的程序入口点即WinMain函数是如何实现的:

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR lpCmdLine, INT nCmdShow)
{
	HRESULT hr = S_OK;
	// UINT uTimerID=0;

	// Initialize COM
	CoInitialize (NULL);

	hInstance = hInst;

	g_pPresentation = new CD3DImageDraw();
	if( !g_pPresentation )
	{
		hr = E_OUTOFMEMORY;
		Msg( TEXT("Memory allocation error: failed to create CD3DImageDraw object"), E_OUTOFMEMORY);
	}
	else
	{
		hr = g_pPresentation->Initialize();
	}


	m_nCurSel = -1;

	if( SUCCEEDED(hr))
	{

		// Enter the message loop
		MSG msg;
		ZeroMemory( &msg, sizeof(msg) );

		// Main message loop
		while( msg.message!=WM_QUIT )
		{
			if(GetMessage( &msg, NULL, 0, 0))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
	}

	// Clean up everything and exit the app
	if( g_pPresentation )
	{
		delete g_pPresentation;
		g_pPresentation = NULL;
	}

	CoUninitialize();
	return 0L;
}

上述代码很直观的展示了整个程序的流程:

1. 调用Com库初始化函数(因为D3D库需要加载);

2. 创建一个CImageDraw类型的实例,将指针变量g_pPresentation指向这个实例;

3. 创建窗口;

4. 开始消息循环;

5. 销毁D3D对象,卸载COM库,退出程序。

因为CImageDraw类负责D3D资源的创建和管理,图像的显示绘制也在这个类里面实现,还有跟图层显示相关的类:CImageTexture,我们有必要对这几个类做一下介绍。以下是这些类的声明:

class  CDirect3DBase
{
   // methods
public:
	CDirect3DBase();
	~CDirect3DBase();

    HRESULT Initialize();
    HRESULT Render();

    HRESULT InitD3D();
    HRESULT SetupMatrices();
    void    SetWorld();

	void SetColor( D3DCOLOR color );
    IDirect3DDevice9 * GetDevice();

public:
	int    m_scnWidth, m_scnHeight;  
    float  m_WorldLeft, m_WorldTop, m_WorldRight, m_WorldBottom;
  
protected:
    void Cleanup(void);

protected:
	HWND    m_hwnd; 
    CComPtr<IDirect3D9>             m_pD3D;         
    CComPtr<IDirect3DDevice9>       m_pd3dDevice;  

    D3DCOLOR   m_d3dcolorBackground; 

};


class CImageTexture
{
public:
   CImageTexture();
   ~CImageTexture();

   CDirect3DBase * m_pD3DBase;

   D3DXVECTOR3   ScreenToWorld(D3DXVECTOR3 s);
   D3DXVECTOR3   WorldToScreen(D3DXVECTOR3 w);
 
public:
	HRESULT   Init();
	HRESULT   LoadImageToTexture(LPCTSTR lpFile);
	//HRESULT LoadImagetoTexture(HBITMAP hbmp);

	void      SetFilePath(LPCTSTR lpszFile);
	HRESULT   ReLoad();
	void      ReleaseTexture();

    HRESULT   BltToTexture(IDirect3DSurface9 *lpSurf, UINT Width, UINT Height);
    HRESULT   CopyMediaSample( BYTE *pSampleBuffer, LONG lSamplePitch );

	int       GetImageWidth()  { return m_ImageWidth; }
	int       GetImageHeight() { return m_ImageHeight; }

	void      SetX(float x) {  m_Xpos = x; }
	void    

本文标签: 拖动 多图 图层 图片浏览器 Direct3D