目前D3D版本很多(10、11、12), 本文以及后续的实例都将使用D3D9。
使用D3DAPI之前,首先需要安装DXSDK_Jun10.exe,这在前边的文章有介绍。具体安装非常容易,下载安装包一路下一步即可。
本文目的:本文将介绍如何将一帧YUV(NV12)数据渲染显示。
主要方法:创建离屏表面
代码流程:
函数原型:
CreateDevice(THIS_ UINT Adapter, D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface);cpp
第一个参数:Adapter
代理模式,即将要使用的显卡适配器的标识号,一般选择 D3DADAPTER_DEFAULT 就ok。
第二个参数:DeviceType
D3DDEVTYPE_HAL:硬件抽象层,通过显示硬件来完成图形渲染工作
D3DDEVTYPE_REF:参考光栅器,一般用于测试显卡不支持的D3D功能
D3DDEVTYPE_SW:用于支持第三方软件
第三个参数:hFocusWindow
创建的窗口句柄,也即图形将出现的窗口。
是焦点窗口,当应用程序从前台模式切换到后台模式的时候向Direct3D提示的窗口。
如果是全屏模式,这个窗口指定的焦点窗口必须是最顶层窗口。
对于窗口模式,这个参数可以是NULL(用的是当前显示的窗口),除非PRESENTPARAMETERS的hDeviceWindow参数是一个合法的非NULL值。
交换链有多个后台缓存的时候,每个后台缓存需要各自hDeviceWindow设备窗口,可以共用一个hFocusWindow焦点窗口(一个焦点窗口可以只给一个后台缓存当做自己的设备窗口)。
D3DCREATE_SOFTWARE_VERTEXPROCESSING
由D3D软件进行顶点运算(常用)
D3DCREATE_FPU_PRESERVE
激活双 精度 浮点运算或浮点运算异常 检测,设置该项会降低系统性能
D3DCREATE_MULTITHREADED
保证D3D是 多线程 安全的,设置该项 会降低系统性能
D3DCREATE_MIXED_VERTEXPROCESSING
由混合方式进行顶点运算
D3DCREATE_HARDWARE_VERTEXPROCESSING
由D3D硬件进行顶点运算
D3DCREATE_PUREDEVICE
禁用D3D的Get*()函数,禁止D3D 使用虚拟设备模拟顶点运算
注意
D3DCREATE_HARDWARE_VERTEXPROCESSING
D3DCREATE_MIXED_VERTEXPROCESSING
D3DCREATE_SOFTWARE_VERTEXPROCESSING
这三个顶点运算时互斥的,且在该函数中必须被指定一个。
后台缓存只用在D3DPRESENT_PARAMETERS中用D3DPRESENTFLAG_LOCKABLE_BACKBUFFER指定了才能被锁定,多重采样纹理的后台缓存和深度缓存不能被锁定。
第五个参数:pPresentationParameters
渲染参数设定,根据需要创建。
第六个参数:ppReturnedDeviceInterface
该参数是输出参数,D3D设备,调用这个借口之后,创建成功的D3D设备将使用该参数返回。
可以将一个矩形区域的像素从设备内存的一个Surface转移到另一个Surface上。
StretchRect()函数的原型如下
HRESULT StretchRect( IDirect3DSurface9 * pSourceSurface, CONST RECT * pSourceRect, IDirect3DSurface9 * pDestSurface, CONST RECT * pDestRect, D3DTEXTUREFILTERTYPE Filter );cpp
// 以下代码实例了,如何将离屏表面的内存拷贝到后台缓冲区: IDirect3DDevice9 *m_pDirect3DDevice; IDirect3DSurface9 *m_pDirect3DSurfaceRender; IDirect3DSurface9 * pBackBuffer; m_pDirect3DDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer); m_pDirect3DDevice->StretchRect(m_pDirect3DSurfaceRender,NULL,pBackBuffer,&m_rtViewport,D3DTEXF_LINEAR); // 将离屏表面的数据传给了后台缓冲表面。一但传给了后台缓冲表面,就可以用于显示了。cpp
在D3D中,需要使用BeginScene和EndScene函数,然后所有的图元绘制代码才能被调用。通过了解,需要注意下下面一些问题:
代码仅作为参考。
/** * 函数调用步骤如下: * * [初始化] * Direct3DCreate9():获得IDirect3D9 * IDirect3D9->CreateDevice():通过IDirect3D9创建Device(设备)。 * IDirect3DDevice9->CreateOffscreenPlainSurface():通过Device创建一个Surface(离屏表面)。 * * [循环渲染数据] * IDirect3DSurface9->LockRect():锁定离屏表面。 * memcpy():填充数据 * IDirect3DSurface9->UnLockRect():解锁离屏表面。 * IDirect3DDevice9->BeginScene():开始绘制。 * IDirect3DDevice9->GetBackBuffer():获得后备缓冲。 * IDirect3DDevice9->StretchRect():拷贝Surface数据至后备缓冲。 * IDirect3DDevice9->EndScene():结束绘制。 * IDirect3DDevice9->Present():显示出来。 */ #include <stdio.h> #include <tchar.h> #include <d3d9.h> #include <windows.h> #include <stdio.h> #include <d3d9.h> #include <d3dx9.h> #include <tchar.h> #include <time.h> #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #pragma comment(lib,"dxguid.lib") #pragma comment(lib, "winmm.lib") CRITICAL_SECTION m_critial; IDirect3D9* m_pDirect3D9 = NULL; IDirect3DDevice9* m_pDirect3DDevice = NULLcpp