顶点缓存
一个顶点缓存是一块连续的存储了顶点数据的内存。
Length 分配给缓存的字节大小。假如想得到一个能存储3个顶点的顶点缓存,那么我们就要在顶点结构中设置这个参数为3 * sizeof ( Vertex ) 。
Usage 指定关于怎样使用缓存的额外信息,可以为0,也可为一下几个参数的一个或多个组合:
D3DUSAGE_DYNAMIC——设置这个参数可以使缓存是动态的。在下一页说明静态和动态缓存。
D3DUSAGE_POINTS——这个参数指定缓存存储原始点。原始点将在第14章粒子系统中介绍。这个参数仅仅用在顶点缓冲中。
D3DUSAGE_SOFTWAREPROCESSING——使用软件顶点处理。
D3DUSAGE_WRITEONLY——指定应用程序只能写缓存。它允许驱动程序分配最适合的内存地址作为写缓存。注意如果从创建好的这种缓存中读数据,将会返回错误信息。
FVF 存储在缓存中的顶点格式。
Pool 缓存放置在哪一个内存池中。
ppVertexBuffer 返回创建好的顶点缓存的指针。
pShareHandle 目前没有使用,一般传NULL。
访问顶点缓存
为了访问顶点缓存,我们需要得到一个指针,因此我们需要使用IDirect3DVertexBuffer9::Lock与IDirect3DVertexBuffer9 :: Unlock。
OffsetToLock 偏移量,以字节为单位,从缓存开始位置到锁定开始位置的距离。
SizeToLock 锁定的字节数。
Flags 标记描述怎样锁定内存。它可能是0 或者是下面参数中的1 个或多个的组合:
D3DLOCK_DISCARD——这个参数仅仅会在动态缓存时被使用。它指示硬件丢弃缓存并返回一个指向新分配的缓存的指针。这是很有用,因为当我们存取一个新分配的缓存时它允许硬件继续从丢弃的缓存渲染。这防止了硬件延迟。
D3DLOCK_NOO VERWRITE——这个参数仅仅会在动态缓存时被使用。它声明你将向缓存中添加数据。即,你不能向已经渲染的内存中写数据。这是有好处的因为他允许你在添加新数据到缓存的同时让硬件继续渲染。
D3DLOCK_READONLY——这个参数声明你锁定的缓存只能从中读取数据而不能写数据。这允许一些内在的优化。
投影(Projection)
视图坐标系的主要任务就是将3D 场景转化为2D 图像表示。这种从n 维转换成n-1 维的过程就叫做投影。
投影变换的实质就是定义可视体(视景体),并将可视体内的几何图形投影到投影窗口上去。
pOut 返回投影矩阵。
fovy 用弧度表示视野角度。
Aspect 宽高比,Width/Height。
zn 前裁剪面距离。
zf 后裁剪面距离。
渲染管线
把3D场景转换成2D图像显示在显示器上,这一系列必须完成的操作就叫做渲染管线。
其过程如下:
Local Space->World Space->View Space->Backface Culling->Lighting->Clipping->Projection
->Viewport Space->Rasterization
渲染管线中的许多级变换都是从一个坐标系到另一个坐标系的变换,可用IDirect3DDevice9::SetTranform来实现。
State 坐标系变换类型
pMatrix 变换矩阵
对于一个物体,通常在可视范围内背面是不可见的,那么背面拣选达到的效果则是拣选(删除)在可视范围内看不见的背面。
Direct3D 中默认顶点以顺时针方向(在观察坐标系中)形成的三角形为正面,以逆时针方向形成的三角形为背面,如果不想使用默认拣选状态可以通过IDirect3DDevice9::SetRenderState来实现。
State 当为D3DRS_FILLMODE时可以改变填充模型。
Value 填充模型
D3DFILL_POINT
D3DFILL_WIREFRAME
D3DFILL_SOLID
D3DFILL_FORCE_DWORD
绘制准备
以下准备皆为IDirect3DDevice9的函数
1.设置资源流
StreamNumber 确定我们的顶点缓存与哪一个资源流挂钩。由于此处不适用多重流,所以默认使用0号流。
pStreamData 一个指向我们想与流挂钩的那个顶点缓存的指针。
OffsetInBytes 相对流开始处的偏移量。以字节为单位,它指定被填入渲染管线的顶点数据
的开始位置。
Stride 我们在顶点缓存中操作的每个部分(每个顶点)的流的字节大小。
2.设置顶点格式
FVF 指定后面用来绘图调用的顶点的顶点格式。
3.设置索引缓存
假如我们使用了索引缓存,我们必须设置后面要用于绘制操作的索引缓存。
pIndexData 传递一个索引缓存指针的拷贝。
绘制图元(不使用索引信息)
PrimitiveType 图元类型,详情查看SDK手册。
StartVertex 索引到在顶点流中的一个元素。设置渲染顶点中的开始点。这个参数给予我
们一定的机动性,可以绘制一个顶点缓存中的某部分。
PrimitiveCount 绘制图元个数。
所有绘制方法都必须在IDirect3DDevice9::BeginScene和IDirect3DDevice9::EndScene
方法之间被调用
- #include <d3dx9.h>
- #include <string.h>
- #include <Windows.h>
- #define WINDOWNAME TEXT("D3DGameFrame")
- #define WINDOWCLASS TEXT("The GameFrame of Dull")
- #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
- #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
- const int Width = 640;
- const int Height = 480;
- HWND mainWindowHandle = NULL;
- HINSTANCE hinstanceApp = NULL;
- bool ESC = true;
- IDirect3DDevice9* Device = NULL;
- IDirect3D9* d3d9 = NULL;
- HRESULT hr = NULL;
- IDirect3DVertexBuffer9* Triangle = NULL;
- struct Vertex
- {
- float x,y,z;
- };
- #define D3DFVF (D3DFVF_XYZ)
- LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT ps;
- HDC hdc;
- switch( msg )
- {
- case WM_PAINT:
- {
- hdc = BeginPaint(hWnd,&ps);
- EndPaint(hWnd,&ps);
- }
- break;
- case WM_DESTROY:
- {
- ::PostQuitMessage(0);
- }
- break;
- }
- return ::DefWindowProc(hWnd, msg, wParam, lParam);
- }
- int GameInit(void *parms = NULL, int num_parms = 0)
- {
- ESC = false;
- Device->CreateVertexBuffer(3*sizeof(Vertex),D3DUSAGE_WRITEONLY,D3DFVF,D3DPOOL_MANAGED,&Triangle,NULL);
- Vertex vertices[] =
- {
- {-1.0f, 0.0f, 2.0f},
- {0.0f, 1.0f, 2.0f},
- {1.0f, 0.0f, 2.0f}
- };
- void* pVertices;
- Triangle->Lock(0,0,(void **)&pVertices,0);
- memcpy(pVertices,vertices,sizeof(vertices));
- Triangle->Unlock();
- D3DXMATRIX proj;
- D3DXMatrixPerspectiveFovLH(&proj,D3DX_PI * 0.5f,(float)Width/(float)Height,1.0f,1000.0f);
- Device->SetTransform(D3DTS_PROJECTION,&proj);
- Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
- return 1;
- }
- int GameMain(void *parms = NULL, int num_parms = 0)
- {
- if(ESC) return 0;
- Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
- Device->BeginScene();
- Device->SetStreamSource(0, Triangle, 0, sizeof(Vertex));
- Device->SetFVF(D3DFVF);
- // Draw one triangle.
- Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
- Device->EndScene();
- Device->Present(NULL, NULL, NULL, NULL);
- if (KEYDOWN(VK_ESCAPE))
- {
- ESC = true;
- SendMessage(mainWindowHandle,WM_CLOSE,0,0);
- }
- return 1;
- }
- int GameShutdown(void *parms = NULL, int num_parms = 0)
- {
- if(NULL != Triangle)
- {
- Triangle->Release();
- Triangle = NULL;
- }
- if( NULL != d3d9)
- {
- d3d9->Release();
- d3d9 = NULL;
- }
- if( NULL != Device)
- {
- Device->Release();
- Device = NULL;
- }
- return 1;
- }
- int WINAPI WinMain(HINSTANCE hInstance,
- HINSTANCE prevInstance,
- PSTR cmdLine,
- int showCmd)
- {
- HWND hWnd;
- MSG msg;
- WNDCLASS wndClass;
- wndClass.style = CS_HREDRAW | CS_VREDRAW;
- wndClass.lpfnWndProc = (WNDPROC)WndProc;
- wndClass.cbClsExtra = NULL;
- wndClass.cbWndExtra = NULL;
- wndClass.hInstance = hInstance;
- wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
- wndClass.hCursor = LoadCursor(0, IDC_ARROW);
- wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
- wndClass.lpszMenuName = NULL;
- wndClass.lpszClassName = WINDOWCLASS;
- if( !RegisterClass(&wndClass) )
- {
- ::MessageBox(NULL, TEXT("RegisterClass() - FAILED"), NULL, NULL);
- return false;
- }
- hWnd = CreateWindow(WINDOWCLASS,
- WINDOWNAME,
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- 0, 0,
- Width,
- Height,
- NULL,
- NULL,
- hInstance,
- NULL);
- if( !hWnd )
- {
- ::MessageBox(NULL,TEXT( "CreateWindow() - FAILED"), NULL, NULL);
- return false;
- }
- hinstanceApp = hInstance;
- mainWindowHandle = hWnd;
- ::ShowWindow(hWnd, SW_SHOW);
- ::UpdateWindow(hWnd);
- //1: 获得一个IDirect3D9接口指针。
- d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
- /*Direct3DCreate9 的唯一一个参数总是D3D_SDK_VERSION,
- 这可以保证应用程序通过正确的头文件被生成。如果函数调用失败,
- 那么它将返回一个空指针。*/
- if( !d3d9 )
- {
- ::MessageBox(NULL, TEXT("Direct3DCreate9() - FAILED"), NULL, NULL);
- return false;
- }
- //2:检查设备能力(D3DCAPS9),搞清楚主显卡是否支持硬件顶点处理。.
- //当我们创建一个IDirect3DDevice9对象来表示主显示设备时,必须要设定其顶点处理的类型。
- D3DCAPS9 caps;
- d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);// 填充主显示设备的能力(D3DCAPS9结构)
- int vp = 0;
- if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
- vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
- else
- vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
- //3: 初始化一个D3DPRESENT _PARAMETERS结构实例。
- 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 = true;
- d3dpp.EnableAutoDepthStencil = true;
- d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
- d3dpp.Flags = 0;
- d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
- d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
- //4:创建一个基于已经初始化好的D3DPRESENT _PARAMETERS结构的IDirect3DDevice9对象。
- hr = d3d9->CreateDevice(//Creates a device to represent the display adapter.
- D3DADAPTER_DEFAULT, // primary adapter
- D3DDEVTYPE_HAL, // device type
- hWnd, // window associated with device
- vp, // vertex processing
- &d3dpp, // present parameters
- &Device); // return created device
- if( FAILED(hr) )
- {
- d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
- hr = d3d9->CreateDevice(
- D3DADAPTER_DEFAULT,
- D3DDEVTYPE_HAL,
- hWnd,
- vp,
- &d3dpp,
- &Device);
- if( FAILED(hr) )
- {
- d3d9->Release(); //释放d3d9
- ::MessageBox(NULL, TEXT("CreateDevice() - FAILED"), NULL, NULL);
- return false;
- }
- }
- GameInit();
- while(TRUE)
- {
- if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
- {
- if (msg.message == WM_QUIT)
- break;
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- GameMain();
- }
- GameShutdown();
- return 0;
- }
转载于:https://blog.51cto.com/heweiyou/1133515