【directX 3D游戏开发】DirectX 中的空间坐标和灵活顶点格式使用
实例工程文件如下:点击打开链接
在DirectX 中,坐标系主要分为三种,分别是:自身坐标系,世界坐标系,和摄像机坐标系
自身坐标系:一般情况下,游戏角色的自身坐标系的原点一般在两脚之间,自身坐标系的作用是用于改变角色形状的,比如你的胳膊相对于自身原点的坐标系改变,胳膊的位置长短什么的就肯定变了
世界坐标系:世界坐标系是物体相对于整个场景的坐标,他是用来确定的物体的位置的,一般物体的平移旋转都是对世界坐标的改变
摄像机坐标系:顾名思义,摄像机坐标系就是相对于摄像机的坐标,以摄像机所在的位置为原点
DirectX中,坐标系采用的是左手坐标系,就是向右为X轴的正方形,向上为Y轴的正方形,向屏幕里是Z轴的正方向,OpenGL里采用右手坐标系,这个不在我们讨论范围,所以在此不再赘述,总之,不同框架有其自己的坐标系规定,我们注意即可。
接下来是顶点,首先要弄明白的就是,顶点有哪些属性:1、基于世界坐标系的世界坐标 2、颜色、法线、贴图、纹理坐标等
下面介绍灵活顶点格式的概念:
灵活顶点格式 ( Flexible Vertex Format )FVF
其实这就是一个我们自己声明定义的一个结构,在其中,我们进行图元顶点的存储,我们在程序中用它来记录一切顶点的属性,但DX本身对它有一定的限制,那就是限制我们在设计其属性时各类型参数的顺序。在这个FVF中,我们可以设置顶点的:
1:位置x,y,z坐标 2:RHW(已转化的顶点,齐次W倒数) 3:混合加权值 4:顶点的法线 5:扩散的颜色(漫射属性) 6:反射颜色(镜面反射属性) 7:纹理坐标集(UV坐标)等 我们可以根据不同的需要来选择部分的属性进行设置,这将比强硬全部设置来的方便,计算机在图形绘制时将根据我们的设置来处理必要的组成部分,节省了大量的内存和渲染时间。但是依旧是那句话,可以部分属性不进行设置,但顺序不可颠倒。(这一段是百度的)
我们着重介绍一下灵活顶点格式的坐标部分:
#define D3DFVF_CUSTOMVERTEX(D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
struct stVertex
{D3DXVECTOR4 vPos;//为什么是4维向量,因为是X Y Z RHW各占一维DWORD dwColor;};
D3D中的顶点缓冲区,为什么有了数组还是定义顶点缓冲区?
D3D的API在绘制的时候,顶点数据是存到数组中了,但是在画的时候,还是从缓冲区中拿。因此数组只是临时存一下,存完了还是要把数据放到缓冲区中,这样显卡在画的时候才能从缓冲中拿数据、绘制
LPDIRECT3DVERTEXBUFFER9 p_dVB = NULL;
stVertex cVertices[] = {{ D3DXVECTOR4(100,100,0,1), D3DCOLOR_XRGB(255 , 0, 0) },//因为使用的是XYZRHW,D3DXVECTOR4(100,100,0,1)最后一个数字一定是1{ D3DXVECTOR4(400,100,0,1), D3DCOLOR_XRGB(0, 255, 0) },{ D3DXVECTOR4(100,400,0,1), D3DCOLOR_XRGB(0, 0, 255) },};
5.为顶点缓冲区分配空间,并将数组中的顶点数据拷贝到顶点缓冲区中
//通过设备指针来创建顶点缓冲区,CreateVertexBuffer类似new,在堆中申请的内存,因此不可以写在循环中,会造成内存泄露g_pDevice->CreateVertexBuffer(sizeof(cVertices),//顶点缓冲区的大小D3DUSAGE_WRITEONLY,//顶点缓冲区的作用D3DFVF_CUSTOMVERTEX,//通过我们已经定义好的灵活顶点模式,告知系统当前每一个顶点的格式D3DPOOL_MANAGED,//顶点缓冲区的存储空间位于哪里,D3DPOOL_MANAGED代表当前存储空间受系统管理,自动分配&p_dVB,//返回的顶点缓冲区指针NULL//Handle*一律给NULL,系统保留参数,一律给NULL即可);//前面只是分配空间,下面要拷贝数据,格式是固定的,先声明一个无类型的指针void* pVertices = NULL;//锁定顶点缓冲区,以便向其中拷贝数据【有锁定就有unlock】p_dVB->Lock(0,//锁定的偏移量,0表示不偏移sizeof(cVertices),//锁定的大小&pVertices,//锁定之后的存储空间由该指针指向0//锁定的标识,为0即可);//将cVertices中的数据拷贝到pVertices中,大小就是cVertices数组这么大memcpy(pVertices,cVertices,sizeof(cVertices));p_dVB->Unlock();
6.设置数据源、设置灵活顶点格式、绘制图元,这部分写在游戏循环里
//设置数据流的来源g_pDevice->SetStreamSource(0,//数据流管道号(d3d中可以同时支持16种管道,编号从0-15,使用的时候依次使用,从0开始)p_dVB,//数据来源,将数据从这个往管道0里面放0,//数据流的偏移量,前面p_dVB->Lock就没有偏移,这都是相对应的,因此这里也不偏移sizeof(stVertex)//每个数据的字节数大小,但是系统不知道按照何种格式解析);
//告知系统数据格式,以便解析数据g_pDevice->SetFVF(D3DFVF_CUSTOMVERTEX);//绘制图元----一种画图方式,以后讲解,PT—Primitive是图元,Type是类型,三角形Triangleg_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST,//三角形列0,//起始点编号(三角形中先画哪个点,等同于在数组中顶点的编号,即从数组的0号元素开始画)1//图元的数量);
完整代码示例如下
//Utility.h
#ifndef D3D_USEFUL_TOOLS_
#define D3D_USEFUL_TOOLS_#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib,"Winmm.lib")#include <d3d9.h> //d3d的基础函数头文件
#pragma comment(lib,"d3d9.lib") //d3d的基础函数库文件#include <d3dx9.h> //d3d的扩展函数头文件
#pragma comment(lib,"d3dx9.lib") //d3d的扩展函数库文件#endif
//main.cpp
#include "Utility.h"HWND g_hWnd = 0;//------改造3D窗口需要用到的内容-------
LPDIRECT3D9 g_pD3D = NULL; //D3D的接口指针
LPDIRECT3DDEVICE9 g_pDevice = NULL; //D3D的设备指针/*在3D窗口中绘制一个三角形的步骤为:(1)、定义灵活顶点格式(2)、根据顶点格式构建一个描述顶点的结构体(3)、声明一个顶点缓冲区指针(4)、定义一个结构体数组用来给每一个顶点赋值(5)、为顶点缓冲区分配空间并将数组中的顶点数据拷贝到顶点缓冲区中(6)、设置数据源、设置灵活顶点格式、绘制图元
*///----步骤(1)、定义灵活顶点格式----
//每一个顶点的格式(经过变换的屏幕坐标|顶点的颜色)
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)//----步骤(2)、根据顶点格式构建一个描述顶点的结构体----
//描述一个顶点的结构体
struct stVertex
{D3DXVECTOR4 vPos;DWORD dwColor;
};//----步骤(3)、声明一个顶点缓冲区指针----
//D3D中的顶点缓冲区
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;//初始化顶点缓冲区
void initVB()
{//----步骤(4)、定义一个结构体数组用来给每一个顶点赋值----//数组用来存储当前程序中的顶点数据stVertex cVertices[] = {{D3DXVECTOR4(100,100,0,1),D3DCOLOR_XRGB(255,0,0)},{D3DXVECTOR4(400,100,0,1),D3DCOLOR_XRGB(0,255,0)},{D3DXVECTOR4(100,400,0,1),D3DCOLOR_XRGB(0,0,255)}};//----步骤(5)、为顶点缓冲区分配空间并将数组中的顶点数据拷贝到顶点缓冲区中----//通过设备指针来创建顶点缓冲区,用来存储顶点数据g_pDevice->CreateVertexBuffer(sizeof(cVertices),//顶点缓冲区的大小D3DUSAGE_WRITEONLY, //顶点缓冲区的作用D3DFVF_CUSTOMVERTEX, //通过我们已经定义好的灵活顶点格式告知系统当前每一个顶点的格式D3DPOOL_MANAGED,//顶点缓冲区的存储空间位于哪里,D3DPOOL_MANAGED代表当前存储空间受系统管理,自动分配&g_pVB,//返回的顶点缓冲区指针NULL //系统保留参数,为NULL即可);void * pVertices = NULL;//锁定顶点缓冲区,以便向其中拷贝数据g_pVB->Lock(0,//锁定的偏移量sizeof(cVertices),//锁定的大小&pVertices, //锁定之后的存储空间由该指针指向0 //锁定的标识,为0即可);memcpy(pVertices,cVertices,sizeof(cVertices));g_pVB->Unlock();}//初始化D3D运行环境
void onCreateD3D()
{g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);if(!g_pD3D)return;-----检测硬件设备能力的方法-----//D3DCAPS9 caps;//ZeroMemory(&caps,sizeof(caps));//g_pD3D->GetDeviceCaps(// D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps);D3DDISPLAYMODE d3ddm;ZeroMemory(&d3ddm,sizeof(d3ddm));g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm);D3DPRESENT_PARAMETERS d3dpp;ZeroMemory(&d3dpp,sizeof(d3dpp));d3dpp.Windowed = true; //窗口模式-------全屏模式的写法:---------//d3dpp.Windowed = false;//d3dpp.BackBufferWidth = d3ddm.Width;//d3dpp.BackBufferHeight = d3ddm.Height;d3dpp.BackBufferFormat = d3ddm.Format;d3dpp.BackBufferCount = 1;d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//是否开启自动深度模板缓冲d3dpp.EnableAutoDepthStencil = true;//当前自动深度模板缓冲的格式d3dpp.AutoDepthStencilFormat = D3DFMT_D16;g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pDevice);if(!g_pDevice)return;//设置渲染状态:设置启用深度值g_pDevice->SetRenderState(D3DRS_ZENABLE,true);}//初始化游戏内容
void onInit()
{onCreateD3D();/*D3DXMATRIX matView , matProj;D3DXMatrixIdentity(&matView);D3DXMatrixIdentity(&matProj);D3DXVECTOR3 vEyePos(0,3,-5);D3DXVECTOR3 vLookAt(0,0,0);D3DXVECTOR3 vUp(0,1,0);D3DXMatrixLookAtLH(&matView,&vEyePos,&vLookAt,&vUp);g_pDevice->SetTransform(D3DTS_VIEW,&matView);D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/3,4.0f/3.0f,1.0f,5000.0f);g_pDevice->SetTransform(D3DTS_PROJECTION,&matProj);*/initVB();
}void onLogic(float fElapsedTime)
{}void onRender(float fElapsedTime)
{g_pDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(234,123,123),1.0f,0);g_pDevice->BeginScene();//----步骤(6)、设置数据源、设置灵活顶点格式、绘制图元----//设置数据流的来源g_pDevice->SetStreamSource(0,//数据流管道号(0-15)g_pVB, //数据的来源0,//数据流的偏移量sizeof(stVertex)//每个数据的字节数大小);//告知系统数据格式,以便解析数据g_pDevice->SetFVF(D3DFVF_CUSTOMVERTEX); //绘制图元 Primitive:图元,Type:类型,Triangle:三角形g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, //三角形列0, //起始点编号(等同于在数组中顶点的编号)1 //图元的数量);g_pDevice->EndScene();g_pDevice->Present(NULL,NULL,NULL,NULL);
}//销毁游戏
void onDestroy()
{}LRESULT CALLBACK WndProc(HWND _hWnd,UINT _uMsg,WPARAM _wparam,LPARAM _lparam);INT WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{WNDCLASS wc;ZeroMemory(&wc,sizeof(wc));wc.cbClsExtra = NULL;wc.cbWndExtra = NULL;wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);wc.hCursor = LoadCursor(NULL,IDC_ARROW);wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);wc.hInstance = hInstance;wc.lpfnWndProc = WndProc;wc.lpszClassName = TEXT("alibaba");wc.lpszMenuName = NULL;wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;RegisterClass(&wc);g_hWnd = CreateWindow(wc.lpszClassName,TEXT("First_3DApp"),WS_OVERLAPPEDWINDOW,100,20,800,600,NULL,NULL,hInstance,NULL);if(!g_hWnd)return 0;ShowWindow(g_hWnd,SW_SHOWNORMAL);UpdateWindow(g_hWnd);onInit();MSG msg;ZeroMemory(&msg,sizeof(msg));while (msg.message!=WM_QUIT){if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}else{static DWORD dwTime = timeGetTime();DWORD dwCurrentTime = timeGetTime();DWORD dwElapsedTime = dwCurrentTime - dwTime;float fElapsedTime = dwElapsedTime * 0.001f;//----------------------------------------onLogic(fElapsedTime);onRender(fElapsedTime);//----------------------------------------if(dwElapsedTime < 1000 / 60)Sleep(1000/60 - dwElapsedTime);dwTime = dwCurrentTime;}}onDestroy();return 0;
}LRESULT CALLBACK WndProc(HWND _hWnd,UINT _uMsg, WPARAM _wparam,LPARAM _lparam)
{switch(_uMsg){case WM_KEYDOWN:if(_wparam == VK_ESCAPE)DestroyWindow(_hWnd);break;case WM_CLOSE:DestroyWindow(_hWnd);break;case WM_DESTROY:PostQuitMessage(0);break;}return DefWindowProc(_hWnd,_uMsg,_wparam,_lparam);
}
【directX 3D游戏开发】DirectX 中的空间坐标和灵活顶点格式使用相关推荐
- 【Unity 3D 学习】 《Unity 3D 游戏开发》(第二版 宣雨凇著) 书中一些名字注解
前言 在学习<Unity 3D 游戏开发>这本书的过程中碰到了一些术语,比如序列化.反序列化.反射等,这些基本都是常见的程序员行话,但是感觉自己对这些术语总是一知半解,为了让自己更清楚地知 ...
- 3D游戏开发套件指南(入门篇)
今天将介绍最新的3D游戏开发套件.不论是使用2D还是3D游戏开发套件,都可以在不编写任何代码的情况下,通过设置与拖放便能快捷的实现游戏创意. 指南简介 本指南将引导开发者设置一个空的场景,使用3D游戏 ...
- 雨松MOMO《Unity 3D游戏开发》源码公布
原创文章如需转载请注明:转载自雨松MOMO程序研究院 本文链接地址:雨松MOMO<Unity 3D游戏开发>源码公布 下载源码时,首先大家请登陆图灵社区找到<Unity 3D游戏开发 ...
- DirectX 12 3D 游戏开发与实战第五章内容
渲染流水线 学习目标: 了解用于在2D图像中表现出场景立体感和空间深度感等真实效果的关键因素 探索如何用Direct3D表示3D对象 学习如何建立虚拟摄像机 理解渲染流水线,根据给定的3D场景的几何描 ...
- DirectX 12 3D游戏开发实战 -- 龙书随书源码各章项目运行结果概览
DirectX 12 3D游戏开发实战 -- 龙书随书源码各章项目运行结果概览 第1章 向量运算 第2章 矩阵运算 第4章 Direct3D初始化 第6章 利用Direct3D绘制几何体Box 第7章 ...
- 《DirectX 9.0 3D游戏开发编程基础》 第二章 绘制流水线 读书笔记
模型的表示 场景:物品或模型的集合 任何物品都可以用三角形网络逼近表示.我们经常用以下术语描述三角形网络:多边形(polygons).图元(primitives).网络几何单元(mesh geomet ...
- Unity 3D - 游戏开发中的Lua
Unity 3D - 游戏开发中的Lua : 本文作者:秦元培, 本文出处:http://blog.csdn.net/qinyuanpei/article/details/39826323 前言 : ...
- 《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——2.1节游戏中的音效
本节书摘来自异步社区<Android 3D游戏开发技术宝典--OpenGL ES 2.0>一书中的第2章,第2.1节游戏中的音效,作者 吴亚峰,更多章节内容可以访问云栖社区"异步 ...
- 学习3D游戏开发进阶之路
笔者从事IT行业15年了,一直奋斗在一线编程,从普通程序员逐步成长到上市公司技术总监,目前在创业公司担任技术合伙人,主要负责公司整个项目团队的技术管理.在网上或者论坛上很多同学请教过我关于如何学习3D ...
最新文章
- Linux系统介绍 文本查看、操作、统计命令(head/tail cat/tac less/more • wc sort uniq • cut paste)
- 记一次因坏块引起的dataguard恢复
- vuejs单文件组件:安装 webpack 和 vue-cli
- elasticsearch 自定义routing
- php获取字符串扩展,PHP7扩展开发之字符串处理
- icd植入是大手术吗_母狗绝育是大手术吗?手术完需要住院吗?绝育后是不是会变胖?...
- 手动配置 iis php环境,iis上手动配置php
- CMU和谷歌联手放出XL号Transformer!提速1800倍 | 代码+预训练模型+超参数
- 3.Jenkins 2 权威指南 --- 流水线执行流程
- m7405d粉盒清零方法_打印机清零方法总览
- 将pem证书转换为crt和key
- Navicat导入连接
- 决策引擎服务平台blaze_是Blaze数据服务还是LiveCycle数据服务?
- 光滑曲线_光滑曲线可求长定理证明
- 大众创业热度不减,好机友项目强势来袭
- 计算机房设备搬迁协议,设备搬迁协议.docx
- 你需要知道的8种数据结构
- iit delhi_IIT的完整形式是什么?
- Russian Dolls on the Christmas Tree
- 【宇麦科技】NAS玩家必备小知识——RAID怎么选才能又快又稳?
热门文章
- 正则表达式,各种空字符和空格字符
- 用RIO包健壮地读写
- MATLAB求解非线性方程组的五种方法
- CentOS-7.4(1708)release notes发行注记
- Mac Dropbox 点击“首选项”无反应 没反应怎么办?
- 2017“CCF科学技术奖”全公布,6位获奖人带来独家经验分享
- 这个将996反对到极致的网站,在GitHub上的Star数已经狂飙到 10 万+了
- 将一个n位数分解为各个位数的数字。
- 反驳李刚的针对我吐槽的回应,曝光疯狂java李刚的骗子行径
- javaScript基础面试题 ---闭包