游戏架构——图形学篇

 

  1. 渲染管线

目前绘制总共有光栅化和光线追踪(Ray Tracing)两种主流方式。

    1. 光栅化

将3D模型的三角形转换为2D屏幕上的像素或者点。对这些像素作进一步处理或“着色”,最后将其显示在屏幕上。

优点:渲染速度比光线追踪快很多

局限:处理阴影相对于光线追踪的自然而言的生成阴影显得不直观,真实感不强,并且需要很多运算。另外,光栅化并非基于对物理光线的追踪计算,对现实复杂的光照效果的就无能为力了,比如无法做反射和折射,和阴影等物理现象

      1. GPU Rendering Pipeline绘制管线/渲染管线

输入:Scene objects, Light Sources, Cameras, Program object( shaders for programmable pipeline stage)

输出:pixels stored in framebuffer(帧缓冲中的像素值)

  • 传统OpenGL渲染管线(不一定能用到):

顶点着色器->形状(图元)装配->几何着色器->光栅化->片段着色器->Alpha测试与混合

顶点着色器:以一个单独的顶点作为输入,把3D 物体座标座标转化为裁剪座标(待考证),以及允许我们对顶点属性进行一些基本处理。

图元装配:将顶点着色器输出的所有顶点作为输入,并将所有的点装配成指定图元的形状

几何着色器:把图元形式的一系列顶点的集合作为输入,可以通过产生新顶点构建新的图元来生成其他形状

光栅化:将几何图元映射到屏幕上相应的像素,生成供片段着色器使用的片段,在片段着色器之前会进行裁剪,丢弃掉视图以外的像素,提升执行效率

片段着色器:片段着色器为几何中的每个片段运行。工作是确定每个片段的最终颜色。

Alpha测试与混合:这个阶段检测片段的对应的深度(和模板(Stencil))值,用它们来判断这个像素是在其它物体的前面还是后面,决定是否应该丢弃。这个阶段也会检查alpha值(透明度)并对物体进行混合(Blend)。所以,即使在片段着色器中计算出来了一个像素输出的颜色,在渲染多个三角形的时候最后的像素颜色也可能完全不同。

  • 完整openGL渲染管线:

Vertex Specification(顶点规范):应用程序设置顶点的有序列表并发送到管道提交顶点数据需要创建一个顶点流,然后告诉GPU如何解释该流

顶点流:流数据定义顶点数据

原始:解释顶点流的方式

Vertex Shader:以一个单独的顶点作为输入,把3D 物体座标座标转化为裁剪座标(已考证),输入顶点与输出顶点1:1映射,以及允许我们对顶点属性进行一些基本处理。但必须输出顶点的位置

Tesselation:可选阶段,图元被细分,划分更加平滑的三角网格。有两个shader以及一个固定功能阶段组成(Tesselation Control Shader/Tesselation evaluation shader , Tesselation primitive generator) (细分控制着色器/细分估计着色器, 细分图元生成器)

Geometry shader:可选阶段,输入图元,输出零个或者多个图元(可以生成新的几何图元)

Vertex Post_processing(顶点后处理):固定功能阶段,主要经历以下步骤:1.Transform feedback:将顶点处理阶段输出的值记录到缓冲区对象中2.裁剪:收集先前阶段生成的图元,然后裁剪到视锥体中 3.透视分割:将剪辑空间位置转换为NDC 4.视口转换:将NDC座标转换为窗口空间。

主要功能是Clippling,裁剪丢弃掉视锥体之外的图元:

图元装配:同上(传统opengl),收集先前阶段输出的一系列顶点数据,并将其组合成一系列图元;face剔除:可以根据窗口空间中三角形的朝向来选择三角形图元,避免渲染揹着视点的三角形图元

光栅化:将图元转化为多个片段,以及通过顶点属性插值得到片段的属性

几何着色器:每个片段都有以窗口座标,以及其他通过插值得到的属性值,输出(深度值,模板值,零个或者多个颜色值),工作是确定每个片段的最终颜色。

Per_Sample Operations:对片段进行Pixel ownership test , Scissor test, Stencil test, Depth test.最后进行Color blending.将片段写进framebuffer.

  • 简化三阶段:应用阶段、几何阶段、光栅化阶段

应用阶段

在CPU中执行,一个在应用程序阶段的算法通常可以减少被渲染的三角形数量。在应用程序阶段的最后,将被渲染的几何数据输入到几何阶段。此外,碰撞检测、动画、变形等通常也可以在应用阶段执行。

几何阶段

可以被细分为如下几个功能阶段:模型/视点变换、顶点着色、图元装配、投影、剪裁、屏幕映射等,经过几何阶段变换且投影过的顶点以及它们相关的着色数据输入到光栅化阶段。

光栅化阶段

可分为:建立三角形阶段、遍历三角形阶段、像素着色阶段以及融合阶段。光栅化阶段对所有剪切区域内的图元生成片元数据,然后对每个生成的片元都执行一个片元着色器,最后经过深度测试等逐片元操作后被显示到屏幕窗口上。

      1. 座标系统和座标变换
  1. 局部空间座标系/物体空间座标系:对象所在的座标空间
  2. 世界空间座标系:一个全局的座标。所有的物体/模型需要经过旋转、平移、缩放从局部世界座标转换到世界空间座标。
  3. 摄像机/观察空间/视点座标系:从摄像机的视角所观察到的空间,包括平移/旋转
  4. 裁剪座标系:通过投影矩阵将指定的座标范围以内的座标转换成裁剪空间内的座标,在[-1, 1]范围内,同时范围以外的座标将被转换成[-1, 1]以外的座标,从而被裁剪掉。
  5. 标准化座标系
  6. 屏幕座标系:即每个像素点的座标,它是由视口变换得来的。

座标变换:物体座标系通过模型变换(modeling transformation,位移、缩放、旋转)到世界座标系,世界座标系通过视点变换(viewing transformation)到摄像机/视点座标系,视点座标系通过投影变换(projection transformation)到裁剪座标系,透视除法,进入NDC座标系(标准化设备座标系),目的是将座标值控制在-1到1之间,再通过视口变换(viewport transformation)将座标转换到屏幕二维座标。

      1. 齐次座标系优势
  1. 使用齐次,可以将三维空间一个点和其方向区别开,例如(1,1,1)在三维中可能表现在一个点 或者一个方向,但是在齐次中,可以会用w进行表现,如果w为非零表示点,w为零表示方向 (表示点和方向方便)
  2. 有齐次后,对物体做任何的干预变换,任何的仿射变换(平移旋转缩放透视投影)都可以通 过矩阵乘向量的方式计算,如果是三维,操作可能就有很多个,例如平移是矩阵加向量,旋转 是矩阵乘向量(可以做预计算)
    1. 光线追踪
  • 主要思想:从视点向成像平面上的像素发射光线,找到与该光线相交的最近物体的交点,如果该点处的表面是散射面,则计算光源直接照射该点产生的颜色;如果该点处表面是镜面或折射面,则继续向反射或折射方向跟踪另一条光线,如此递归下去,直到光线逃逸出场景或达到设定的最大递归深度。

 

  • 局限:通常将每条光线当作独立的光线,需要每次都要重新计算,现有计算资源,无法实现
  • 升级版:路径追踪:从视点发出一条光线,光线与物体表面相交时,根据表面的材质属性继续采样一个方向,发出另一条光线,如此迭代,直到光线逃逸出场景或达到设定的最大递归深度。然后用蒙塔卡洛方法,计算光线贡献,作为颜色值。

简短: 路径追踪 = 光线追踪 +  蒙特卡洛方法

      1. Ray tracing pipeline on GPU
  • GPU device code(也叫”shader”,着色器)

显卡上执行的程序在图形学中叫着色器CUDA也是执行在GPU上的,叫kernel

进行光线跟踪需要有五个shader,这五个shader都是执行在GPU上面的,分别是:

Ray generation shader:生成光线

Intersection shader:光线和平面求交

Miss shader:如果光线和场景没有求到交点应该进行什么操作

Closet-hit shader:如果光线和物体求到最近的交点之后应该进行什么操作

Any-hit shader:光线和物体任何求到任何一个交点之后应该进行什么操作

  • CPU host code(也叫 graphics API)


首先由ray generation shader生成光线,遍历场景,由intersect shader进行找到光线与几何物体相交进行相交测试,若找不到最近的相交加速结构或者没有相交,则重新进行相交测试,当找到最近的交点,使用is opaque(一种内置结构)判断是否透明,若不是则为需要节点跳到[2],若透明使用any hit shader判断交点是否要使用),若不需要该点则重新相交测试,否则跳到[2]
[2]在这个交点使用closet-hit shader(这个shader是光线的属性,每个光线有不同的closet-hit shader),如果光线与所有几何物体不相交,那么执行miss shader(该shader由指定的每根光线)

    1. 加速结构

主要包括基于空间的划分和基于物体的划分方式

  • 基于空间的划分(存在的问题:如果一个物体属于不同节点,如何处理)

一个物体可能属于多个子空间。四叉树、八叉树、kd树,BSP(Binary Space Partition),主要应用在KNN Search或ray tracing,也可以用于碰撞检测/邻域搜索

四叉树、八叉树:每次划分过程都对空间进行均匀的四(或八)等分,不考虑物体的分布

优点:划分简单,算法复杂度低,建树快(四叉树用于二维空间、八叉树用于三维空间)

缺点:没有考虑物体的分布,物体在子空间中的分布不均匀,查找效率较低,在建树完成后树中会有很多空节点,浪费空间

kd树(重点)进行空间划分时,可以自由选取划分轴、划分位置以及终止条件。一般根据物体的分布来进行空间划分

优点:可以根据物体的分布来进行空间划分,物体在空间中的分布较均匀查找效率高

缺点:划分过程考虑因素多,算法效率较低,建树慢,更新代价高

BSP树:二叉空间分割树,是一种常用来判别对象可见性的空间数据结构,每个节点表示一个有向超平面,将当前空间划分为前向和背向两个子空间,与kd树类似,但划分轴可以不垂直于座标轴,也不关心面的位置在什么地方,只要能够把空间划分成两个子空间

优点:比kd树更灵活,查找效率更高

缺点:划分过程还需考虑划分轴的方向,算法效率低,建树慢,更新代价高

总结:KD树与BSP树的建树耗时大,使得这两种方法都不适合动态场景

  • 基于物体的划分

空间之间可能有重叠。包围球、AABB、OBB、凸包、BVHBB(Bounding Box)=BV(Bounding Volume)

包围球:使用球体来包围物体

优点:相交测试,当物体发生旋转时,不需要更新

缺点:包围紧密度低,当物体发生形变时,需要重新计算

AABB(重点): Axis Aligned Bounding Box使用平行于座标轴的长方体来包围物体

优点:座标轴对齐的包围盒,相交测试快,当物体发生形变之后,仅需对变形了的基本几何元素相应的包围盒计算一次

缺点:紧密性较差,对倾斜对角方向放置的瘦长型对象,会留下非常大的边角空隙,导致大量不必要的包围盒相交测试,不能随物体旋转

OBB:使用不一定平行于座标轴的长方体来包围物体,与AABB不同的是,它不一定平行于座标轴,由物体的几何特点来决定它的朝向

优点:紧密性较好,可以大大降低参与相交测试的包围盒的数目,整体性能优于AABB和包围球,当物体发生旋转运动后,仅需对OBB进行相同的旋转

缺点:计算复杂,重建代价较大

凸包:使用凸几何体来包围物体

优点:紧密性非常好

缺点:相交测试非常复杂,计算代价大,凸包计算很难,碰撞检测很难。

 

BVH(重点)层次包围盒/体,核心思想:用体积略大而几何特征简单的包围盒来近似地描述复杂的几何对象,进一步提高求交效率。常用于层次视锥体裁剪,整个物体是根节点,依次迭代地将物体二等分放入左右孩子节点当中,树中所有节点都使用包围球。树中同一层的所有包围盒集合起来与整个物体的形状类似

优点:紧密性好,相交测试快,相比于kd树更新速度快

缺点:计算代价大

总结:使用BV的准则/目标:

1.包围核应把物体包的越紧越好

2.包围核更新代价越低越好

3.包围核在做碰撞检测的时候,计算过程尽量简单

      1. 采样问题-走样

光线追踪属于点采样,每个像素投射一条光线,引发走样失真

解决方法:超采样(supersampling),尽可能多采样,使用平均结果(可以降低反走样,但不能消除它)

  • 均匀采样

优点:所有区域都能被均匀采集到

缺点:存在不必要的采样

  • 随机采样

优点:随机生成样本,避免了均匀采样的规律性

缺点:有些区域存在不必要的采样,有些必要采样的区域可能没有采样到,不可控

  • 泊松采样

优点:产生随机的样本,两两样本之间不会太近

缺点:耗时相对更长

  • 自适应超采样

优点:不需要超采样所有的像素,采样在边角和中心,能够有效地减少走样

缺点:耗时长

  • Jittered采样:将像素分成网格,在每个网格内使用泊松采样

    没有提高采样率,但移除了规律性

  1. 反走样技术
      1. 产生走样原因

如果在数学上想要避免走样,那么采样必须满足奈奎斯特(Nyquist)采样定理(如果想重建原始图像,采样频率应该是采样信号最大频率的2倍之上),才能在数学上有可能把原始的信号完美地重建出来。而图形学上常使用点采样(用点采样渲染场景就不可能避免反走样问题),本身就不能够满足奈奎斯特采样定理,所以图形学上有很多反走样的方法。

简单点:(重建与采样频率不匹配,采样频率太低)

造成走样的两个主要原因有:1、对几何函数的采样不足,也就是常见的边缘锯齿(也叫几何走样),一般发生在光栅化阶段。2、对渲染方程的采样不足,因为渲染方程也是一个连续函数,对某些部分(比如法线,高光等)在空间变化较快(高频部分)采样不足也会造成走样,反映在视觉上一般是图像闪烁或者噪点,这类称之为着色走样(Shading Aliasing),一般发生在着色阶段。

      1. 反走样方法

基于几何的反走样方法,分为三类:基于屏幕的反走样方法(基于超采样的反走样方法)、基于时间的反走样方法(Temporal antialiasing,TAA) 、基于形态学的反走样方法。

基于屏幕的反走样方法:

SSAA(Supersampling Anti-Aliasing)超级采样反走样方法:通过以更高的分辨率来采样图形,然后再显示在低分辨率的设备上,从而减少失真。

特点:提高了存储空间和计算量,代价昂贵,但简单,高质量

MSAA(Multi-Sampled Anti-Aliasing)多采样反走样方法:是对SSAA的改进,改进之处在于执行片元着色器的次数并没有明显增加,对边缘部分却进行了很好的反走样,随机采样。对于每个像素,不要仅用一个中间点来判断三角形是否覆盖,而是取4个顶点来分别判断:

基于时间的反走样方法:将样本分散到多个帧中

基于形态学的反走样方法MLAA(Morphological antialiasing)形态抗锯齿

简单总结:对于静态场景可以用历史数据,动态场景利用Motion Vector来使用历史帧

      1. 走样的场景

纹理映射  光线追踪 shadow map

  1. 光照
    1. 微表面模型

眼睛上看起来光滑的平面,实际上是由很多微小的平面构成,这些微小的平面对于光的波长来说是不平的。但是每一个微小的平面,对于光的波长来说,是一个绝对光滑的平面,即完美地符合反射定理。所以对于每一个微平面来说,一束入射光会在微平面反射形成反射光或进入介质形成折射光。而对于整个宏观的平面来说,一束入射光被反射出来的光就有了不同的朝向,就产生了反射的光;而进入物体的折射光,在物体内部进行多次反射后从某一点反射出物体的表面,就产生了次表面散射的光

specular、diffuse、次表面散射形成的原理:

  • specular:入射光在表面直接反射的光
  • diffuse:入射光在表面经折射、吸收、散射、多次反射而形成的光
  • 次表面散射:在某一个点入射的光,折射进入物体内部后经多次反射从物体表面的另一个点反射出来的光
    1. 辐射度量学

Radiant flux (Ф, 辐射通量): flow of radiant energy over time (unit: W)

Irradiance (E = d Ф/d A, 辐射照度): density of radiant flux with respect to area (unit: W/m2)

Radiant intensity (I = d Ф/d ω, 辐射强度): flux density with respect to solid angle (unit: W/sr)

Radiance (L = d2 Ф/dAd ω, 辐射亮度): density of radiant flux with respect to both area and solid angle (unit: W/(m2sr))

f(l,v) = radiance/Irradiance

    1. BRDF

定义:双向反射分布函数 ,定义为出射辐射率的微分(differential outgoing radiance)和入射辐照度的微分(differential incoming irradiance)之比,描述了入射光线经过某个表面反射后如何在各个出射方向上分布,给定了入射方向和出射方向能量的相对量

1.对于给定的方向,BRDF给出了来自每个入射方向的光对出射光的相对贡献。

2.给定一束来自某个方向的光线,BRDF给出了反射光和散射光在表面上所有出射方向上的相对分布。

BRDF描述了两种不同的物理现象

表面反射-镜面反射    次表面散射-漫反射

BRDF模型分为两大类

  • 经验模型(简单的、常用于实时渲染、朗伯特模型、冯氏模型)
  • 基于物理的模型:

Lambertion(朗伯特模型):用作理想的漫反射模型(光均匀的反射到各个方向)。

冯氏模型:从物体上的一点发射到观察者眼睛的光能包括三个部分:环境光、漫反射、高光反射。

    1. 直接光照与间接光照(全局光照)

全局光照(直接光照+间接光照):考虑环境中所有物体表面和光源相互作用的照射效果,模拟真实光照规律,真实感强,计算代价高

直接光照:只考虑光源到物体表面的照射效果,物体表面的颜色只由它本身的材质/位置/光属性等影响,不能产生阴影和多重反射效果,真实感弱,计算代价低

    1. 延迟渲染Deferred Rending/Shadering

在出现延迟渲染之前,已经出现的渲染方法:

  • per-vertex shading在per-vertex shading中,光照计算发生在三角形图元的顶点处,即光栅化钱的vertex shader中。在光栅化之后,片元的颜色值由三角形图元的三个顶点的颜色值经过差值得到。

优点:优于顶点数量少,故其计算量小

缺点:在vertex shader中计算光照,通过光栅化之后得到的是线性插值后的光照效果,而实际上光照效果应该是非线性的,所以得到的结果不够真实。

  •  per-pixel shading在per-pixel shading中,光照计算发生在光栅化后生成的每个片元上,即光栅化之后的fragment shader中。

优点:把光照计算放在片元中,而不是差值生成,保证光照正确。

缺点:在fragment shader中是对场景中的所有片元都尽心光照计算,而物体之间存在遮挡关系,最终显示在屏幕上的只有离屏幕最近的片元,被遮挡的片元无法通过深度测试而被抛弃,这部分多余的光照计算导致计算资源的浪费。

  • 延迟渲染(两个pass过程)

几何处理阶段:先对场景进行渲染,然后将能通过深度测试的片元信息存储在G_buffer中;

光照处理阶段: 只需渲染出一个屏幕大小的二维矩形,使用第一步在G_Buffer中存储的数据对每个片段计算场景的光照

优点:1.只渲染可见的片段,节省计算量 2.将光源的数目和场景中的物体的数目在复杂度上完全分开,可以处理大量的光源,保持一定帧率,降低复杂度

缺点:1.G_Buffer保存了多个纹理,内存开销大 2.读写G_buffer的内存带宽是性能瓶颈

3.透明物体渲染不能解决 4.对多重采样抗锯齿MSAA支持不友好

改进方向:1.最小化G_Buffer结构(Light Pre_Pass) 2.分块延迟渲染(Tile_Based Deferred Rendefing

  1. 高级纹理
    1. 纹理映射Texture Mapping(增加颜色质量)

思想:用少量的信息表示复杂的几何表面信息

特性:1.复用性 2.向GPU传输少量数据,让其尽可能多运算

问题:纹理走样(纹理分辨率低或者纹理分辨率高会出现的问题)也可以说是像素的大小和纹素的大小不匹配引发的问题/

解决方法:

1.若纹理过小(分辨率低,像素大小<纹素大小),会导致走样失真(屏幕空间的几个像素点对应在纹理贴图的座标上都是集中在一个像素大小之内),通过双线性插值解决

 

2.若纹理过大(分辨率高,像素大小>纹素大小(屏幕空间的一个像素对应了纹理贴图上的一片范围的点)), 反采样会很麻烦,其实就是欠采样:

  1. Supersampling:一个像素内多采集样本点
  2. 通过Mip-map =>目的:将像素大小大于纹素的大小反转成像素大小小于纹素情况

基本思想(方法):提前对纹理进行滤波,相当于低通滤波器(把高频过滤)

    1. 高级纹理映射技术Model geometry:增加渲染质量
  • BumpMap Bump技术通过一张称为高度图的灰度图来存储物体表面每一点(像素)的高度信息,在对物体表面某一点(像素)进行光照计算前,先在高度图中查找与该表面位置相对应的高度,然后根据高度信息重新计算该点处的法线向量,最后对这一点进行光照计算。

缺点:1.只能用于漫反射表面,不能表现镜面高光

2.没有改变物体几何信息,因此物体边缘并不会有凹凸效果

  • Normal Map 将物体表上面的法线信息以X,Y,Z的形式代替RGB值存储在纹理中,根据物体法线贴图中的法线向量来进行光照计算。

优点:法线贴图要快得多,消耗的资源也更少,因为几何图形不变。

缺点:1.法线贴图的主要限制是,它只会扰动表面的法线,物体边缘不会有凹凸效果

2.当视角接近平行时,无凹凸感(Bump Mapping也是)

       (保存低分辨率的模型,通过高分辨率的法线贴图扰动,得到高分辨率模型)

  • Parallax Mapping:根据观察方向和高度贴图修改纹理座标,使一个fragment的表面看起来比实际的更高或者更低(同法线贴图一样,区别是除了存储法线信息,还存储了与之对应的BumpMapping高度图)
    缺点(和NormalMapping一样):1.当视角接近平行时,无凹凸感 2.边缘仍是平滑的:
    优点:会根据视角调整纹理映射的偏移,从而产生遮挡效果。
  • DisplacementMapping 类似于法线贴图,位移贴图的每一个纹素中存储了代表对应顶点的位移的向量。根据Displacement Mapping中采样的结果,对顶点高度进行移位,真正改变了顶点信息,由此产生凹凸效果。
    优点:能产生真正得凹凸表面,这是边缘和阴影也是凹凸的。
    缺点:平面必须由很多顶点组成才能获得真实感,由此将带来巨大的计算量,增加负荷。

总结:BumpMap和Normal Map最大的缺点:在物体的边缘部分是看不到真正的凸起(无法做自遮挡,自阴影)无法得到突起的阴影

    1. Shadow Mapping(阴影贴图)

基本原理:确定场景中某个着色点是否对视点可见,在光源下不可见。

基本流程:两次渲染

  1. 将场景的深度值预先渲染到以光源位置为原点、光线发射方向为观察方向的投影座标系中,形成深度纹理。
    2、再次渲染场景的过程中,将每个片(像素)变换到前述眼座标系中,并缩放到[0,1]的范围内以便查询纹理。
    3、以当前片在眼座标中的S、T座标查询深度纹理获得深度值,将此深度值与当前片断的Z座标进行比较,若Z座标大于深度值,则当前片断在阴影中;否则不在
    存在问题:
  1. 走样问题(采样率不足):原因:shadow mapping还是基于texture mapping技术,会遇到与之相同的走样问题(看纹理映射)
  2. 深度比较时的问题精度问题):原因:深度纹理的分辨率有限
  3. 整个场景需要绘制两遍,很耗时的操作
    1. 硬阴影和软阴影
  1. 硬阴影:阴影是半影和全影组成,当光源为点光源时,就不会存在半影,这种阴影就称为硬阴影,现实中,光源都是有大小的,不错在硬阴影,,但在图形学中很常见1.阴影要么在内部或在外部 2.由点光源生成(本影3.实践中不存在,但易产生
  2. 软阴影:当光源时面光源或体光源时,会存在半影和全影,更加现实和普遍
  1. 帧缓冲

帧缓冲由像素的矩形阵列组成,每个像素都可以在图像的该点上显示一个很小的颜色正方形,主要有:颜色缓冲  深度缓冲 模板缓冲(Stencil buffer)

颜色缓冲主要存储每一个像素的RGB颜色值,同时也可能存alpha值。多个颜色缓冲可能存在一个帧缓冲中

深度缓冲:存储每个像素的深度值,其取值范围为[0,1],使用深度值可以用于深度测试,遮挡剔除,模拟透明物体,混合图片等

模板缓冲:存储模板,用于模板测试

帧缓存目的:记录当前所看到的最近的片元

方式:存储片元,发现有更近的,放入,已有的,抛弃

  1. 敏捷开发总结

基本思想:敏捷开发以用户需求为核心,采用迭代、循序渐进的方法进行软件开发。
将软件开发周期分为若干个迭代周期。每个迭代周期以实现某些用户功能为目标每个迭代周期都有需求分析,架构设计,编码和测试。通过持续交付可用软件频繁从用户那里获得反馈,以消除各种不确定性

自己在敏捷团队中的不足/原因/改进

  • 前期对工作量估计不准,投点不准,任务有时需要熬夜去完成,不能对工作任务做合理拆分打包

原因:前期刚接触项目组,对项目不了解,对项目困难度有了错误认识,忽略了项目执行过程中的一些不确定因素,对任务投点不准。另外,平时对工作日志的记录不是很准确,一般只是记录个大概完成时间,造成了历史数据失去了可靠的参考性。最后,团队成员讨论不充分,由于学生总是尽可能放宽适合自己的要求,导致团队成员对任务投点时,只是大概说一下自己的看法理由,有时投完点就各自领任务。

改进:1.要准确详细记录自己的工作日志,不能把它当成应付工作,随便填写,不能只把它只当成”数据“,记录下来就要充分发挥其作用。要追求真实可靠,坚信今天你欺骗数据,明天数据也会欺骗你。

  1. 团队要充分讨论再投点:项目组人员能力肯定参差不齐,对任务的估计也不会完全相同,因此成员要充分讨论任务的实施细节,实施难点,让成员充分认识任务困难度,然后再独立估计,并讲述理由。为了防止流于形式,建议有监督人员参与,对讨论做记录
  • 对用户需求理解有偏差,考虑不充分就开发,当需求改动时或结果不符合用户的预期要求就得推倒重

原因:没有养成基于测试用例的开发驱动习惯,拿到任务时,总想着先把功能实现了之后才去补测试用例,这样也违背了编写测试用例的初衷

改进:首先养成测试用例先行的项目开发思维,及时编写测试用例让用户尽可能看到最终的大概项目效果,这样也可以提前规避风险,防止对用户需求理解有偏差,理解有歧义,让已做的工作付之东流。

  • 项目研发进度不一致,对自己完成任务以外的其他工作了解不够

原因:缺少一定量的工作进度汇报,大家只会对自己的工作有了解,对项目其他成员的工作知之甚少

改进:团队是一个整体,每个项目成员都应该对项目有着一定的认识,平时,成员内部可以有个简短的工作进度汇报,一方面起个互相监督的作用,另一方面也可以让其他成员对你所做的工作有一定的了解,这样也可以防止当成员发生改动时,工作无人能去做的局面。

总结:敏捷开发追求的不仅仅是快速,更是提前规避风险。

附加:

Scurm:敏捷是一种指导思想或开发方式,没有明确告诉我们到底采用什么样的流程进行开发,在敏捷的理念下.衍生出了很多不同敏捷软件开发方法,Scrum是敏捷开发的具体方式,起源于软件开发项目,但它适用于任何复杂或创新性的项目。用于开发和维持复杂产品的框架 ,是一个增量的、迭代的开发过程,使用产品Backlog来管理产品需求,整个开发过程由若干个短的迭代周期组成,一个短的迭代周期称为一个Sprint在Sprint中,从产品Backlog中挑选最高优先级的需求进行开发,挑选的需求在Sprint计划会议上经过讨论、分析和估算得到相应的任务列表,称为Sprint backlog,在每个迭代结束时,递交潜在可交付的产品增量。

敏捷软件开发法和瀑布法之间的区别:

1.其中之一就是质量和测试方法。在瀑布模型中,构建阶段之后总是有单独的测试阶段; 但是,在敏捷软件开发测试中,与编程相同的迭代完成。

由于测试是在每一次迭代中完成的-开发一小部分软件,用户可以经常使用这些新的软件并验证其价值。用户知道更新后的软件的真实价值后,可以对软件的未来作出更好的决策。在每次迭代中进行一次价值回顾和软件重新计划会话 - Scrum通常只有两个星期的迭代循环 - 帮助团队不断调整自己的计划,以最大限度地提高其价值。 遵循与PDCA循环类似的模式,因为工作已经计划、完成、检查(在审查和回顾中),并且任何商定的变更都会被运行。这种叠方法支持产品更甚于项目思维。这在整个开发过程中提供更大的灵活性; 而在项目中,需求是从一开始就定义和锁定的,以后很难改变它们。迭代开发允许软件产品根据业务环境或市场需求的变化而发展。由于敏捷软件开发的迭代方式较短,因此与精益创业概念有着密切的联系。

2.敏捷开发区别于瀑布式的特征很明显,敏捷开发是以一种迭代的方式推进的,而瀑布模型式是最典型的 预见性的方法,严格遵循预先计划的需求分析、设计、编码、集成、测试、维护的步骤顺序进行,步骤 成果作为衡量进度的方法,例如需求规格,设计文档,测试计划和代码审阅等等。敏捷开发过程中,软 件一直处于可使用状态,它将项目分成若干相互联系、可以独立运行的子项目,因此,每个阶段软件都 是可见的,客户可以直观的体验并提出意见。如果按照瀑布式流程,客户可能在签订开发合同3个月 后,看到的还只是各种文档(需求文档、设计文档、详细设计文档等等),客户心理或许会不踏实。瀑 布式的主要的问题是它的严格分级导致的自由度降低,项目早期即作出承诺导致对后期需求的变化难以 调整,代价高昂。瀑布式方法在需求不明并且在项目进行过程中可能变化的情况下基本是不可行的。在 瀑布式开发中,需求修改的时间越靠后,成本越大,所以需求分析人员的压力很大。由于敏捷开发是迭 代式的,,并且迭代周期较短,因此很容易相应新需求或是对旧需求的修改。瀑布式开发有很多文档,

但敏捷开发不是没有文档,而是轻文档。在敏捷开发过程中,适量的文档还是很有帮助,有助于整理思 路,加快沟通和讨论,比如概念设计文档、架构图、SWOT分析文档等等,这些文档在每个产品版本开 始之前会有产生,在每个迭代的过程中根据业务人员和市场的反馈也会有一些变更。通过实践证明,这对产品的思路、沟通讨论都非常有帮助。而且这些文档,大多是几页PPT,书写和维护工作都很小。 相比迭代式的增量开发,相同的是两者都强调在较短的开发周期提交软件。基于Scrum的迭代增量开 发一般会在一个比较长的一个迭代周期频率下不断交付,同时迭代中不允许有变化的需求,这样就有一 些场景让这种迭代很困难,例如紧急的技术支持、临时增加的非常高的优先级的需求等等,另外项目的 估算非常难,导致不容易承诺。相比较,敏捷方法的周期可能更短,并且更加强调队伍中的高度协作。 敏捷开发的原则之一是拥抱变化需求时刻在变,人们对于需求的理解也时刻在变,项目环境也在不停的 变化,因此你的开发方法必须要能够反映这种现实,敏捷开发方法就是属于适应性的开发方法,而非预 设性。另外,敏捷开发更适用于小型团队,在一个办公室工作,属于那种通信基本靠吼的状态,当然团 队成员之间的交互会更方便。另外敏捷开发强调用户(或用户代表)要与开发团队在一起工作,便于及 时沟通交流。重视交互也应该可以算是最明显的区别之一。这样还有一个好处,就是有利于团队中知识 的迅速传播。即使有人离开团队,另外的人也能完成相应的工作。因此,“人与交互”被列为敏捷开发价

值观之一,并排在第一位。

 

瀑布模型:瀑布模型的线性特征也是它问题的根源。瀑布模型总是试图做好一件事情之后才做下一件事,但是错误 是不可避免的。可以看出,在整个开发过程中,只有在最后的部署阶段才能让客户看到这个软件。而通 常需求分析阶段是最容易出现错误的阶段,所以很可能最开始的错误会一直流传到最后才会被发现,这 意味着我们必须要更改所有的活动以求改正错误,同样的问题还会出现在需求变更时。 增量模型问题:在开发过程中,需求的变化是不可避免的。增量模型的灵活性可以使其适应这种变化的 能力大大优于瀑布模型和快速原型模型,但也很容易退化为边做边改模型,从而使软件过程的控制失去 整体性。 如果增量包之间存在相交的情况且未很好处理,则必须做全盘系统分析,这种模型将功能细化后分别开

发的方法较适应于需求经常改变的软件开发过程。

敏捷开发的缺点: 

1.采用敏捷开发,对开发团队的人员素质要求比较高

敏捷开发的首要任务是快速,目前提出的"全栈软件工程师",它要求软件开发工程师在开发的各方面,即从需求,设计,编码,软件测试一直到系统搭建都要求是行家里手,这样可以减少因彼此沟通带来的时耗,这才能保证他在一个Sprint中能独立完成产品中某个特定的任务。显然这样的软件开发工程师的素质一定要求很高的,而在软件开发行业中,人员流动率高,新手多的情况下,要做到这一点是比 较困难的。

2.采用敏捷开发,开发工程师与软件测试工程师混为一体,彼此分工不明晰

敏捷开发要求软件开发工程师会软件测试,软件测试工程师会软件开发,这实施起来是比较困难的。因为软件开发和软件测试工程师关注的重点是不同的:开发关注技术实现比较多,一般都采用正向思维;而软件测试关注业务比较多,多采用逆向思维。所以一个产品要保证有高的品质,就必须要有独立的软件测试工程师,因此测试和开发要有比较清晰明确的分工。正如古话所说:"闻道有先后,术业有专攻"。

3.采用敏捷开发,是"短平快"的开发方式,由于产品发布周期短,所以产品的软件测试、维护、升级等操作的频率也增加了这必然增大开发工程师、软件测试工程师以及运行维护工程师的工作压力,在这样高压的环境下工作很容易出错,从而影响产品的质量。

4.采用敏捷开发,不利于文档的建立和修改

敏捷开发有一句口号"拥抱变化"。然而客户需求的变更是经常变化的,正如当今社会流行的"唯一不变的是变化"。为了缩短版本发布周期,特别是在版本发布之前,当客户的需求发生变更时,敏捷开发团队仅仅是修改代码而没有时间修改所对应的文档,这就造成了产品和文档的开发不一致性这就给产品的后期优化、调整或二次开发,带来了极大的麻烦,在人员频繁流动中更是灾难性的。

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章