• [D3D] DirectX SDK 2006学习笔记2——顶点缓冲


    来源:http://www.cnblogs.com/fence/archive/2010/03/12/1683918.html

      D3D9以一种比较易于理解的方式让程序员来组织游戏画面,这种方式就是顶点缓冲。程序员可以自己定义一组记录多 边形定点颜色,纹理位置等的数组,让D3D9去自动生成多边形内部每个像素的信息。为了和以后的vertex shader相区别,我们现在谈论的都是固定功能的顶点处理( Fixed-Function )。
      上面一段话似乎有点晦涩,让我们首先来看看这些术语的定义吧:
    • 顶点缓冲Vertex Buffer:由用户定义的,包含顶点信息的数组。

      首先我们来学习一下Vertex Buffer的技术。我喜欢先看代码再讲理论,否则看了理论也找不到北。

      下面就是一个自定义的顶点缓冲的结构
    struct CUSTOMVERTEX
    {
    FLOATx, y, z, rhw;
    // The transformed position for the vertex
    DWORDcolor; // The vertex color
    };

      其中,x, y, z是顶点在3维空间的最终位置,rhw是3维矩阵的倒数(不明白的话找本图形学的书研究一下),color自然就是顶点的颜色了。由于这个结构是自定义的,所以我们需要告诉D3D应该如何识别这个结构,这就需要我们定义一个常量了:
    // Our custom FVF, which describes our custom vertex structure
    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

       这个D3DFVF_CUSTOMVERTEX就是用来告诉D3D上面那个CUSTOMVERTEX结构是如何组织的:首先是 D3DFVF_XYZRHW,即顶点在3维坐标系的最终位置,D3DFVF_DIFFUSE是色彩模式,告诉D3D紧接着D3DFVF_XYZRHW信息 的是顶点的色彩信息,并且这种色彩信息是漫反射模式的。类似的标志可以学习DirectX SDK文档(搜索D3DFVF),这里就不再赘述。
      上面所提到的顶点缓冲定义方式就是为大家熟知Flexible Vertex Format,简称FVF,是不是有点眼熟呢。
      下面是Direct3D游戏编程入门一书中对复杂的FVF举的一个例子,供参考
    typedef struct SObjVertex
    {
    FLOATx, y, z;
    // position
    FLOATnx, ny, nz; // normal
    DWORDdiffuse; // diffuse color
    DWORDspecular; // specular color
    FLOATtu, tv; // first pair of texture coordinates
    FLOATtu2, tv2, tw2; // second pair of texture coordinates
    FLOATtu3, tv3; // third pair of texture coordinates
    FLOATtu4, tv4; // fourth pair of texture coordinates
    } SObjVertex;

    const DWORD gSObjVertexFVF = (D3DFVF_XYZ |
    D3DFVF_DIFFUSE
    |
    D3DFVF_SPECULAR
    |
    D3DFVF_NORMAL |
    D3DFVF_TEX4 |
    D3DFVF_TEXCOORDSIZE2(0) |
    D3DFVF_TEXCOORDSIZE3(1) |
    D3DFVF_TEXCOORDSIZE2(
    2) |
    D3DFVF_TEXCOORDSIZE2(
    3) );

      看完了FVF顶点格式的定义,就可以看它是如何使用的。使用方法非常简单,在OnCreateDevice中添加创建和初始化代码,在OnFrameRender中添加渲染代码就可以了,具体如下:
    LPDIRECT3DVERTEXBUFFER9g_pVB = NULL; // Buffer to hold vertices
    HRESULTCALLBACKOnCreateDevice( IDirect3DDevice9* pd3dDevice, constD3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
    {
    // Initialize three vertices for rendering a triangle
    CUSTOMVERTEX vertices[] =
    {
    // x, y, z, rhw, color
    { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, },
    {
    250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
    {
    50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
    };
    if( FAILED( pd3dDevice->CreateVertexBuffer(
    3*sizeof(CUSTOMVERTEX),
    0, D3DFVF_CUSTOMVERTEX,
    D3DPOOL_MANAGED,
    &g_pVB, NULL ) ) )
    {
    return E_FAIL;
    }
    // Now we fill the vertex buffer. To do this, we need to Lock()
    // the VB togain access to the vertices. This mechanism is
    // required becuase vertexbuffers may be in device memory.
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
    returnE_FAIL;
    memcpy( pVertices, vertices,
    sizeof(vertices) );
    g_pVB
    ->Unlock();
    }

       为了统一和强调精度,D3D采用了float作为其主要的数值类型。上面的程序调用了CreateVertexBuffer和 LPDIRECT3DVERTEXBUFFER9-> Lock和 Unlock函数。另外需要在OnFrameRender中的BeginScene和EndScene中调用如下代码
    pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
    pd3dDevice
    ->SetFVF( D3DFVF_CUSTOMVERTEX );
    pd3dDevice
    ->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

      其中SetStreamSource函数第一个参数StreamNumber用来设定使用哪条数据流,这个数据流的最大值根据显卡硬件的不同而不同,现在好的显卡可以支持8条或者16条数据流。SetFVF函数用来把我们自定义的顶点缓冲布局常量传递给D3DDrawPrimitive函数用来告诉D3D以那种图元绘制这个图形。其中图元这个概念很重要,它是D3D世界中最基本的单位,分为点列表,线列表,线带,三角形列表,三角形带,三角扇形六中,在D3D中的具体定义如下:
    typedef enum _D3DPRIMITIVETYPE
    {
    D3DPT_POINTLIST
    = 1,
    D3DPT_LINELIST
    = 2,
    D3DPT_LINESTRIP
    = 3,
    D3DPT_TRIANGLELIST
    = 4,
    D3DPT_TRIANGLESTRIP
    = 5,
    D3DPT_TRIANGLEFAN
    = 6,
    D3DPT_FORCE_DWORD
    = 0x7fffffff,
    } D3DPRIMITIVETYPE;

       其中点列表,线列表,三角形列表很好理解,它们就是独立的点/线/三角形的集合,每个顶点缓冲中的点分别表示一个点/独立线条中的一个端点/独立三角形 中的一个顶点。而线带,三角形带每个顶点缓冲中的点表示连续的线条的端点/连续三角形中的顶点。三角扇形顶点缓冲中的点表示三角扇形中的每个顶点,如图:

    在特殊情况下三角形带和三角扇形都可以组成四边形。只要将DrawPrimitive中的参数变换一下,适当改变顶点缓冲就可以得到D3D中以不同图元画出的图形。下图是三角形列表形式画出的一个三角形。

      不要忘了更改CreateVertexBuffer中的第一个表示顶点缓冲大小的参数,否则添加的顶点会被忽略的。最后在OnDestroyDevice中调用SAFE_RELEASE( g_pVB )来释放资源。
  • 相关阅读:
    关于echarts
    es6数组相关操作
    日期格式化(超实用)
    vue对象深拷贝(避免对象赋值,改变一个对象的值,另一个对象也变化)
    vue在js公用文件中使用this
    VUE百度地图API调用(手机端、PC端、微信通用)
    promise与async/await
    手机端软键盘弹出又收回后,页面下方留空白、样式定位错乱或不能滚动
    移动端表格(固定首列及表头)
    VUE面试知识整理
  • 原文地址:https://www.cnblogs.com/hcbin/p/1748616.html
Copyright © 2020-2023  润新知