zoukankan      html  css  js  c++  java
  • DirectX学习---顶点缓存

    今天在学习DirectX时发现了几个问题:

    1、灵活顶点格式(FVF)的取值到底对图像的呈现有什么影响?

    2、顶点的数据格式是否可以自己设置?

    3、D3DXMatrixPerspectiveFovRH 和 D3DXMatrixPerspectiveFovLH有什么区别?

    先贴出我的测试代码:

      1 /*
      2 运行所需的库文件:d3dx9d.lib,d3d9.lib,d3dx11.lib,dxerr.lib,dxguid.lib,winmm.lib,comctl32.lib
      3 */
      4 
      5 #include <windows.h>
      6 #include <windowsx.h>
      7 #include <d3d9.h>
      8 #include <D3DX10Math.h>
      9 
     10 #define WINDOW_WIDTH 600
     11 #define WINDOW_HEIGHT 800
     12 #define WINDOW_CLASS_NAME TEXT("C_class")
     13 #define SAFE_RELEASE(p) {if(p){(p)->Release();(p) = NULL;}}
     14 
     15 #pragma comment(lib,"winmm.lib")
     16 #pragma comment(lib,"d3d9.lib")
     17 #pragma comment(lib,"d3dx9d.lib")
     18 
     19 //结构定义
     20 struct MVertex {
     21     MVertex() {};
     22     MVertex(float x, float y, float z) {
     23         m_x = x; m_y = y; m_z = z;
     24     }
     25     float m_x, m_y, m_z;
     26     static const DWORD FVF;
     27 };
     28 const DWORD MVertex::FVF = D3DFVF_XYZ;
     29 
     30 //全局声明
     31 float time = 2.0f;
     32 HWND g_hdc = NULL;
     33 HINSTANCE g_hinstance = NULL;
     34 IDirect3DDevice9* g_device = NULL;
     35 IDirect3DVertexBuffer9* Vbuffer = NULL;
     36 typedef LRESULT(CALLBACK* WNDPROCRET)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
     37 
     38 //全局函数
     39 LRESULT CALLBACK  WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
     40 WNDCLASSEX&       gCreateWindowsClass(HINSTANCE hInstance, LPCTSTR name, WNDPROCRET lpfnproc,UINT style = CS_HREDRAW | CS_VREDRAW);
     41 VOID              gMessageLoop();
     42 HRESULT           gGame_Init(HWND hwnd);
     43 VOID              gRender(HWND hwnd);
     44 VOID              Clean_Up(HWND hwnd);
     45 VOID              gCreateInterface_D3D(LPDIRECT3D9& pd3d);
     46 VOID              gGetHalinfo(LPDIRECT3D9 pd3d,int& vp);
     47 VOID              gFullParameter(HWND hwnd,D3DPRESENT_PARAMETERS& d3dpp);
     48 VOID              gCreateVertexBuffer(IDirect3DDevice9* pdevice);
     49 VOID              gCreatecamera(IDirect3DDevice9* pdevice, D3DXVECTOR3& pos, D3DXVECTOR3& target, D3DXVECTOR3& up);
     50 VOID              gTranslation(IDirect3DDevice9* pdevice);
     51 VOID              gMydraw(float time, IDirect3DDevice9* pdevice);
     52 
     53 
     54 int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
     55 {
     56     g_hinstance = hInstance;
     57 
     58     WNDCLASSEX WClass = gCreateWindowsClass(hInstance, WINDOW_CLASS_NAME, WindowProc);
     59 
     60     if (!RegisterClassEx(&WClass))
     61     {
     62         MessageBox(0, TEXT("error"), TEXT("注册失败!"), MB_OK);
     63         return 0;
     64     }
     65 
     66     g_hdc = CreateWindow(WINDOW_CLASS_NAME, TEXT("CYX"), WS_OVERLAPPEDWINDOW | WS_EX_TOPMOST,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,0,0,hInstance,0);
     67     if (!g_hdc)
     68     {
     69         MessageBox(0, TEXT("error"), TEXT("窗口创建失败!"), MB_OK);
     70         return 0;
     71     }
     72 
     73     ShowWindow(g_hdc, nShowCmd);
     74     UpdateWindow(g_hdc);
     75 
     76     if (FAILED(gGame_Init(g_hdc))) {
     77         MessageBox(0, TEXT("error"), TEXT("游戏初始化失败!"), MB_OK);
     78         return 0;
     79     }
     80     
     81     gMessageLoop();
     82 
     83     UnregisterClass(WINDOW_CLASS_NAME, hInstance);
     84     return 0;
     85 }
     86 
     87 //函数定义
     88 LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
     89     switch (uMsg) {
     90     case WM_PAINT:
     91         BeginPaint(hwnd, NULL);
     92         gRender(hwnd);
     93         //ValidateRect(hwnd, NULL);//这个函数还不是很清楚
     94         EndPaint(hwnd, NULL);
     95         break;
     96     case WM_DESTROY:
     97         Clean_Up(hwnd);
     98         PostQuitMessage(0);
     99         break;
    100     case WM_KEYDOWN:
    101         switch (wParam) {
    102         case VK_ESCAPE:
    103             DestroyWindow(hwnd);
    104             break;
    105         case VK_UP:
    106             time += 5.0f;
    107             break;
    108         case VK_DOWN:
    109             time -= 5.0f;
    110             break;
    111         default:break;
    112         }
    113     default:
    114         break;
    115     }
    116     return DefWindowProc(hwnd, uMsg, wParam, lParam);
    117 }
    118 
    119 WNDCLASSEX& gCreateWindowsClass(HINSTANCE hInstance,LPCTSTR name, WNDPROCRET lpfnproc, UINT style /* = CS_HREDRAW | CS_VREDRAW */) {
    120 
    121     static WNDCLASSEX Mywindowclass;
    122     Mywindowclass.cbSize = sizeof(Mywindowclass);
    123     Mywindowclass.cbClsExtra = 0;
    124     Mywindowclass.cbWndExtra = 0;
    125     Mywindowclass.lpfnWndProc = lpfnproc;
    126     Mywindowclass.hInstance = hInstance;
    127     Mywindowclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    128     Mywindowclass.hCursor = LoadCursor(0, IDC_ARROW);
    129     Mywindowclass.hIconSm = NULL;
    130     Mywindowclass.hIcon = NULL;
    131     Mywindowclass.lpszClassName = WINDOW_CLASS_NAME;
    132     Mywindowclass.lpszMenuName = NULL;
    133     Mywindowclass.style = style;
    134 
    135     return Mywindowclass;
    136 }
    137 
    138 VOID gMessageLoop() {
    139     MSG mmsg = { 0 };
    140     while (mmsg.message != WM_QUIT)
    141     {
    142         if (PeekMessage(&mmsg, 0, 0, 0, PM_REMOVE))
    143         {
    144             TranslateMessage(&mmsg);
    145             DispatchMessage(&mmsg);
    146         }
    147         else
    148         {
    149             gRender(g_hdc);
    150         }
    151     }
    152 }
    153 
    154 HRESULT gGame_Init(HWND hwnd) {
    155     LPDIRECT3D9 pd3d = NULL;
    156     gCreateInterface_D3D(pd3d);
    157 
    158     int vp = 0;
    159     gGetHalinfo(pd3d,vp);
    160 
    161     D3DPRESENT_PARAMETERS d3dpp;
    162     gFullParameter(hwnd, d3dpp);
    163 
    164     if (FAILED(pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, vp, &d3dpp, &g_device)))
    165     {
    166         MessageBox(0, TEXT("error"), TEXT("设备创建失败!"), MB_OK);
    167         return E_FAIL;
    168     }
    169 
    170     SAFE_RELEASE(pd3d);
    171 
    172     //创建定点缓存
    173     gCreateVertexBuffer(g_device);
    174 
    175     //设置摄像机
    176     D3DXVECTOR3 pos(.0f, 5.0f, 10.0f);
    177     D3DXVECTOR3 tar(0.0f, 0.0f, 0.0f);
    178     D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    179     gCreatecamera(g_device,pos,tar,up);
    180 
    181     //变换
    182     gTranslation(g_device);
    183 
    184     return S_OK;
    185 }
    186 
    187 VOID gRender(HWND hwnd) {
    188     gMydraw(time, g_device);
    189 }
    190 
    191 VOID Clean_Up(HWND hwnd) {
    192     SAFE_RELEASE(g_device);
    193     SAFE_RELEASE(Vbuffer);
    194 }
    195 
    196 VOID gCreateInterface_D3D(LPDIRECT3D9& pd3d) {
    197     if (!(pd3d = Direct3DCreate9(D3D_SDK_VERSION)))
    198     {
    199         MessageBox(0, TEXT("error"), TEXT("接口创建失败!"), MB_OK);
    200         return;
    201     }
    202 }
    203 
    204 VOID gGetHalinfo(LPDIRECT3D9 pd3d,int& vp) {
    205     D3DCAPS9 caps;
    206     if (FAILED(pd3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
    207     {
    208         MessageBox(0, TEXT("error"), TEXT("获取设备信息失败!"), MB_OK);
    209         return;
    210     }
    211     if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
    212     {
    213         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    214     }
    215     else
    216         vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    217 }
    218 
    219 VOID gFullParameter(HWND hwnd,D3DPRESENT_PARAMETERS& d3dpp) {
    220     ZeroMemory(&d3dpp, sizeof(d3dpp));
    221     d3dpp.BackBufferWidth = WINDOW_WIDTH;
    222     d3dpp.BackBufferHeight = WINDOW_HEIGHT;
    223     d3dpp.BackBufferCount = 1;
    224     d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
    225     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
    226     d3dpp.EnableAutoDepthStencil = TRUE;
    227     d3dpp.Flags = 0;
    228     d3dpp.hDeviceWindow = hwnd;
    229     d3dpp.FullScreen_RefreshRateInHz = 0;
    230     d3dpp.MultiSampleQuality = 0;
    231     d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    232     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    233     d3dpp.Windowed = TRUE;
    234     d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//该参数是干什么的??
    235 }
    236 
    237 VOID gCreateVertexBuffer(IDirect3DDevice9* pdevice) {
    238     if (FAILED(pdevice->CreateVertexBuffer(
    239         24 * sizeof(MVertex),
    240         0,
    241         MVertex::FVF,
    242         D3DPOOL_MANAGED,
    243         &Vbuffer,
    244         0
    245     )))
    246     {
    247         MessageBox(0, TEXT("定点缓存创建失败!"), TEXT("error"), MB_OK);
    248         return;
    249     }
    250 
    251     //填充定点缓存
    252     MVertex* v = NULL;
    253     Vbuffer->Lock(0, 0, (VOID**)&v, 0);
    254 
    255     v[0] = MVertex(0.0f, 1.4f, 0.0f);     v[6] = MVertex(0.0f,1.4f, 0.0f);
    256     v[1] = MVertex(-1.0f, 0.0f, -1.0f);   v[7] = MVertex(1.0f, 0.0f, 1.0f);
    257     v[2] = MVertex(-1.0f, 0.0f, 1.0f);    v[8] = MVertex(1.0f, 0.0f, -1.0f);
    258 
    259     v[3] = MVertex(0.0f, 1.4f, 0.0f);     v[9] = MVertex(0.0f, 1.4f, 0.0f);
    260     v[4] = MVertex(-1.0f, 0.0f, 1.0f);    v[10] = MVertex(1.0f, 0.0f, -1.0f);
    261     v[5] = MVertex(1.0f, 0.0f, 1.0f);     v[11] = MVertex(-1.0f, 0.0f, -1.0f);
    262 
    263     v[12] = MVertex(0.0f, -1.4f, 0.0f);   v[13] = MVertex(-1.0f, 0.0f, -1.0f);
    264     v[14] = MVertex(1.0f, 0.0f, -1.0f);   v[15] = MVertex(0.0f, -1.4f, 0.0f);
    265     v[16] = MVertex(1.0f, 0.0f, -1.0f);   v[17] = MVertex(1.0f, 0.0f, 1.0f);
    266 
    267     v[18] = MVertex(0.0f, -1.4f, 0.0f);   v[19] = MVertex(1.0f, 0.0f, 1.0f);
    268     v[20] = MVertex(-1.0f, 0.0f, 1.0f);   v[21] = MVertex(0.0f, -1.4f, 0.0f);
    269     v[22] = MVertex(-1.0f, 0.0f, 1.0f);   v[23] = MVertex(-1.0f, 0.0f, -1.0f);
    270 
    271     Vbuffer->Unlock();
    272 }
    273 
    274 VOID gCreatecamera(IDirect3DDevice9* pdevice, D3DXVECTOR3& pos, D3DXVECTOR3& target, D3DXVECTOR3& up) {
    275     D3DXMATRIX V;
    276     D3DXMatrixLookAtLH(&V, &pos, &target, &up);
    277     pdevice->SetTransform(D3DTS_VIEW, &V);
    278 }
    279 
    280 VOID gTranslation(IDirect3DDevice9* pdevice) {
    281     //投影变换
    282     D3DXMATRIX proj;
    283     //居然还有D3DMatrixPerspectiveFovRH()
    284     D3DXMatrixPerspectiveFovLH(
    285         &proj,
    286         D3DX_PI*0.5f,
    287         (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT,
    288         1.0f,
    289         1000.0f
    290     );
    291     pdevice->SetTransform(D3DTS_PROJECTION, &proj);
    292 
    293     //设置线型
    294     pdevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    295     //打开光照
    296     //pdevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    297 }
    298 
    299 VOID gMydraw(float time, IDirect3DDevice9* pdevice) {
    300     if (pdevice)
    301     {
    302         D3DXMATRIX Rx;
    303         static float y = 0.0f;
    304         D3DXMatrixRotationX(&Rx, y);
    305         y += time*0.002;
    306         if (y > 6.28f)
    307             y = 0.0f;
    308         pdevice->SetTransform(D3DTS_WORLD, &Rx);
    309 
    310         pdevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(230, 230, 230), 1.0f, 0);
    311         pdevice->BeginScene();
    312         pdevice->SetStreamSource(0, Vbuffer, 0,sizeof(MVertex));
    313         pdevice->SetFVF(MVertex::FVF);
    314         pdevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 8);
    315         pdevice->EndScene();
    316         pdevice->Present(0, 0, 0, 0);
    317     }
    318 }
    View Code

    现在我们来解决问题吧、

    一、灵活顶点格式(FVF)的取值到底对图像的呈现有什么影响?

    首先,常用的灵活顶点格式的取值及含义如下:

    D3DFVF_XYZ——顶点的三维坐标(分别代表X,Y,Z坐标),表示有位置,而且需要进行矩阵变换(世界,投影,视口,取景)和设置摄像机位置才能在屏幕上显示;
    D3DFVF_XYZRHW——即平时所说rhw,它说明顶点有位置,而且经过了矩阵变换,不用再由Direct3D对它进行变换,通常用于做UI(用户界面);
    D3DFVF_DIFFUSE——表示顶点格式中有漫反射颜色(这涉及到顶点数据格式的设置),同时,必须开启了光照才能看到设置的颜色,否则是本色(一般是白色)的;
    D3DFVF_NORMAL——表示顶点有法线向量;
    D3DFVF_TEX*——表示顶点有纹理坐标,*可以是1至8,表示有多少套纹理坐标

    举例来说,上述测试代码中,我的想法是将顶点格式设置为包含三个原始坐标的类,所以在FVF设置时我就将其设置为D3DFF_XYZ,同时,在后续绘制于屏幕之前,我将

    我的坐标进行了投影变换同时设置了摄像机的位置,如果将摄像机注释掉,则在屏幕上看不到任何东西。

    *注意:

    1、D3DFVF_XYZ默认的用户区中心坐标是(0,0),而D3DFVF_XYZRHW是左上角为(0,0)
    用D3DFVF_XYZ默认的为非光照的,而D3DFVF_XYZRHW是高洛德光照。

    二、顶点的数据格式是否可以自己设置?

    答案当然是一定的,不过一般要根据自己的FVF需求去设置,比如,如果你使用D3DFVF_XYZ(D3DFVF_XYZRHW) | D3DFVF_DIFFUSE | D3DFVF_NORMAL,那么你的顶点数据结构

    就应该有三种内容:坐标,颜色,法向量。对于我而言,我习惯于将FVF也定义到顶点数据结构中,这比较方便、

    三、D3DXMatrixPerspectiveFovRH 和 D3DXMatrixPerspectiveFovLH有什么区别?

    前者是创建右手坐标透视投影矩阵,而后者是创建左手坐标透视投影矩阵。回顾一下左手坐标与右手坐标:

    左手坐标:伸出左手,让拇指和食指成“L”形,大拇指向右,食指向上。其余的手指指向前方。这样就建立了一个左手坐标系。拇指、食指和其余手指分别代表x,y,z轴的正方向。判断方法:在空间直角坐标系中,让左手拇指指向x轴的正方向,食指指向y轴的正方向,如果中指能指向z轴的正方向,则称这个坐标系为左手直角坐标系.反之则是右手直角坐标系。

    右手坐标:右手坐标系在我们以前初中高中学几何的时候也经常用到。在三维坐标系中,Z轴的正轴方向是根据右手定则确定的。右手定则也决定三维空间中任一坐标轴的正旋转方向。要标注X、Y和Z轴的正轴方向,就将右手背对着屏幕放置,拇指即指向X轴的正方向。伸出食指和中指,如右图所示,食指指向Y轴的正方向,中指所指示的方向即是Z轴的正方向。要确定轴的正旋转方向,如下图所示,用右手的大拇指指向轴的正方向,弯曲手指。那么手指所指示的方向即是轴的正旋转方向。

    温润如玉,坚毅如铁。
  • 相关阅读:
    Apache ab压力测试
    2、Android自动测试之Monkey工具
    1、Monkey环境搭建
    解决IDEA中,maven依赖不自动补全的问题
    Centos7解决在同一局域网内无法使用ssh连接
    sql草稿
    mysql三表联合查询,结果集合并
    vue:父子组件间通信,父组件调用子组件方法进行校验子组件的表单
    vue:使用不同参数跳转同一组件,实现动态加载图片和数据,以及利用localStorage和vuex持久化数据
    vue:解决使用param传参后,再次刷新页面会新增一个原有的tab
  • 原文地址:https://www.cnblogs.com/heisen/p/9384601.html
Copyright © 2011-2022 走看看