Games101 - 遮挡与深度
之前几节课学了怎么映射一个三角面到画面上,这节学多个三角面之间的遮挡关系处理,谁在前谁在后,也就是可见性怎么处理。
实现遮挡关系画家算法由远及近依次画(光栅化)。近的物体覆盖远的物体,就可以实现遮挡关系。
但是画家算法也存在一些问题,比如存在一些不可依赖深度排序解决的问题。所以不会直接用画家算法。
深度缓存 Z-Buffer这是工业界采用的算法。这里的z不是z轴,而是深度 depth,是摄像机位置到所求点的距离。
最后,只渲染每个像素上depth最浅的那个颜色。当物体发生运动后,会同步更新深度,有更小值出现就重新赋色。
深度缓存的复杂度是O(n),而不是排序的O(nlogn),因为深度缓存并不排序只求最小值。
Games101 - MVP变换
从三维旋转到欧拉角首先三维旋转绕某个轴旋转,已经知道是这样的了。
那么就可以通过对3个轴的旋转分别描述,来实现复杂的旋转角。这3个旋转角就叫做欧拉角。
罗德里格斯旋转公式一个公式,来实现绕轴n旋转α角度。轴n的定义为起点为原点,方向为n。
推导// TODO
四元数的引入由于用旋转矩阵来做平滑插值并不合理(旋转20°矩阵 和 旋转50°矩阵 的平均值并不是旋转35°),并且存在万向锁问题,所以引入四元数。games101不展开。
MVP变换Model-View-Projection 模型-视图-投影变换:将3D的模型(Model)投影到2D的屏幕(View)上。
先定义相机的 位置 Position、朝向 Look-at、向上方向 Up direction(与朝向垂直,用于确定相机本身的旋转角)。
视图结果是相对不变的,当物体和相机的移动方式完全一致、没有相对运动时,成像不变。
标准相机我们定义一个Position在 原点,Look-at在 -Z,Up direction在 Y的相机作为默认相机。
以后就可以将其他相机移成标准相机、然后再做变换、最后移回就实现了相机旋转。
投影 ...
Games101 - 矩阵变换入门
向量 Vector小概念数学上叫做向量,物理上喜欢称作矢量。
向量的模 Magnitude。
向量的归一化,意味着求单位向量 unit Vector。
向量矩阵下面是在表示笛卡尔坐标系x-y下的某个向量,可以用矩阵来表示向量。
点乘 Dot满足交换律、结合律、分配律。
结果是一个数值,可以用来检测2个向量的夹角,<90度为正,90度为0,90~180度为负。
叉乘 Cross不满足交换律!向量A x 向量B = -向量B x 向量A
结果是一个向量,这个向量是与A、B向量所组成平面的垂直向量,也就是说A、B、C向量构成一个右手直角坐标系。而法线的方向,满足右手螺旋。注意a在前所以a是食指。
图形学上,用来检测某个点是否在一个多边形(比如三角形)内。
//因为 向量AB x 向量AP 的结果大于0则说明P在AB左侧,小于0则说明P在AB右侧。
更新=> 首先确定是左手还是右手坐标系。在【右手坐标系】下,如果两个向量的叉乘结果为正值,表示向量AB经过不大于180°的【逆时针】旋转可以与向量AP的方向一致;如果为负,那么就需要转180°到360°(右手法则)。
至于为什么,思 ...
Games101 - 导学
计算机图形学看一个游戏的图形方面做得如何,一般可以参考画面亮不亮,原因是这关系到了全局光照。
光栅化 Rasterization把三维的几何形体画在屏幕上,这个画的过程,就叫光栅化。
几何学 Curves and Meshes光线追踪 Ray Tracing从相机发射光线穿过每个像素,计算交集和阴影,并继续反射光线直到它们击中光源。
动画、仿真 Animation/Simulation其他行业应用。
总结描述整个渲染管线现代GPU常规流程。具体的可以看渲染管线篇。
0.一堆三维空间的顶点。
1.将顶点做MVP变换,拉伸转换成2维平面。这步涉及2种相机、根据相似三角形确定的拉伸矩阵、纹理映射。(如果是顶点着色模式,这在一步,还会进行Shading。
纹理映射:这一步就要做,因为需要在3维空间内和uv贴图进行一一映射。关系是 二维像素 - 三维平面 - uv贴图。
2.将二维平面的点进行连线,做出大量三角面(顺时针为正面)。
3.将三角面进行采样,投射到屏幕的像素点上,这一步叫光栅化。这步涉及:光栅化的预处理视口变换、采样阶段的优化包围盒、为了抗锯齿做的预处理(滤波、模糊)。
...
AOI视野管理
什么是AOIAOIAOI(Area of Interest),一般指一个游戏对象在所处游戏场景(MMO居多)中的视野范围。
因为玩家和较远距离的角色不会产生互动,所以不需要他们的状态,只要关注、同步视野范围内的其他单位即可。
AOI主要方式
暴力计算:每隔一定帧数,就执行一次位置计算
十字链表:只关注上下左右四个方位。
九宫格:
UGUI学习 - Button
整体流程Button继承自Selectable、IPointercliClickHandler、ISubmitHandler。
外部注册IPointerClickHandlerIPointerClickHandler接口仅包含一个OnPointerClick()方法,当鼠标点击时会调用该接口的方法。而Button能触发点击事件是因为继承自IPointerClickHandler接口,并且重写了OnPointerClick方法。那IPointerClickHandler接口的方法又是被谁调用的呢?查找引用,发现是ExecuteEvents类的Execute方法,并且Execute方法赋值给s_PointerClickHandler字段。
没错,ExecuteEvents,和之前我在UGUI学习 - 事件系统、射线检测的分析一致。
AddListener那么onClick.AddListener()的本质也可以挖一下,其实就是监听了 public ButtonClickedEvent onClick。而这个追溯到最底层,就是对一个回调方法队列进行List.Add()。
Unity调用也是和 ...
算法基础:图论
名词解释
算法:查找与搜索
参考查找1.顺序查找 顺序遍历。
2.二分查找 折半查找、二分查找,一个东西。对数据有要求,必须是按照关键字进行排序的。
3.插值查找 在二分查找上做的优化。其实就是计算mid值不再是除以2,而是根据线性插值求出一个接近的数。对数据更高要求,不但得是顺序,还必须满足数值分布均匀。
4.斐波那契查找 想在非均匀分布的数据中优化二分查找,就需要用到了。原理与黄金分割有关,从没见过暂时不看。
5.分块查找 这个就是类似桶排序的行为,把数据分成多个区间块来查找。
6.哈希查找 其实就是散列表。选一种哈希函数f,把数据的存储位置x和关键字y形成一种映射,然后查找关键字y时求出下标x即可(当然会有哈希碰撞问题要解决)。
搜索深度优先 DFS属于图算法一种,是一个针对图和树的遍历算法。是盲目搜索算法。一般用堆+栈数据结构来辅助进行遍历,堆是要遍历的对象、栈内是路径结果。
搜索前先定义是先找左下子结点还是右下子结点。探索时会不停往下找,直到下方结点没有了,就开始往上一级。遍历期间,将遇到的结点入栈,如果遇到往上一级的情 ...
算法:常见排序
参考精简归纳:https://www.drflower.top/posts/6a923688/
入门图解:
https://blog.csdn.net/weixin_50651363/article/details/120070517
https://blog.csdn.net/kexuanxiu1163/article/details/103051357
内部排序冒泡排序我们先固定队尾。进行多次遍历,每一次遍历途中两两比较、两两交换,直到确定到最后1位。下一次还是从头开始遍历,但是之确定到倒数第2位…直到第1位为止。
可以优化,如果某次遍历产生了0次交换,那么可以提前结束遍历。比如排序有序数组时,一次遍历就结束了。
选择排序我们先固定队头。将队列分为2个部分,前面是排序完的部分、后面是待排序部分,每一次遍历都是去找待排序部分的最小值,放到排序完部分的队尾。
Q:冒泡排序与选择排序哪个效率高?A:两者时间复杂度都时候O(n),但冒泡排序在内存循环交换,选择排序在外循环交换,一般而言选择排序效率更高。
插入排序我们先固定队头。将队列分为2个部分,前面是即刻排序完的部分、后面是待排序部 ...
UGUI学习 - LayoutSystem布局系统
学习博客:https://blog.csdn.net/qq_28820675/article/details/106245195
CanvasUpdateSystem中更新布局的具体实现系统。
布局 LayoutSystem也就是上一篇中说的 Canvas刷新系统 中,重建得2个数组之一Layout数组是怎么来的、又是怎么重建得。
什么时候标记也是用脏标记。时机一般为尺寸改变时(RectTransform Dimensions)。
标记后干什么UGUI组件(如Graphic、ScrollRect…)在需要布局处理时(也就是被标记或OnDisable时),会把自身的RectTransform组件用LayoutRebuilder对象包装,之后加入Layout数组。
重建布局这个的执行时机,在画布刷新系统那篇里有细写。
12345678910111213// CanvasUpdateSystem触发重建public void Rebuild(CanvasUpdate executing){ switch (executing) { cas ...

