Direct3D应用中的2D应用.docx
- 文档编号:23550941
- 上传时间:2023-05-18
- 格式:DOCX
- 页数:20
- 大小:22.81KB
Direct3D应用中的2D应用.docx
《Direct3D应用中的2D应用.docx》由会员分享,可在线阅读,更多相关《Direct3D应用中的2D应用.docx(20页珍藏版)》请在冰豆网上搜索。
Direct3D应用中的2D应用
Direct3D应用中的2D应用
2DApplication收藏()2DApplication
这一章将讨论IDirect3DDevices9接口怎样应用到简单的两维应用程序里去。
然而,接下来讨论的方法和接口的方法不仅仅只应用在两维应用程序里面。
开始我们将看看IDirect3DSurface9接口,它用于存放像素数据。
我们将看看怎样创建surfaces,怎样填充数据,并且执行像素拷贝操作。
接下来,我们讨论IDirect3DSwapChain9接口管理backbuffer集合。
设备创建的时候都会携带一个默认的swapchain,但是也可以为window模式下多个视图创建新的swapchain。
再接下来,我们将讨论Presentation,Present也是IDirect3DDevice9提供的方法。
即使Direct3D可以不使用GDI,但是他们也要处理发送到应用程序top-level窗口的消息。
我们推荐使用Direct3D应用程序来处理窗口消息。
DirectX并没有提供直接方法来将GDI和Direct3D结合起来。
但是,通常是在存DC和流水线产生的结果像素数据上执行GDI操作。
最后,我们将讨论流水线的Videoscanout部分以及swapchain从backbuffer到frontback的过程。
videoscanout电流读取数据,使用cursoroverlay,gamma校正以及像素数据转化成monitor的模拟信号。
PixelSurface
Pixel面是像素数据的矩形集合。
像素数据的存layout是通过D3DFORMAT定义的。
在设备上使用surface有几处地方:
backbuffersurfaces,depth/stencilbuffersurfaces,纹理层surface,rendertargetsurface以及图片surface。
Direct3D使用IDirect3DSurface9接口表示一个surface,CreateOffscreenPlainsurface方法可以创建一个图片surface,它能存在于scrath存池,系统存池和设备存池。
CreateDepthStencilSurface和CreateRenderTarget分别返回depth/stencil的surface和render
target的surface。
一个plainsurface可能不是3D渲染的目标,但是你能在plainsurface和其他surface之间进行数据拷贝。
HRESULTCreateOffscreenPlainSurface(UINTwidth,
UINTheight,
D3DFORMATformat,
D3DPOOLpool,
IDirect3DSurface9**result,
HANDLE*unused);如果设备不支持被请求面的各式,CreateOffscreenPlainSurface将会失败,或者是系统存里面没有足够的存储空间。
使用CheckDeviceFormat可以用来预先检查设备是否支持某种格式的surface。
interfaceIDirect3DSurface9:
IDirect3DResource9
{
HRESULTGetContainer(REFIIDcontainer_iid,void**value);
HRESULTGetDC(HDC** value);
HRESULTGetDesc(D3DSURFACE_DESC*value);
HRESULTLockRect(D3DLOCKED_RECT* data,constRECT*locked_region,DWORDflags);
HRESULTRelease(HDCcontext);
HRESULTUnlockRect();
}对于CreateOffscreenPlainSurface创建的surface,当container_iid是IID_Direct3DDevice9时,GetContainer将返回成功。
GetDESC将返回D3DSURFACE_DESC结构体里面的像素数据的描述信息。
typedefstruct_D3DSURFACE_DESC
{
D3DFORMATFormat;
D3DRESOURCETYPEType;
DWORDUsage;
D3DPOOLPool;
D3DMULTISAMPLE_TYPEMultiSampleType; //与rendertargetsurface一起使用的multisampling
DWORDMultiSampleQuality;
UINTWidth;
UINTHeight;
}D3DSURFACE_DESC;AccessingSurfacePixelData
为了获取surface的像素数据,我们需要使用LockRect和UnlockRect方法。
当lockRect方法的locked_region不为NULL的时候,就只lock住了surface的某个局部。
参数flags告诉Direct3D一旦surface被锁住,数据将怎么办。
Flags包括D3DLOCK_DISCARD,D3DLOCK_DONOTWAIT,D3DLOCK_NO_DIRTY_UPDATE,D3DLOCK_NOSYSLOCK,D3DLOCK_READONLY。
D3DLOCK_DISCARD通知runtime整个locked区域将只被写入而不读取。
使用discardflag,runtime不会提供一份surface数据的copy给应用程序读取。
不使用discardflag,runtime可能被迫停掉所有未决的操作,然后再返回一个surface数据的copy给应用程序。
注意:
这个flag不能使用在子区域。
D3DLOCK_DONOTWAIT决定当lock的时候不会阻塞住runtime,等待未决的渲染操作完成。
如果lock调用已经阻塞了,它将返回D3DERR_WASSTILLDRAWING。
Direct3D为每个可管理的surface(注意这里只能是managedsurface)维护一个dirty区域表,用来最小化unlock数据的拷贝量。
如果已经是使用了D3D_NO_DIRTY_UPDATE,locked区域将不会影响dirty区域list。
使用D3DLOCK_READONLY,应用程序保证对锁定区域没有任何的写操作。
D3DLOCK_NOSYSLOCK只只能应用到videomemory的surfaces。
为了阻止video存储资源被锁时设备lost,Direct3D获取系统criticalsection来阻止设备丢失。
它也能阻塞操作系统的其他部分执行,这样势必会影响系统的交互和反应灵敏度。
D3DLOCK_NOSYSLOCK禁止获取系统的criticalsection。
LockRect方法返回D3DLOCKED_RECT结构体,它定义了surface的像素数据。
它保证了surface数据在sanline上是连续的。
typedefstruct_D3DLOCKED_RECT
{
intpitch;//定义了相邻两个scanlines的距离。
void*pBits;//像素数据的指针。
}D3DLOCKED_RECT;当遍历surface的每个像素时,pitch和像素的大小是很重要的。
像素数据的大小是跟D3DFORMAT有关。
IDirect3DSurface9并没有提供方法用于从图片装载到surface,或者像素格式转换,D3DX却提供了很多这样的操作方法。
UsingGDIOnaSurfaceGDI提供GetDC和ReleaseDC方法来操作与GDI兼容格式的surface。
与GDI兼容格式包括D3DFMT_R5G6B5,D3DFMT_X1R5G5B5,D3DFMT_R8G8B8和D3DFMT_X8R8G8B8。
GDIdevicecontext可以使用GDI执行基于surface的渲染操作,然后立刻释放。
一旦devicecontext被创建,就会在Direct3Druntime里面建立一个lock。
这个lock保证runtime并不直接跟GDIrendering交互。
因为这个lock的存在,应用程序应该尽可能快的释放GDIdevicecontext。
而且,只有devicecontext释放以后,下面表里的方法才能调用。
Interface
Method
IDirect3DCubeTexture9
LockRect
IDirect3DDevice9
ColorFill
Present
StretchRect
UpdateSurface
UpdateTexture
IDirect3DSurface9
LockRect
IDirect3DSwapChain9
Present
IDirect3DTexture9
LockRect
SwapChain
每个设备都包含一组默认的swapchains。
GetNumberOfSwapChains返回设备swapchains的数目。
GetSwapChain方法返回默认swapchain集合里的swapchain的接口。
默认swapchain集合的属性定义在D3DPRESENT_PARAMETERS。
Swapchain由1个,2个,3个backbuffersurface和一个frontbuffersurface。
frontbuffersurface不能直接访问,但是它仍然参与到swapchain的presentation过程中。
当调用Present时backbuffersurface显示在monitor。
exclusive模式的设备使用它默认的backbuffer。
window模式的设备可以使用多个swapchain,每个都可以将渲染结果绘制它自己的窗口。
exclusive模式的adaptergroup设备也可以渲染到多个monitor。
CreateAdditionalSwapChain创建一个基于D3DPRESENT_PARAMETERS的swapchain,然后返回一个IDirect3DSwapChain9接口。
注意一个Swapchain只能包含backbuffersurface而不是depth/stencilsurface。
HRESULTCreateAdditionalSwapChain(D3DPRESENT_PARAMETERS*params,IDirect3DSwapChain9**result);interfaceIDirect3DSwapChain9:
IUnknown
{
HRESULTGetBackBuffer(UINTbuffer,D3DBACKBUFFER_TYPEkind,IDirect3DSurface9**value);
HRESULTGetDevice(IDirect3DDevice9**value);
HRESULTGetDisplayMode(D3DDISPLAYMODE*value);
HRESULTGetFrontBufferData(IDirect3DSurface9*destination);
HRESULTGetPresentParameters(D3DPRESENT_PARAMETERS*value);
HRESULTGetRasterStatus(D3DRASTER_STATUS*value);
HRESULTPresent(CONSTRECT*source,CONSTRECT*destination,HWNDoverride,CONSTRGNDATA*dirty_region,DWORDflags);
}GetBackBuffer返回一个backbuffersurface的接口指针。
backbuffer序号以0开始,present首先显示是backbuffer0里面的容,然后再是backbuffer1,依此下去...。
D3DBACKBUFFER_TYPE定义了backbuffer的类型。
DirecX9.0c并不支持stereo渲染,,kind只能是D3DBACKBUFFERTYPE_MONO.
typedefenum_D3DBACKBUFFER_TYPE
{
D3DBACKBUFFER_TYPE_MONO=0,
D3DBACKBUFFER_TYPE_LEFT=1,
D3DBACKBUFFER_TYPE_RIGHT=2
}D3DBACKBUFFER_TYPE;Present跟device的Present方法一样,都执行同样的功能。
flag的值包括D3DPRESENT_DONOTWAIT和D3DPRESENT_LINEAR_CONTENT。
D3DPRESENT_DONOTWAIT表示如果presentation引起应用程序阻塞,它将立刻返回D3DERR_WASSTILLDRAWING。
D3DPRESENT_LINEAR_CONTENT告诉设备presentation时源区域像素应该从线性颜色空间转化到sRGB颜色空间。
Presentation
当调用了Present后,backbuffer的容将会被复制到frontbuffer,videoscanout电流读取frontbuffer的像素把他们显示在monitor上。
如果D3DCAPS9:
:
DevCaps的D3DDEVCAPS_CANRENDERAFTERFLIP被设置,present发生以后设备将继续queue渲染命令,也就是在设备与CPU之间有更多的并发,当前帧渲染的时候,下一帧已经queue。
但是一个设备queue的帧数最多不能超过两帧。
#defineD3DDEVCAPS_CANRENDERAFTERFLIP0x000000800L
HRESULTPresent(constRECT*source_rect,constRECT*dest_rect,HWNDoverride_window,constRGNDATA*dirty_region);
Present对Swapchain的行为使用D3DPRESENT_PARAMETERS的SwapEffect定义的。
typedefenum_D3DSWAPEFFECT
{
D3DSWAPEFFECT_DISCARD=1,
D3DSWAPEFFECT_FLIP=2,
D3DSWAPEFFECT_COPY=3
}D3DSWAPEFFECT;在window模式下面,所有的swapeffec都是通过拷贝操作实现的。
使用最近时间间隔创建的swapchain并不能让monitor的垂直扫描与拷贝操作同步。
拷贝操作运行在在Videoscanout过程中,这样导致了artifacts,也称作图像tearing。
为了避免这种artifacts,我们需要同步videoscanout与拷贝操作,以便于当videobeam还停留在拷贝操作的目的地时,不能有拷贝操作发生。
如果显卡并不支持videobeam位置信息,拷贝操作将会立刻发生。
在exclusive模式下,presentation的频率是由D3DPRESENT_PARAMETERS的FullScreen_PresentationInterval指定的。
默认的presentationinverval对应adapter视频模式的刷新率。
如果dest_window不是空,dest_window客户端区域就是present的Target。
如果dest_window空而D3DPRESENT_PARAMETERS的hDeviceWindow不空,则hDeviceWindow就是present的Target。
如果两者都空,CreateDevice的focus_window参数将是present的target。
source和dest只能应用到拷贝操作方式,Flip和Discard这两个参数必须是空。
空值表示整个sourcesurface和目的surface。
dirty_region也只能使用在拷贝操作下。
LostDevicesandReset
TestCooperativelevel检查设备的状态,Reset重启设备。
HRESULTReset(D3DPRESENT_PARAMETERS*params);
HRESULTTestCooperativeLevel();VideoScanout
frontbuffer的容来自于Present。
GetDisplayMode返回了当前frontbuffer的显示模式。
应用程序不能直接访问frontbuffer,但是可以通过GetFrontBufferData返回一份frontbuffer的拷贝。
GetFrontBufferData的destination参数必须是一个存在的surface,它的维度等于adapter当前显示模式,并且像素格式是D3DFMT_A8R8G8B8。
在拷贝过程中数据将从adapter的显示模式格式转化成surface格式。
HRESULTGetDisplayMode(D3DDISPLAYMODE*value);
HRESULTGetFrontBufferData(IDirect3DSurface*destination);如果D3DCAPS:
:
Caps的D3DCAPS_READ_SCANLINE位被设置,设备将它的videoscanoutscanline和垂直blank状态。
GetRasterStatus将使用D3DRASTER_STATUS结构体返回videoscanout状态。
scanline成员指定了raterbeam的当前位置,0是最顶端的scanline。
如果是自下而上的垂直扫描,InVBlank成员将为TRUE。
HRESULTGetRasterStatus(D3DRASTER_STATUS*value);
typedefstruct_D3DRASTER_STATUS
{
BOOL InVBlank;
UINTScanline;
}D3DRASTER_STATUS;·Cursor
在exclusive模式下,Direct3D管理着cursor的显示。
在videoscanout的过程中硬件Cursor可能会取代cursor图像。
如果硬件cursor不可用,runtime会提供一个软件cursor对frontbuffer读,修改,写操作。
在window模式下,应用程序可能会使用GDIcursor或者Direct3Dcursor。
Direct3Dcursor能通过方法ShowCursor显示或者隐藏cursor。
ShowCursor并不返回HRESULT,而是cursor的上一个隐藏状态。
如果它是TRUE,cursor在调用ShowCursor之前是可见的。
BOOL ShowCursor(BOOLShow);
voidSetCursorPosition(UINTx,UINTy,DWORDflags);
HRESULTSetCursorProperties(UINThot_spot_x,UINThot_spot_y,IDirect3DSurface9*image);
cursor的位置是通过SetCursorPosition设定的,flags参数·GammaRamp
在exclusive模式下,应用cursor以后,在进行A/D转换之前将会对像素数据应用Gamma校正。
在窗口模式下,应用程序也能使用GDI来做Gamma校正。
如果D3DCAPS9:
:
Caps的D3DCAPS2_FULLSCREENGAMMA设置,设备将会支持exclusive的GammaRamp。
GetGammaRamp能读取GammaRamp的属性,它返回一个GammaRamp的结构体。
voidGetGammaRamp(D3DGAMMARAMP*value);
voidSetGammaRamp(DWORDFlags,constD3DGAMMARAMP*value);
typedefstruct_D3DGAMMARAMP
{
WORDred[256];
WORDgreen[256];
WORDblue[256];
}D3DGAMARAMP;Gammaramp属性通过SetGammaRamp进行设置,并且它能够立刻产生反应。
Flags参数表示设备是否使用ramp的calibration,它包括D3DSGR_NO_CALIBRATION和D3DSGR_CALIBRATE。
如果D3DCAPS9:
:
Caps2的D3DCAPS2_CANCALIBRATEGAMMA位设置,设备将能够给GammaRamp指定一个calibration。
下面例子显示了怎样计算rampvalues。
voidcompute_ramp(D3DGAMARAMP&ramp,floatgamma)
{
for(UINTi=0;i<256;i++)
{
constWORDval=static_cast<int>(65535*pow(i/255.f,1.f/gamma));
ramp.red[i]=val;
ramp.green[i]=val;
ramp.blue[i]=val;
}
}2DPixelCopies
如果我们申请可锁住的backbuffer,我们能锁住backbuffer的矩形区域,然后使用软件直接对它读写操作。
然而,backbuffersurface是videomemory的设备surface。
通过CPU访问videomemory将是一个昂贵的操作,我们应该避免。
但是存放系统存池或者scratch存池的图像surface能轻松的被CPU访问。
拷贝像素操作一般包括:
设备存到设备存,系统存到设备存,设备存到系统存。
StetchRect能有效的进行设备存之前的拷贝。
UpdateSurface和UpdateTexture一般都是将数据从系统存转移到设备存里面。
GetRenderTargetData用于从设备存将像素数据转移到系统存。
当你想要在设备资源直接拷贝数据时,你可以使用StretchRect。
当你需要更新默认存池的某个资源(如图像surface或者纹理资源),你可以使用UpdateSurface和updateTexture,不过managed池里的资源会自动更新,当它的系统存的数据变化时,它会自动更新到设备存里面去)。
PixelCopiesWithinDeviceMemory
StretchRect能够将一个矩形区域的像素从设备存的一个surface转移到另一个上面去。
这两个surface通常会是同样的D3DFORMAT。
在拷贝过程中,StretchRect也能执行有限的几颜色转换。
HRE
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Direct3D 应用 中的