一个复杂的3D模型可能由成千上万个三角形组成,而2D图像基本都是由两个三角形组成的四边形组成。如何绘制一个四边形呢:

在图中,我们用四个顶点组成了一个正方形,这四个顶点分别是v0,v1,v2,v3。为了正确描述这个正方形,我们需要根据这四个顶点创建两个三角形△V0V1V2 ,和 △V0V2V3,而这两个三角形的顶点数据,会依次保存在顶点缓冲区中。我们使用VS2019创建一个新的项目“D3D_03_Quad”,将上面绘制三角形的代码全部复制过来。因为我们之间已经做好函数封装,因此在这里,我们只需要修改initScene函数和renderScene函数即可。

// 定义初始化场景函数
void initScene(HWND hwnd, HINSTANCE hInstance) {// 四边形顶点数组,数组元素012构成一个三角形,数组元素345构成另一个三角形// 图元类型必须是 D3DPT_TRIANGLELIST,表示离散性顶点组成三角形// 相对于 D3DPT_TRIANGLESTRIP 类型,多出了V0和V2两个顶点////   V1 *********** V2//    *       *  *//     *     *    *//     *   *      *//     * *        *//  V0 *********** V3// D3D_DATA_VERTEX vertexArray[] ={// 红色三角形V0V1V2,左下角顺时针{ 300.0f, 400.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0) },{ 300.0f, 200.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0) },{ 500.0f, 200.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0) },// 蓝色三角形V0V2V3,左下角顺时针{ 300.0f, 400.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255) },{ 500.0f, 200.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255) },{ 500.0f, 400.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255) },};// 创建顶点缓冲区对象D3DDevice->CreateVertexBuffer(sizeof(vertexArray),// 表示顶点数据的字节大小0,                  // 表示使用缓存的额外信息,默认0即可。D3D_FVF_VERTEX,     // 表示灵活顶点格式D3DPOOL_DEFAULT, // 表示顶点缓存的存储位置,D3DPOOL_DEFAULT表示显卡的显存中&D3DVertexBuffer,  // 表示顶点缓存指针对象NULL);             // 表示保留参数,在此设置为NULL// 将四边形顶点数组写入顶点缓冲区对象void* ptr;D3DVertexBuffer->Lock(0,                 // 表示从什么位置开始加锁(存储区偏移量)sizeof(vertexArray),// 表示要锁定的字节数,也就是加锁区域的大小(void**)&ptr,     // 表示被锁定的存储区的指针0);                  // 表示锁定方式,这里我们设置0即可// 赋值顶点数据到缓冲区memcpy(ptr, vertexArray, sizeof(vertexArray));D3DVertexBuffer->Unlock();
}

我们发现,绘制一个三角形和四边形的区别在于,顶点数组数据不一样,其他都一样。这里需要大家注意的就是这个四边形是由那两种方向的三角形组成的,这个东西是固定的。我们不能够使用其他方向的三角形来绘制出同样的四边形。

// 定义渲染场景函数
void renderScene(HWND hwnd) {D3DDevice->SetStreamSource(0,                               // 表示顶点缓存连接的数据流,默认0即可D3DVertexBuffer,                // 表示顶点缓存数据0,                               // 表示数据流中偏移量,默认0即可sizeof(D3D_DATA_VERTEX));      // 表示每个顶点结构的大小D3DDevice->SetFVF(D3D_FVF_VERTEX); // 设置灵活顶点格式D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,  // 表示要绘制的图元类型,D3DPT_TRIANGLELIST表示三角形列表0,                    // 指定顶点缓存读取顶点数据的起始索引2);                 // 绘制三角形图元数量(两个三角形组成一个四边形)
}

我们发现,绘制一个三角形和四边形几乎相同,区别仅在于DrawPrimitive函数的最后一个参数,三角形的个数是不一样的。一个三角形就是1,两个三角形就是2。运行效果如下:

三角形是Direct3D中绘制图形的基本单元,当我们绘制图形的时候,可能会使用大量的三角形组合来完成。上文中我们使用两个三角形来绘制一个四边形,共计使用了6个顶点。但是现实中一个四边形也只有4个顶点,也就是说我们多用了2个顶点。为了解决这个问题,Direct3D加入了索引缓冲区来解决这个问题。一般情况下,顶点缓冲区和索引缓冲区都是搭配使用的。顶点缓冲区保存了物体模型的所有顶点数据,这些顶点是唯一的。而索引缓冲区则是保存了按照三角形构造物体的顶点在顶点缓冲区中的索引值,通过索引查找对应的顶点,来绘制整个图形。例如我们绘制一个四边形,顶点缓冲区只保存4个顶点数据,而索引缓冲区则是保存了6个顶点索引值。这样一来,绘制一个四边形需要的数据就少很多了,性能也提升很多。关于如何使用顶点缓冲区和索引缓冲区绘制一个四边形,我们不在详细介绍,大家可以自行下载阅读这个部分。这个项目个名称是“D3D_03_Index”。

我们上面绘制的三角形和四边形的顶点类型是D3DFVF_XYZRHW,也就是说它的顶点的坐标单位就是像素。但是,如果我们使用D3DFVF_XYZ的话,它就不是像素单位了。在DirectX的3D空间中的单位是一个虚拟单位,它不可能与现实世界的单位(CM或M,甚至像素)来做对比,但是可以将这个单位理解成现实世界的某一个单位。举个例子,我绘制一个边长为100的四边形,那么这个四边形到底有多大呢?它在屏幕上显示多大呢?DirectX的单位是虚拟的,但是屏幕的像素单位是真实存在的,例如1366*768。假如一张图片的尺寸就是1366*768的话,那么打开这个图片的话,它会正好覆盖整个屏幕。假如一个3D模型的尺寸同样也是1366*768的话,那么这个模型在屏幕上会显示会占满整个屏幕吗?答案是,也不是。这个取决于透视摄像机与3D模型之间的距离。在3D场景中,距离透视摄像机近的物体大,反之就小。这里的大小就是屏幕像素的大小。也就是说,透视摄像机距离模型近的话,它在屏幕上呈现的就会大一些,反之,就会小一些。因为DirectX里面的单位与屏幕的像素单位是受摄像机影响的,它不是一个固定的转换关系。也就是说,我们制作一个10大小的模型和一个100大小的模型没有任何的区别,因为我们可以调整摄像机的距离,让两个模型在同一屏幕上显示相同的像素大小。单位存在的另一个意义在于,在制作多个模型的时候,相互之间要有一个大小的参考。例如,一个人物模型的高度为180,一颗大树模型的高度就不应该小于180。因为这样有悖于我们的认知常理,一棵大树比人还低。

本课程的所有代码案例下载地址:

workspace.zip

备注:这是我们游戏开发系列教程的第二个课程,这个课程主要使用C++语言和DirectX来讲解游戏开发中的一些基础理论知识。学习目标主要依理解理论知识为主,附带的C++代码能够看懂且运行成功即可,不要求我们使用DirectX来开发游戏。课程中如果有一些错误的地方,请大家留言指正,感激不尽!

第三章 DirectX 图形绘制(下)相关推荐

  1. matlab在绘图时分数,第三章_Matlab图形绘制试卷.ppt

    2.griddata函数,用来产生经插值后均匀间隔数据作图.常用的调用方法是:[XI,YI,ZI] = griddata(x,y,z,XI,YI,'method'),其中x,y,z来自关系式z=f(x ...

  2. 第三章 使用 matplotlib 绘制直方图

    系列文章目录 第一章 使用 matplotlib 绘制折线图 第二章 使用 matplotlib 绘制条形图 第三章 使用 matplotlib 绘制直方图 第四章 使用 matplotlib 绘制散 ...

  3. matlab图形绘制经典案例,MATLAB经典教程第四章_图形绘制.ppt

    <MATLAB经典教程第四章_图形绘制.ppt>由会员分享,可在线阅读,更多相关<MATLAB经典教程第四章_图形绘制.ppt(32页珍藏版)>请在人人文库网上搜索. 1.Ma ...

  4. 第三章:计算机视觉(下)

    目录 LeNet LeNet在手写数字识别上的应用 LeNet 识别手写数字 LeNet在眼疾识别数据集iChallenge-PM上的应用 数据集准备 查看数据集图片 定义数据读取器 启动训练 Ale ...

  5. 【第三章:标准单元库 下】静态时序分析圣经翻译计划

    本文由知乎赵俊军授权转载,知乎主页为https://www.zhihu.com/people/zhao-jun-jun-19 3.6 黑盒的接口时序模型 本节将介绍黑盒(任意模块或块)的IO接口时序弧 ...

  6. OpenGL(三)三维图形绘制

    #include "stdafx.h" #include<GL/freeglut.h> #include<GLFW/glfw3.h>// 绘图棱锥 void ...

  7. 第九章、图形绘制——图形控件和图形方法的应用

    1.图形控件 1.Shape控件 (1)Shape属性 2-Oval椭圆 4-Round Rectangle圆角矩形 5-Round Square圆角正方形 (2)FillStyle(填充类型)和Fi ...

  8. 第三章网页图形图像设计

    3.1网页图形图像在网页中的应用 3.1.1图形图像在网页中的应用 1.标志(LOGO) 2.背景框图 3.主图 4.超链接 3.1.2构成要素--点线面 1.点 圆点.方点.三角点.锯齿点.泥点.雨 ...

  9. 计算机图形学绘制多边形代码_《GPU编程与CG语言之阳春白雪下里巴人》- 第二章(GPU 图形绘制管线)...

    第二章 GPU 图形绘制管线 万事开头难,每门科学都是如此. ------ 马克思 图形绘制管线描述 GPU 渲染流程,即"给定视点.三维物体.光源.照明模式,和纹理等元素,如何绘制一幅二维 ...

最新文章

  1. 在php代码中加视频,php – 如何在laravel代码中嵌入视频
  2. list_for_each引起的问题
  3. R12客户表结构分析
  4. 执行游戏时出现0xc000007b错误的解决方法
  5. 通过配置文件避免硬编码的一个例子
  6. Educational Codeforces Round 101 (Rated for Div. 2) D. Ceil Divisions 思维 + 根号数
  7. 《深入浅出WPF》笔记——绑定篇(一)
  8. java 异常抛出空指针异常_java.lang.NullPointerException 抛出空指针异常
  9. 关于测试一个接口的面试题
  10. Java输出特定时间段特定格式时间信息
  11. 【leetcode 简单】 第八十四题 两个数组的交集
  12. window php composer,Window下安装php composer
  13. win10开机时不显示锁屏壁纸
  14. centos下mysql执行命令_CentOS下mysql数据库常用命令总结
  15. 应急卫星通信系统项目建设要求
  16. My New Game2
  17. html实现凹陷效果,css3怎么实现字体凹陷凸出效果?(附代码)
  18. 微信自定义菜单和个性化菜单添加emoji表情(兼容ios和安卓,防止小方框)
  19. codeforces 869C The Intriguing Obsession【组合数学+dp+第二类斯特林公式】
  20. win10下如何为jdk配置环境变量

热门文章

  1. Hadoop的简单概述以及架构
  2. AD20使用字体图标 Mooretronics 矢量图标标识
  3. 十一来临,国内有哪些手机智能助手帮你出行?
  4. 前端js做公司庆典页面背景旋转星云文字从左向右穿过
  5. 九零后中年人勿入雷区,95%的人都中招了
  6. 设置TextView光标的位置
  7. [转载]点阵图(位图)与矢量图的区别
  8. 用C语言写一程序,要求输入平时成绩与期末成绩,可计算出总成绩。(平时成绩占30%,总成绩占70%),要求程序计算出成绩后不退出,可不断输入。
  9. 实战_之逆向人工智能计算器(脱壳授权)
  10. Modbus TCP