今天我们来学习下Direct3D的顶点和顶点缓存,首先我们需要在场景中绘制一些物体,物体都是由多个三角形组成,每一个三角形由三个顶点组成,我们来看下面一个NPC的模型

左图:正常的模型                      右图:看的出模型是有多个三角形组成

现在我们知道了一个模型最小单位是一个顶点. 如果我们需要自己绘制物体,就要学习下Direct3D如何创建顶点. 顶点在Direct3D中叫顶点缓存(VertexBuffer),顶点缓存保存了顶点的一些数据空间,比如位置,颜色,法向量等等.

定制顶点缓存(FVF)格式:

刚刚说了顶点有很多信息,有的时候我们只需要一些信息,根据自己需要定制顶点缓存

//坐标位置和颜色的顶点
struct CUSTOMVERTEX1
{
float x,y,z;
DWORD color;
};
//等下创建顶点缓存,要传入这个宏,Direct3D才知道我们用的是那种顶点
#define D3DFVF_CUSTOMVERTEX1 (D3DFVF_XYZRHW | D3DFVF_DIFFUSE); //坐标位置和法向量的顶点
struct CUSTOMVERTEX2
{
float x,y,z;
float nx,ny,nz; //法向量
float u,v; //纹理坐标
};
#define D3DFVF_CUSTOMVERTEX2 (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);

FVF常用格式

D3DFVF_XYZ 未经过坐标变换的顶点坐标值,不可以和D3DFVF_XYZRHW一起使用
D3DFVF_XYZRHW 经过坐标变换的顶点坐标值,不可以和D3DFVF_XYZ,D3DFVF_NORMAL一起使用
D3DFVF_XYZB1~5 顶点混合的权重值
D3DFVF_NORMAL 法线向量的数值
D3DFVF_DIFFUSE 漫反射的颜色值
D3DFVF_SPECULAR 镜面反射的数值
D3DFVF_TEX1~8 1~8纹理坐标的信息(纹理=贴图)

顶点格式的顺序原则:

顶点坐标位置->RHW值->顶点混合权重值->顶点法向量->漫反射颜色值->镜面反射颜色值->纹理坐标信息


 

创建顶点缓存:

LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;        //顶点缓存对象
Device->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX1), 0 , D3DFVF_CUSTOMVERTEX1 , D3DPOOL_DEFAULT,&g_pVertexBuffer,NULL);

 

访问顶点缓存:

//创建顶点缓存
if(FAILED(g_pd3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&g_pVertexBuffer,NULL)))
{
return E_FAIL;
} //创建顶点数据
CUSTOMVERTEX vertices [] =
{
{ 100.0f, 100.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0, 0,0), },
{ 300.0f, 100.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), },
{ 300.0f, 300.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0,0,0), },
}; //填充顶点缓冲区
VOID *pVertices;
if(FAILED(g_pVertexBuffer->Lock(0,sizeof(vertices),(void**)&pVertices,0))) //加锁
{
return E_FAIL;
} memcpy(pVertices,vertices,sizeof(vertices)); //把顶点数据保存到顶点缓存中
g_pVertexBuffer->Unlock(); //解锁 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,false);

 

图形的绘制: 上面我们已经准备好了顶点数据,现在只需要把顶点绘制到屏幕上就可以啦,绘制图形都是的BeginScene() 和 EndScene()函数中间,接下来我们需要依次调用以下函数,、

1. IDirect3DDevice9::SetStreamSource() 设置顶点源

2. IDirect3DDevice9::SetFVF() 设置灵活顶点格式

3. IDirect3DDevice9::DrawPrimitive() 绘制图形

g_pd3dDevice->SetStreamSource(0,g_pVertexBuffer,0,sizeof(CUSTOMVERTEX));        //设置绘制的顶点数据
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); //设置灵活顶点格式
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2); //绘制两个三角形

效果图:

 

全部代码:

#include <d3d9.h>
#include <d3dx9.h>
#include <tchar.h> #pragma comment(lib,"winmm.lib")
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib") #define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE L"盘子脸的程序"
#define SAFE_RELEASE(p) { if(p) { (p) -> Release();(p)=NULL;} } struct CUSTOMVERTEX
{
float x,y,z,rhw;
DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) //声明变量
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
ID3DXFont* g_pFont = NULL;
float g_FPS = 0.0f;
wchar_t g_strFPS[50]; //包含帧速率的字符
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; //顶点缓冲区对象 //全局函数声明部分
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
HRESULT Direct3DInit(HWND hwnd);
HRESULT ObjectsInit(HWND hwnd);
VOID Direct3DRender(HWND hwnd);
VOID Direct3DCleanUp(); //主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
//设置一个完整的窗口类,没有设置图标
WNDCLASSEX wndClass = {0};
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW; //设置窗口样式
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = L"GameDevelop"; //注册窗口类
if(!RegisterClassEx(&wndClass))
{
return -1;
} //正式创建窗口
HWND hwnd = CreateWindow(L"GameDevelop",WINDOW_TITLE,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,WINDOW_WIDTH,
WINDOW_HEIGHT,NULL,NULL,hInstance,NULL); //初始化Direct3D资源
if(!(S_OK == Direct3DInit(hwnd)))
{
MessageBox(hwnd,_T("初始化Direct3D失败"),_T("盘子脸的消息窗口"),0);
} MoveWindow(hwnd,250,80,WINDOW_WIDTH,WINDOW_HEIGHT,true);
ShowWindow(hwnd,nShowCmd);
UpdateWindow(hwnd); //消息循环过程
MSG msg = {0};
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}else
{
Direct3DRender(hwnd);
}
} //窗口类的注销
UnregisterClass(L"GameDevelop",wndClass.hInstance); return 0;
} //消息处理函数
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
Direct3DRender(hwnd);
ValidateRect(hwnd,NULL);
break;
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
Direct3DCleanUp(); //失败Direct3D资源
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
} return 0;
} HRESULT Direct3DInit(HWND hwnd)
{
//创建Direct3D接口对象
LPDIRECT3D9 pD3D = NULL;
if(NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
{
return E_FAIL;
} //获取硬件消息
D3DCAPS9 caps;
int vp = 0;
if(FAILED(pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps)))
{
return E_FAIL;
} if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
//支出硬件顶点运算
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else
{
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
} //填充Direct3Dpresent参数
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.BackBufferWidth = WINDOW_WIDTH;
d3dpp.BackBufferHeight = WINDOW_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 = 0;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //创建Direct3D设备接口
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hwnd,vp,&d3dpp,&g_pd3dDevice)))
{
return E_FAIL;
} SAFE_RELEASE(pD3D); if(!(S_OK == ObjectsInit(hwnd)))
{
return E_FAIL;
} return S_OK;
} HRESULT ObjectsInit(HWND hwnd)
{
//创建字体
if(FAILED(D3DXCreateFont(g_pd3dDevice,36,0,0,1,false,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,DEFAULT_QUALITY,0,_T("微软雅黑"),&g_pFont)))
{
return E_FAIL;
} //创建顶点缓存
if(FAILED(g_pd3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&g_pVertexBuffer,NULL)))
{
return E_FAIL;
} //创建顶点数据
CUSTOMVERTEX vertices [] =
{
{ 100.0f, 100.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0, 0,0), },
{ 300.0f, 100.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), },
{ 300.0f, 300.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0,0,0), },
}; //填充顶点缓冲区
VOID *pVertices;
if(FAILED(g_pVertexBuffer->Lock(0,sizeof(vertices),(void**)&pVertices,0))) //加锁
{
return E_FAIL;
} memcpy(pVertices,vertices,sizeof(vertices)); //把顶点数据保存到顶点缓存中
g_pVertexBuffer->Unlock(); //解锁 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,false);
return S_OK; } void Direct3DRender(HWND hwnd)
{
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); //定义一个矩形
RECT formatRect;
GetClientRect(hwnd,&formatRect); g_pd3dDevice->BeginScene();
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD); //绘制图形
g_pd3dDevice->SetStreamSource(0,g_pVertexBuffer,0,sizeof(CUSTOMVERTEX)); //设置绘制的顶点数据
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); //设置灵活顶点格式
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2); //绘制两个三角形 //绘制文本信息
g_pFont->DrawTextW(NULL,L"盘子脸",3,&formatRect,DT_TOP | DT_RIGHT , D3DCOLOR_XRGB(255,39,136)); g_pd3dDevice->EndScene();
g_pd3dDevice->Present(NULL,NULL,NULL,NULL);
} void Direct3DCleanUp()
{
SAFE_RELEASE(g_pVertexBuffer);
SAFE_RELEASE(g_pFont);
SAFE_RELEASE(g_pd3dDevice);
}

Direct3D 顶点缓存的更多相关文章

  1. 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记5——Direct3D中的顶点缓存和索引缓存

    第12章 Direct3D绘制基础 1. 顶点缓存 计算机所描绘的3D图形是通过多边形网格来构成的,网网格勾勒出轮廓,然后在网格轮廓的表面上贴上相应的图片,这样就构成了一个3D模型.三角形网格是构建物 ...

  2. Direct3D 索引缓存

    小学的时候我们知道3个顶点组成一个三角形,那么四个顶点我们会说有4个三角形.这就是一个顶点同时参与了四次绘制三角形的结果. 在程序中也一样,比如我们绘制的两个三角形是挨着一起的,总有几个顶点是重合的. ...

  3. 顶点缓存对象(VBO)

    创建VBO 绘制VBO 更新VBO 实例 GL_ARB_vertex_buffer_object扩展致力于提供顶点数组与显示列表的优势来提升OpenGL效率,同时避免它们实现上的不足.顶点缓存对象(V ...

  4. NeHe OpenGL教程 第四十五课:顶点缓存

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. OpenGL 顶点缓存对象

    顶点缓存对象(Vertex Buffer Object,简称 VBO),允许开发者根据情况把顶点数据放到显存中. 如果不用 VBO,用 glVertexPointer / glNormalPointe ...

  6. 顶点缓存对象(VBO)【转】

    http://www.cnblogs.com/hefee/p/3824300.html 顶点缓存对象(VBO) 创建VBO 绘制VBO 更新VBO 实例 GL_ARB_vertex_buffer_ob ...

  7. DX9 顶点缓存案例

    // @time 2012.3.5 // @author jadeshu //包含头文件 #include <Windows.h> #include <d3d9.h> #pra ...

  8. Windows游戏编程之从零开始d

    Windows游戏编程之从零开始d I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来 ...

  9. 最简单的视音频播放示例4:Direct3D播放RGB(通过Texture)

    本文接着上一篇文章继续记录Direct3D(简称D3D)播放视频的技术.上一篇文章中已经记录了使用Direct3D中的Surface渲染视频的技术.本文记录一种稍微复杂但是更加灵活的渲染视频的方式:使 ...

随机推荐

  1. iOS开发:深入理解GCD 第一篇

    最近把其他书籍都放下了,主要是在研究GCD.如果是为了工作,以我以前所学的GCD.NSOperation等知识已经足够用了,但学习并不仅仅知识满足于用它,要知其然.并且知其所以然,这样才可以不断的提高 ...

  2. 图片实时预览JSP加js

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. NetAnalyzer笔记 之 八 NetAnalyzer2016使用方法(2)

    [创建时间:2016-05-06 22:07:00] NetAnalyzer下载地址 在写本篇的时候,NetAnalyzer 3.1版本已经发布,所以本篇就以最新版本的为例继续使用,并且顺带说明一下, ...

  4. 【leetcode】Merge k Sorted Lists(按大小顺序连接k个链表)

    题目:Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity ...

  5. cp命令的编写——浅谈系统调用

    摘要:linux中cp命令的实现,通过这个程序,我们需要了解系统调用耗费时间的方面,同时学会系统调用的错误处理机制. 本文来源:http://blog.csdn.net/trochiluses/art ...

  6. 查看哪些ip破解你ssh密码以及次数

    在互联网中,总有一些无聊的人,每天不断的猜解别人服务器的密码!作为linux服务器的管理员,我们应该了解哪些IP经常不断地扫描我们的SSH端口以尝试暴力破解,下面我们用一条命令简单列出哪些IP破解你S ...

  7. Android-Context的IO功能

    如何将应用数据保存到本地文件?如何从本地文件加载数据到应用中?我实现的步骤是: 应用(java数据)<--org.json-->JSONString<--Context.IO--&g ...

  8. 转载 Silverlight实用窍门系列:1.Silverlight读取外部XML加载配置---(使用WebClient读取XAP包同目录下的XML文件))

    转载:程兴亮文章,地址;http://www.cnblogs.com/chengxingliang/archive/2011/02/07/1949579.html 使用WebClient读取XAP包同 ...

  9. ssh maven 搭建

    数据库建表脚本不带,是很简单的一个表,把数据库环境搭建起来即可. 1.项目结构(Eclipse) 2.pom.xml <project xmlns="http://maven.apac ...

  10. hdu5338 ZZX and Permutations(贪心、线段树)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud ZZX and Permutations Time Limit: 6000/300 ...