一、预备知识
1、表面
表面就是Direct3D用于储存2D图像数据的一个像素矩阵。width和height以像素为单位,pitch以字节单位,用接口IDirect3DSurface来描述表面
LockRect:该方法用于获取指向表面存储区的指针,通过通过指针运算,可对每个像素进行读写操作;
UnlockRect:配对使用,调用lock必须unlock,解除对表面存储区的锁定;
GetDesc: 获取表面的描述信息,通过填充D3DSURFACE_DESC;
//Assume _surface is a pointer to an IDirect3DSurface9 interface //Assume a 32-bit pixel format for each pixel //Get the surface description. D3DSURFACE_DESC surfaceDesc; _surface->GetDesc(&surfaceDesc); //Get a pointer to the surface pixel data D3DLOCKED_RECT lockedRect; _surface->LockRect( &lockedRect, 0, 0); //Iterate through each pixel in the surface and set it to red DWORD *imageData = (DWORD *)lockedRect.pBits; for (int i = 0; i < surfaceDesc.height; ++i) { for (int j = 0; j < surfaceDesc.width; ++j) { int nIndex = i * lockedRect.pitch / 4 + j; imageData[nIndex] = 0xffff000; } } _surface->UnlockRect();
2、多重采样
多重采样(multisampling)一项用于平滑块状图像的技术
D3DMULTISAMPLE_TYPE:Defines the levels of full-scene multisampling that the device can apply.
typedef enum D3DMULTISAMPLE_TYPE { D3DMULTISAMPLE_NONE = 0, D3DMULTISAMPLE_NONMASKABLE = 1, 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 = 0xffffffff, } D3DMULTISAMPLE_TYPE, *LPD3DMULTISAMPLE_TYPE;
3、像素格式D3DFORMAT
创建表面或者纹理(texture)时需要指定像素格式
D3DFMT_R8G8B8 D3DFMT_X8R8G8B8 D3DFMT_A8R8G8B8 D3DFMT_A16B16G16R16F D3DFMT_A32B32G32R32F D3DFMT_DXT5
4、内存池
D3D RUTIME的内存类型,分为3种,VIDEO MEMORY(VM)、AGP MEMORY(AM)和SYSTEM MEMORY(SM)
VIDEO MEMORY(VM):VM就是位于显卡上的显存,CPU只能通过AGP或PCI-E总线访问到,读写速度都是非常慢的,
CPU连续写VM稍微快于读,因为CPU写VM时会在CACHE中分配32或64个字节(取决于CACHE LINE长度)
的写缓冲,当缓冲满后会一次性写入VM;
SYSTEM MEMORY(SM):SM就是系统内存,CPU读写都非常快,
因为SM是被CACHE到2级缓冲的,但GPU却不能直接访问到系统缓冲,所以创建在SM中的资源,
GPU是不能直接使用的;
AGP MEMORY(AM):AM是最麻烦的一个类型,AM实际也存在于系统内存中,
但这部分MEM不会被CPU CACHE,意味着CPU读写AM都会写来个CACHE MISSING然后才通过内存总线访问AM,
所以CPU读写AM相比SM会比较慢,但连续的写会稍微快于读,
原因就是CPU写AM使用了“write combining”,而且GPU可以直接通过AGP或PCI-E总线访问AM
所有D3D资源都创建在这3种内存之中,在创建资源时,我们可以指定如下存储标志,
D3DPOOL_DEFAULT、D3DPOOL_MANAGED、D3DPOOL_SYSTEMMEM和D3DPOOL_SCRATCH
D3DPOOL_DEFAULT:默认值,该类型的内存池指示Direct3D将资源放入最适合该资源类型极其适用方式的存储区中。该存储区可能是显存,AGP存储区或系统存储区。注意,调用IDirect3DDevice9::Reset之前,必须对默认内存池中的资源销毁或释放。上述函数调用后,还必须对内存池中的资源重新初始化。
D3DPOOL_MANAGE:放入该托管内存池中的资源交由Direct3D管理(即资源将根据需要被设备自动转移到显存或AGP存储区中)。此外,这些资源将在系统存储区中保留一个备份。这样,必要时,Direct3D会将这些资源自动更新到显存中。
D3DPOOL_SYSTEMMEM:指定将资源放入系统存储区中。
D3DPOOL_SCRATCH:指定将资源放入系统存储区中。不同于D3DPOOL_SYSTEMMEM,这些资源不受图形设备的制约。所以,设备无法访问该类型内存池中的资源。但这些资源之间可互相复制。
5、交换链和页面置换
Direct3D维护着一个表面集合,该集合通常由两到三个表面组成,称为交换链。该集合用接口IDirect3DSwapChain9来表示。
交换链和页面置换技术主要用于生成更加平滑的动画。
6、深度缓存
深度缓存是一个只含有特定像素的深度信息而不含图像数据的表面。深度缓存为最终绘制的图像中的每一个像素都保留了一个深度项。所以,当绘制的图像的分辨率为640X800,深度缓存中有640X800个深度项。
前面物体部分遮挡位于其后的物体,Direct3D为了判定某一个物体的哪些像素位于另一个物体之前。使用了一项称为深度缓存或z-缓存的技术。
深度缓存用于计算每个像素的深度值,并进行深度测试。深度测试的基本内容是依据深度值让处于同一位置的不同像素进行竞争。以选出应写入该位置的像素。距离摄像机最近的像素获胜,并被写入深度缓存的相应位置。
深度缓存的格式决定了深度测试的精度。24位的深度缓存要比16位的深度缓存精确得多。
D3DFMT_D32:32位深度缓存。
D3DFMT_D24S8:24位深度缓存,其中8位保留供模板缓存使用。
D3DFMT_D24X8:仅指定24位深度缓冲。
D3DFMT_X4S4:指定24位深度缓存,其中4位保留供模板缓存使用。
D3DFMT_D16:仅指定16位深度缓存。
二、Direct3D的初始化
1、获取接口IDirect3D9的指针
IDirect3D9* Direct3DCreate9( UINT SDKVersion );
Create an IDirect3D9 object and return an interface to it.
//step 1: Create the IDirect3D9 object IDirect3D9 d3d9; d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2、校验硬件顶点运算
//step 2: Check for hardware vp // HRESULT GetDeviceCaps( // [in] UINT Adapter, // [in] D3DDEVTYPE DeviceType, // [out] D3DCAPS9 *pCaps // ); // Adapter [in] // Type: UINT // Ordinal number that denotes the display adapter. D3DADAPTER_DEFAULT is always the primary display adapter. // DeviceType [in] // Type: D3DDEVTYPE // Member of the D3DDEVTYPE enumerated type. Denotes the device type. // pCaps [out] // Type: D3DCAPS9* // Pointer to a D3DCAPS9 structure to be filled with information describing the capabilities of the device. D3DCAPS9 caps; d3d9.GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps); int vp = 0; if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
//step 3: Fill out the D3DPRESENT_PARAMETERS structure. D3DPRESENT_PARAMETERS d3dpp; d3dpp.BackBufferWidth = nWidth; //后台缓冲中表面的宽度,单位为像素 d3dpp.BackBufferHeight = nHeight; //后台缓冲中表面的高度,单位为像素 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; //后台缓冲的像素格式 d3dpp.BackBufferCount = 1; //需要时用的后台缓存个数,通常为1 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; //后台缓存使用的多重采样类型 d3dpp.MultiSampleQuality = 0; //多重采样质量水平 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //D3DSWAPEFFECT枚举类型的一个成员,该类型指定了交换链中的缓冲的页面置换方式,D3DSWAPEFFECT_DISCARD时效果最高 d3dpp.hDeviceWindow = hWnd; //指定所以进行绘制的应用程序窗口 d3dpp.Windowed = bWindowed; //true:窗口模式 false:全屏模式 d3dpp.EnableAutoDepthStencil = true; //true:Dierct3D自动创建并维护深度缓存或者模板缓存 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; //深度缓存或者模板缓存的像素格式(D3DFMT_D24S8 24位深度,8位模板) d3dpp.Flags = 0; //附加特性 0无标记或D3DPRESENTFLAG集合中的一个成员 常用的2个 //D3DPRESENTFLAG_LOCKABLE_DEPTHBUFFER 指定可锁定后台缓存,可能会减低性能 //D3DPRESENTFLAG_DISCARD_DEPTHBUFFER 指定当下一个后台缓存提交时,哪个深度或者模板缓存将被丢弃。这样可以提升性能; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //刷新频率 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT集合中的一个成员, //D3DPRESENT_INTERVAL_IMMEDIATE 立即提交
4、创建IDirect3DDevice9接口
hResult = d3d9->CreateDevice( D3DADAPTER_DEFAULT, // primary adapter deviceType, // device type hWnd, // window associated with device vp, // vertex processing &d3dpp, // present parameters device); // return created device if(FAILED(hResult)) { // try again using a 16-bit depth buffer d3dpp.AutoDepthStencilFormat = D3DFMT_D16; hResult = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hWnd, vp, &d3dpp, device); if(FAILED(hResult)) { d3d9->Release(); // done with d3d9 object ::MessageBox(0, "CreateDevice() - FAILED", 0, 0); return false; } }
最后贴一下自己的成果,虽然基本是从龙书上copy下来 o(╯□╰)o
DX笔记之一---Direct3D基础