找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 6043|回复: 5

【D3D入门】教你理解3D游戏的算法

[复制链接]

1111

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24235 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
发表于 2014-1-26 23:20:53 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
你要了解3D编程,你必须知道3D编程的原理。3D编程其实一点也不难,你要知道的第一点就是如何把一个空间里的顶点投影到屏幕上。
首先,假设你有一堆模型数据,也就是顶点数据,如下图所示
Points.PNG

用数组表示就是下面这样的:

  1. D3DXVECTOR3 vModel[8]=//立方体八个顶点
  2. {
  3.         {+1,+1,+1},
  4.         {-1,+1,+1},
  5.         {+1,-1,+1},
  6.         {-1,-1,+1},
  7.         {+1,+1,-1},
  8.         {+1,-1,-1},
  9.         {-1,+1,-1},
  10.         {-1,-1,-1}
  11. };
复制代码

没错,这就是顶点数据。我们要如何才能把一个模型显示到屏幕上呢?那就是让它去×世界矩阵,观察矩阵,投影矩阵。
先别急,我教大家怎么取得顶点数据在屏幕中的位置。
首先你不可能只把模型数据显示在坐标原点附近吧?你需要在别处显示这个模型,不能总在一个地方显示模型,也不要为了移动模型的位置而修改模型数据,那样太慢了,耗费CPU资源。因此我们需要掌握一个概念叫“世界矩阵”。
所谓“世界矩阵”就是一个相对坐标系,顶点数据×这矩阵之后,顶点数据表示的位置就会从绝对坐标移动到相对坐标的位置。这样物体的移动就能实现了。
举个例,假如我有一个顶点的位置在(0,0,1),然后我在位置(1,0,0)处重新建立了一个坐标系,那么这个坐标系可以用“世界矩阵”来表示,那么当我把这个顶点拿去×这个矩阵的时候呢,顶点的位置就变换到了(1,0,1)。这么一说大家就知道“世界矩阵”的意义了吧?

世界矩阵是一个4x4矩阵,你可以像下面这样理解:

  1. typedef struct
  2. {
  3.         D3DXVECTOR4 X轴;
  4.         D3DXVECTOR4 Y轴;
  5.         D3DXVECTOR4 Z轴;
  6.         D3DXVECTOR4 坐标系原点;
  7. }Matrix;
复制代码

可以注意到每个向量都是四维向量。不要管第四维是什么(前面三维用xyz表示,第四维用w表示,也就是(x,y,z,w)这样的表示方法)
第四维就让它的值为1就行了。
然后大家要知道的就是顶点×矩阵的计算方法,我来这样介绍。


首先把矩阵沿对角线翻转过来,这被称作矩阵转置(Transpose),看!

497c4ec0f269ec752b3e7eae6674ab2f.png

没错,就是这样!
开个玩笑,其实是矩阵的转置,第一行分别是矩阵成员的“X轴”、“Y轴”、“Z轴”、“坐标系原点”的X,然后是……
靠,这种表达方式太费劲。我重新来给大家表示下
假如原先的矩阵是这样的:

  1. typedef struct
  2. {
  3.         FLOAT _11,_12,_13,_14;//X轴
  4.         FLOAT _21,_22,_23,_24;//Y轴
  5.         FLOAT _31,_32,_33,_34;//Z轴
  6.         FLOAT _41,_42,_43,_44;//坐标系原点
  7. }Matrix;
复制代码

那么进行矩阵转置后,就是下面这样的:(睁大你们的眼睛好好看看除了注释以外,最重要的区别在哪里,可不要遗漏任何一个细节哦)


  1. typedef struct
  2. {
  3.         FLOAT _11,_21,_31,_41;
  4.         FLOAT _12,_22,_32,_42;
  5.         FLOAT _13,_23,_33,_43;
  6.         FLOAT _14,_24,_34,_44;
  7. }Matrix;
复制代码

其实区别也就是转置了一下,转置嘛!这样说就能明白了吧。
然后呢,我们要进行向量×矩阵的算法,也就是进行矩阵变换(Transform)。

矩阵变换很简单,就是拿你的原向量去和这个已经转置过的矩阵的每一行进行点乘,就可以得到新的向量。
不过因为矩阵是4x4矩阵,如果向量不是四维的,那也很简单,给它补个1来充当w(w就是第四维,我们用x,y,z,w四个字母表示四个维度),让它变成4维的就行了。
那么就是这样:

  1. 结果.x = 向量·矩阵第一行;
  2. 结果.y = 向量·矩阵第二行;
  3. 结果.z = 向量·矩阵第三行;
  4. 结果.w = 向量·矩阵第四行;
复制代码

当然如果你只需要得到一个三维向量就直接扔掉那个“结果.w”就行了。
哈?你居然说不懂?唉,那我再举个例子来给大家演示一下。快感谢我吧!为了感谢我,你们得多在论坛交流就是了。
首先我不可能自己去一个顶点一个顶点的去算,这是GPU的工作,可不能交给我!我可不是显卡,我是人类(也许吧)。
那么我从刚才的那个立方体中找一个顶点来做例子。啊,就是它了,(1,1,1)
那么我要把这个立方体移动到(5,5,5)的位置(当然一个矩阵不止包括了平移的信息,还能包括旋转、拉伸的信息)

于是我建立一个坐标系。因为不需要旋转,因此这个坐标系的X轴还是指向原先的X轴,Y轴还是指向原先的Y轴,Z轴还是指向原先的Z轴,然后我们用不到W,因此三个坐标轴的W都是0。最后这个矩阵是要平移到(5,5,5)的位置,因此我需要把矩阵的原点位置设立好。因此我们得到了如下的矩阵:
1,0,0,0
0,1,0,0
0,0,1,0
5,5,5,1
嗯,就是这样。现在我们把矩阵转置一下,就是下面这个样子的了:
1,0,0,5
0,1,0,5
0,0,1,5
0,0,0,1
嗯,w被果断无视了。很不错。我们的顶点数据是(1,1,1),是个三维向量。矩阵是4x4矩阵,我们在顶点数据后面补上一个1,就是(1,1,1,1)。
我们将进行以下的变换操作:
结果.x = (1,1,1,1)·(1,0,0,5)
结果.y = (1,1,1,1)·(0,1,0,5)
结果.z = (1,1,1,1)·(0,0,1,5)
结果不需要w
最后得到的结果是(6,6,6),因为这个顶点对应的是立方体原先的(1,1,1)这个顶点,也就是相对于立方体中央的。照这么说,立方体的中央就是(5,5,5)了。没错,这就是矩阵变换。
说了那么多,这样大家就应该理解了吧?


然后继续,我说到哪了?嗯,世界矩阵说完了,接下来是观察矩阵。
所谓观察矩阵就是镜头的位置,方向,组成的反矩阵。为什么要×观察矩阵呢?因为这样才能把要观察的东西移动到镜头前呗。
其实是为了方便计算,为了定位顶点的位置而设置的算法。原本空间坐标系里面镜头附近的顶点×了观察矩阵之后,它就会被移动到原点附近,这样才能算作是“投影”。透视什么的之后再说,那个属于投影矩阵的范围。
当顶点数据×了观察矩阵之后,我们可以把x、y轴上的平面当做显示器屏幕,z轴当做顶点与屏幕的距离。这样一来就很容易计算了。
不过呢,因为计算单位的原因,我们还要进行透视投影矩阵的×法计算。只有好好×了各个矩阵,才能得出顶点的确切位置。


投影矩阵就是这样的矩阵,顶点×了投影矩阵之后,顶点的x、y轴在屏幕上的位置的区间就被控制在[-1,1]区间了,对应的显示屏幕左边和右边,或者上边和下边。然后z轴的位置就是“深度”。所谓“深度”就是距离,用来进行距离判断的参数,会被写入“深度缓冲”。D3D在画每一个像素的时候,只要你开启了“深度比较”功能,它就会进行深度比较,深度比深度缓冲深的像素意味着它已经被“眼前”的物体遮挡住了,因此就没有画出来。这就是目前3D游戏解决遮挡处理的办法。可不是有些人想象中的通过“排序得到渲染次序”、“裁剪模型”。那些被用在别的领域(比如水面倒影、平面反射等)
而顶点×投影矩阵的时候,w成员不能丢。w是用来进行纹理拉伸的一个参数。这个我在这里一时半会儿也解释不清,因为这里涉及到贴图坐标的问题。贴图坐标可不是简单的把像素的位置当做纹理坐标就可以了的,那要通过这个w来计算的。
回复

使用道具 举报

0

主题

19

回帖

51

积分

用户组: 小·技术宅

UID
158
精华
0
威望
1 点
宅币
30 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-3-26
发表于 2014-3-26 16:37:38 | 显示全部楼层
谢谢分享
回复

使用道具 举报

0

主题

2

回帖

17

积分

用户组: 初·技术宅

UID
4719
精华
0
威望
2 点
宅币
11 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2019-2-27
发表于 2019-2-27 17:22:05 | 显示全部楼层
大佬有什么推荐的资料么
回复 赞! 靠!

使用道具 举报

0

主题

1

回帖

31

积分

用户组: 初·技术宅

UID
8492
精华
0
威望
2 点
宅币
26 个
贡献
0 次
宅之契约
0 份
在线时间
2 小时
注册时间
2023-11-27
发表于 2024-3-3 14:00:48 | 显示全部楼层
很好的东西,学习了
回复 赞! 靠!

使用道具 举报

1

主题

42

回帖

977

积分

用户组: 大·技术宅

UID
7437
精华
0
威望
112 点
宅币
600 个
贡献
110 次
宅之契约
0 份
在线时间
130 小时
注册时间
2021-9-11
发表于 2024-3-3 19:03:16 | 显示全部楼层
问题来了 矩阵的算法 有吗?
回复 赞! 靠!

使用道具 举报

1111

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24235 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
 楼主| 发表于 2024-3-3 20:59:07 | 显示全部楼层
tlwh163 发表于 2024-3-3 19:03
问题来了 矩阵的算法 有吗?

帖子里不就有么

结果.x = 向量·矩阵第一行;
结果.y = 向量·矩阵第二行;
结果.z = 向量·矩阵第三行;
结果.w = 向量·矩阵第四行;


回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-19 18:54 , Processed in 0.043995 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表