1.表面(Surface)
typedef struct D3DSURFACE_DESC {
D3DFORMAT Format;
D3DRESOURCETYPE Type;
DWORD Usage;
D3DPOOL Pool;
D3DMULTISAMPLE_TYPE MultiSampleType;
DWORD MultiSampleQuality;
UINT Width;
UINT Height;
} D3DSURFACE_DESC, *LPD3DSURFACE_DESC;
表面是像素点阵,在d3d中存储2d图形数据。Surface中每一行的数据不纯是像素颜色,还会有一个缓冲区,Pitch就是一整行的数据的总长度
//header:D3D9Types.h
typedef struct D3DLOCKED_RECT {
INT Pitch;//Number of bytes in one row of the surface.
void *pBits;//pBits will be appropriately offset from the start of the surface.
} D3DLOCKED_RECT, *LPD3DLOCKED_RECT;
接口:
IDirect3DSurface9
Method | Description |
Retrieves a description of the surface. | |
Locks a rectangle on a surface. | |
Unlocks a rectangle on a surface. |
LockRect:通过这个方法可以获得一个指向表面内存的指针,从而进行读写操作
//header: D3D9.h
HRESULT LockRect(
[out] D3DLOCKED_RECT *pLockedRect,
[in] const RECT *pRect,
[in] DWORD Flags
);
UnlockRect :通过这个方法来解锁
GetDesc :通过填充D3DLOCKED_RECT结构来返回表面的信息。
HRESULT GetDesc(
[out] D3DSURFACE_DESC *pDesc
);
1.1 像素格式
由D3DFORMAT来决定
typedef enum _D3DFORMAT {
... (values)
} D3DFORMAT
1.3 交换链和页面切换,当Front Buffer的内容显示器还没有显示时,就先render to Back Buffer,当front Buffer 的内容显示出来后,front Buffer 就相当于原来的back buffer,back buffer就变为原来的front buffer这个过程称为presenting
1.Render to back buffer
2.Present to back buffer
3.Goto(1)
1.4 设备能力 :通过D3DCAPS9这个结构来判断。
2.初始化directx3d
1.获得一个IDirect3D9接口指针。这个接口用于获得物理设备的信息和创建一个IDirect3DDevice9接口,它是一个代表我们显示3D图形的物理设备的C++对象。
2.检查设备能力(D3DCAPS9),搞清楚主显卡是否支持硬件顶点处理。我们需要知道假如它能支持,我们就能创建IDirect3DDevice9接口。
3.初始化一个D3DPRESENT_PARAMETERS结构实例,这个结构包含了许多数据成员允许我们指定将要创建的IDirect3DDevice9接口的特性。
4.创建一个基于已经初始化好的D3DPRESENT_PARAMETERS结构的IDirect3DDevice9对象。它是一个代表我们显示3D图形的物理设备的C++对象。
HRESULT CreateDevice(
[in] UINT Adapter,//指定要对象显示的物理显示设备
[in] D3DDEVTYPE DeviceType,//设备类型
[in] HWND hFocusWindow,//窗口句柄
[in] DWORD BehaviorFlags,//D3DCREATE_HARDWARE_VERTEXPROCESSING或是D3DCREATE_SOFTWARE_VERTEXPROCESSING
[in, out] D3DPRESENT_PARAMETERS *pPresentationParameters,//要填充的D3DPRESENT_PARAMETERS实例
[out, retval] IDirect3DDevice9 **ppReturnedDeviceInterface//返回创建的设备
);
//清除
//IDirect3DDevice9::Clear Method
//Clears one or more surfaces such as a render target, multiple render targets, a stencil buffer, and a depth buffer.
HRESULT Clear(
//清除表面的个数
[in] DWORD Count,
//将要清除的矩形数组,这样清除屏幕的某个部分。
[in] const D3DRECT *pRects,
//指定在哪些表面上执行清除表面的操作
//D3DCLEAR_STENCIL Clear the stencil buffer.
//D3DCLEAR_TARGET 目标表面,通常为后备表面
//D3DCLEAR_ZBUFFER Clear the depth buffer.
[in] DWORD Flags,
//用什么颜色填充清除的表面
[in] D3DCOLOR Color,
//设置深度缓冲的值
[in] float Z,
//设置模板缓冲的值
[in] DWORD Stencil
);
一般屏幕被填充后要调用present方法进行后备表面的交换。
if( Device ) // Only use Device methods if we have a valid device.
{
// Instruct the device to set each pixel on the back buffer black -
// D3DCLEAR_TARGET: 0x00000000 (black) - and to set each pixel on
// the depth buffer to a value of 1.0 - D3DCLEAR_ZBUFFER: 1.0f.
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
// Swap the back and front buffers.
Device->Present(0, 0, 0, 0);
}
初始化代码:
1.
//
#include"dxdhear.h"
// Globals
//
IDirect3DDevice9* Device = 0;
//
// Framework Functions
//
bool Setup()
{
// Nothing to setup in this sample.
return true;
}
void Cleanup()
{
// Nothing to cleanup in this sample.
}
bool Display(float timeDelta)
{
if( Device ) // Only use Device methods if we have a valid device.
{
// Instruct the device to set each pixel on the back buffer black -
// D3DCLEAR_TARGET: 0x00000000 (black) - and to set each pixel on
// the depth buffer to a value of 1.0 - D3DCLEAR_ZBUFFER: 1.0f.
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
// Swap the back and front buffers.
Device->Present(0, 0, 0, 0);
}
return true;
}
//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
case WM_KEYDOWN:
if( wParam == VK_ESCAPE )
::DestroyWindow(hwnd);
break;
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
HINSTANCE prevInstance,
PSTR cmdLine,
int showCmd)
{
if(!d3d::InitD3D(hinstance,
640, 480, true, D3DDEVTYPE_HAL, &Device))
{
::MessageBox(0, "InitD3D() - FAILED", 0, 0);
return 0;
}
if(!Setup())
{
::MessageBox(0, "Setup() - FAILED", 0, 0);
return 0;
}
d3d::MsgLoop( Display );
Cleanup();
Device->Release();
return 0;
}
2.
#include"dxdhear.h"
bool d3d::InitD3D(
HINSTANCE hInstance,
int width, int height,
bool windowed,
D3DDEVTYPE deviceType,
IDirect3DDevice9** device)
{
//
// Create the main application window.
//
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)d3d::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = "Direct3D9App";
if( !RegisterClass(&wc) )
{
::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
return false;
}
HWND hwnd = 0;
hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App",
WS_EX_TOPMOST,
0, 0, width, height,
0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);
if( !hwnd )
{
::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
return false;
}
::ShowWindow(hwnd, SW_SHOW);
::UpdateWindow(hwnd);
//
// Init D3D:
//
HRESULT hr = 0;
// Step 1: Create the IDirect3D9 object.
IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if( !d3d9 )
{
::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
return false;
}
// Step 2: Check for hardware vp.
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 = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = windowed;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// Step 4: Create the device.
hr = 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(hr) )
{
// try again using a 16-bit depth buffer
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
deviceType,
hwnd,
vp,
&d3dpp,
device);
if( FAILED(hr) )
{
d3d9->Release(); // done with d3d9 object
::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
return false;
}
}
d3d9->Release(); // done with d3d9 object
return true;
}
int d3d::MsgLoop( bool (*ptr_display)(float timeDelta) )
{
MSG msg;
::ZeroMemory(&msg, sizeof(MSG));
static float lastTime = (float)timeGetTime();
while(msg.message != WM_QUIT)
{
if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else
{
float currTime = (float)timeGetTime();
float timeDelta = (currTime - lastTime)*0.001f;
ptr_display(timeDelta);
lastTime = currTime;
}
}
return msg.wParam;
}
3.
#ifndef dxdhear_H_
#define dxdhear_H_
#include<d3dx9.h>
#include<string>
#include<comdef.h>
namespace d3d
{
bool InitD3D
(
HINSTANCE hInstance,//[in]typedef HANDLE HINSTANCE;Handle to an instance
int width,//[in]
int height,//[in]
bool windowed,//[in] full screen(false) or windowed(true)
D3DDEVTYPE deviceType,//[in]设备类型
IDirect3DDevice9** device//[out]创建的设备
);
int MsgLoop(bool (*ptr_display)(float timeDelta));//消息循环
//回调函数
/*
凡是由你设计却由windows系统呼叫的函数,统称为callback函数。
某些API函数要求以callback作为你参数之一。如SetTimer,LineDDA,EnumObjects。
回调函数是由开发者按照一定的原形进行定义的函数(每个回调函数都必须遵循这个原则来设计)
回调函数必须有关键词CALLBACK;
回调函数本身必须是全局函数或者静态函数,不可定义为某个特定的类的成员函数
回调函数并不由开发者直接调用执行(只是使用系统接口API函数作为起点)
回调函数通常作为参数传递给系统API,由该API来调用
回调函数可能被系统API调用一次,也可能被循环调用多次
LRESULT:Signed result of message processing. typedef LONG_PTR LRESULT;
HWND:Handle to a window.
WPARAM:Message parameter,typedef UINT_PTR WPARAM
LPARAM:Message parameter,typedef LONG_PTR LPARAM
*/
LRESULT CALLBACK WndProc(
HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam
);
template<class T>
void Release(T t)
{
if(t)
{
t->Release();
t=0;
}
}
template<class T>
void Delete(T t)
{
if(t)
{
delete t;
t=0;
}
}
}
#endif