Direct3D 索引缓存



小学的时候我们知道3个顶点组成一个三角形,那么四个顶点我们会说有4个三角形.这就是一个顶点同时参与了四次绘制三角形的结果. 在程序中也一样,比如我们绘制的两个三角形是挨着一起的,总有几个顶点是重合的. 这个顶点是可以重复使用,可以使用顶点缓存来记录如何绘制顶点的顺序,多次使用同一个顶点.到达内存的节省. 下面我们就是用四个顶点绘制出2个三角形


创建索引缓存:

LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer = NULL;            //索引缓存
//创建索引缓存
if(FAILED(g_pd3dDevice->CreateIndexBuffer(6 * sizeof(WORD),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&g_pIndexBuffer,0)))
{
    return E_FAIL;
}

访问索引缓存: 

WORD * indices = 0;
g_pIndexBuffer->Lock(0,0,(void**)&indices,0);

//第一个三角形由0,1,3顶点组成
indices[0] = 0;
indices[1] = 1;
indices[2] = 3;

//第二个三角形由1,2,3顶点组成
indices[3] = 1;
indices[4] = 2;
indices[5] = 3;

g_pIndexBuffer->Unlock();

绘制图形:

g_pd3dDevice->SetStreamSource(0,g_pVertexBuffer,0,sizeof(CUSTOMVERTEX));        //设置绘制的顶点数据
g_pd3dDevice->SetIndices(g_pIndexBuffer);                                       //设置索引缓存
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);                                      //设置灵活顶点格式
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);               //根据索引绘制图形,4代表使用4个顶点,2代表两个三角形,其他查询API了解吧

 

效果图:

全部代码:

#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;            //顶点缓冲区对象
LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer = 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(4*sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&g_pVertexBuffer,NULL)))
    {
        return E_FAIL;
    }

    //创建索引缓存
    if(FAILED(g_pd3dDevice->CreateIndexBuffer(6 * sizeof(WORD),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&g_pIndexBuffer,0)))
    {
        return E_FAIL;
    }

    //创建顶点数据
    CUSTOMVERTEX vertices [] =
    {
        { 100.0f, 100.0f, 0.0f, 1.0f,  D3DCOLOR_XRGB(36, 45,0), },
        { 300.0f, 400.0f, 0.0f, 1.0f,  D3DCOLOR_XRGB(255, 255, 255), },
        { 500.0f, 100.0f, 0.0f, 1.0f,  D3DCOLOR_XRGB(0,44,0), },
        { 300.0f, 100.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();                            //解锁

    //这是索引缓存数据
    WORD * indices = 0;
    g_pIndexBuffer->Lock(0,0,(void**)&indices,0);

    indices[0] = 0;
    indices[1] = 1;
    indices[2] = 3;

    indices[3] = 1;
    indices[4] = 2;
    indices[5] = 3;

    g_pIndexBuffer->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->SetIndices(g_pIndexBuffer);
    g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);                                        //设置灵活顶点格式
    //g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);

    g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,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);
}
时间: 2024-10-13 12:33:56

Direct3D 索引缓存的相关文章

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

第12章 Direct3D绘制基础 1. 顶点缓存 计算机所描绘的3D图形是通过多边形网格来构成的,网网格勾勒出轮廓,然后在网格轮廓的表面上贴上相应的图片,这样就构成了一个3D模型.三角形网格是构建物体模型的基本单元,而一个三角形有3个顶点,为了能够使用大量三角形组成三角形网格来描述物体,需要首先定义号三角形的顶点(Vertex),3个顶点确定一个三角形,顶点除了定义每个顶点的坐标位置外,还还含有颜色等其他属性. 在Direct3D中,顶点的具体表现形式是顶点缓存,顶点缓存保存了顶点数据的内存空

WebGL-利用索引缓存来绘图

通过操作模型坐标变换矩阵,实现了多个模型的移动,旋转和放大缩小.但是,渲染的依然是简单的三角形,是个构造及其简单的模型.但是实际中,用WebGL来绘制一个简单的三角形的机会是很少见的.至少是个四角多边形吧,通常会是更复杂的模型.伴随着模型的复杂化,顶点的个数也会大幅度增加,越是精密圆滑的模型,所需要的顶点的量也会变的肥大化.javascript中倒是没有什么限制,也不是为了节省内存或者是节省代码量,直接绘制这些大量顶点数据也不是说不可以,但是尽可能的减少数据量这种想法是程序员本性.在WebGL中

顶点缓存与索引缓存

顶点缓存与索引缓存是相互配合来简化重复顶点的,3D中任何显示出来的东西都是三角形,所以一个图元中含有n个三角形,但是计算机不认三角形,而只储存顶点,这就是顶点缓存,但是光有这些顶点是没法组织成一系列有序三角形的,所以要有索引缓存来和这部分顶点缓存相配合. 比如共有n个顶点,这些顶点中有些用了一次有些用了很多次,这n个顶点都存储在顶点缓存中. 然后索引缓存中只是一些0~n-1的数字对应顶点缓存中的n个顶点,然后计算机从索引缓存中开始3个一组的读取三角形,直到此图元绘制完成. 函数实现:g_pd3d

[WebGL入门]十八,利用索引缓存来绘图

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 对应复杂的模型 上次,通过操作模型坐标变换矩阵,实现了多个模型的移动,旋转和放大缩小.但是,渲染的依然是简单的三角形,是个构造及其简单的模型.但是实际中,用WebGL来绘制一个简单的三角形的机会是很少见的.至少是个四角多边形吧,通常会是更复杂的模型.伴随着模型的复杂化

Direct3D 顶点缓存

今天我们来学习下Direct3D的顶点和顶点缓存,首先我们需要在场景中绘制一些物体,物体都是由多个三角形组成,每一个三角形由三个顶点组成,我们来看下面一个NPC的模型 左图:正常的模型                      右图:看的出模型是有多个三角形组成 现在我们知道了一个模型最小单位是一个顶点. 如果我们需要自己绘制物体,就要学习下Direct3D如何创建顶点. 顶点在Direct3D中叫顶点缓存(VertexBuffer),顶点缓存保存了顶点的一些数据空间,比如位置,颜色,法向量等等

【MySQL】MySQL中针对大数据量常用技术_创建索引+缓存配置+分库分表+子查询优化(转载)

原文地址:http://blog.csdn.net/zwan0518/article/details/11972853 目录(?)[-] 一查询优化 1创建索引 2缓存的配置 3slow_query_log分析 4分库分表 5子查询优化 二数据转移 21插入数据 如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求.这个时候NoSQL的出现暂时解决了这一危机.它通过降低数据的安全性,减少对事务

mysql数据库性能优化(包括SQL,表结构,索引,缓存)

优化目标减少 IO 次数IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑,当然,也是收效最明显的优化手段.降低 CPU 计算除了 IO 瓶颈之外,SQL优化中需要考虑的就是 CPU 运算量的优化了.order by, group by,distinct … 都是消耗 CPU 的大户(这些操作基本上都是 CPU 处理内存中的数据比较运算).当我们的 IO 优化做到一定阶段之后

Windows游戏编程之从零开始d

I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来浅墨的博客逛一下看有没有更新,"每天都来就像看女神那般不依不舍",弄得我再不更新都不好意思了,哈哈~怎么说呢,前段时间忙毕设,回国,暑假,间隔年旅行休整,然后是适应新的生活,各种事情,也真正没有心境来更新博客了,最近正好心境安定下来,就继续开始写博.额,关于思想汇报改天我专门写一篇文章和大家交流交流,现在先打住说正事吧~ 首

使用redis缓存加索引处理数据库百万级并发

使用redis缓存加索引处理数据库百万级并发 前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1000万条数据,可以参考我之前的文章插入数据,这里不再细说.我大概的做法是这样的,编码使用多线程访问我的数据库,在访问数据库前先访问redis缓存没有的话在去查询数据库,需要注意的是redis最大连接数最好设置为300,不然会出现很多报错. 贴一下代码吧 1 2 3 4 5 6 7 8 9 10 1