3D基础编程笔记(一)

概念篇

DirectX 9.0,C++

作为3D编程菜菜,经同事指点若须打好基础,应从DirectX3D开始,因为D3DX对于3D编程的封装没那么高级.同样一个功能 D3DX往往需要几个函数,而OpenGL等则一个函数搞定,太高级的封装反而隐藏了原理.(大家都会用cocos2d-x,而且用得很溜,试问又有几个能拍胸脯说真正理解其内部原理呢.)下面记录一些常用概念,主要方便自己查询.

什么是引擎

引擎是什么?大家在游戏开发中肯定会遇到的,在日常同行交流中 首先问的估计也是:你们项目用的是什么引擎啊?用cocos2d-x?用U3D?用虚幻4?用CryEngine?用godot?那为什么要把他们叫做引擎呢?说到引擎一般有三种东西:

  • 机器发动机

汽车的引擎也叫发动机,因为那是整个汽车的动力源泉.

  • 搜索引擎

搜索引擎指自动从因特网搜集信息,经过一定整理以后,提供给用户进行查询的系统。

  • 游戏引擎

游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些互交式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程序而不用由零开始。大部分都支持多种操作系统平台,如Linux、Mac OS X、微软Windows。游戏引擎包含以下系统:渲染引擎(即“渲染器”,含二维图像引擎和三维图像引擎)、物理引擎、碰撞检测系统、音效、脚本引擎、电脑动画、人工智能、网络引擎以及场景管理。

我们关注的显然是游戏引擎,一句话概括:游戏引擎就是一整高级编程组件.

0D1D2D3D4D

普遍的理解是:

0D 一个点;

1D 一条线;

2D 一个平面;

3D 一个立体空间;

4D 在3D立体空间上再加一个时间线

很多4D是在3D的基础上加其他属性 例如震感,落花流水,4D电影与3D电影的主要差别就是增加实际环境元素,让人更身临其境,4D还有一个更实际的应用 就是4D电视,通过佩戴不同频率的眼镜 同时观看一个电视屏幕 但是看到的确实不同的电视台节目,这样就实现了 同时间 但是不同空间.

齐次坐标

就是将一个原本是n维的向量用一个n+1维向量来表示,例如三维坐标 (x,y,z)表示为(x,y,z,w).限定为当w为0时候 表示一个向量,w为1时为一个点.当w为1的时候 (x,y,z,w)可用(x/w,y/w,z/w,1)表示,代表的是不同平面的一系列点..只是这些点都有一个特征:在w=1的平面上的投影都是(x,y,z,1).由此引出了3D投影的概念

虚拟摄像机

3D游戏中的虚拟摄像机和现实生活中的摄像机非常相似:功能都是通过一个角度去观察物品,使物品成像.也可以理解为眼睛.只要是一个实体 例如生活中的杯子,无论是谁也只能看到杯子的部分.没有人能360°无死角的看到杯子.3D游戏中的物体也是如此.虚拟摄像机只能截取显示3D物体的部分.与眼睛有视力限制相同的是 虚拟摄像机 也有”视力”.这种”视力”叫做可视体.

  • 眼睛所能看清的东西是有距离限制的,同样的虚拟摄像机也有,叫做平截头体,由前截面和后截面组成一般都设置z = [1,1000]的范围内.
  • 眼睛所能看到的地方是有视角限制的,总不能看到后背吧,同样的虚拟摄像机也有可视角度,比较抽象的是:设置的可视角度越大 相同位置的物体显得越小.因为角度越大 设备的屏幕并没有变大,渲染出来的物体就会显得越小了.这一点和 相机的镜头焦距调整功能有点象.

摄像机可以有6种变换,目前的所有3D游戏摄像机都是使用了其中的1种或者N种.

以下的XYZ轴 并不是世界坐标中的 而是摄像机坐标中的三个坐标轴

  • Pitch 倾斜 绕着Z轴旋转 在现实中最简单的例子 就是歪脖子看物体
  • Yaw 偏航 绕着Y轴旋转 在最简单的例子就是 打魔兽的时候鼠标不小心移动到屏幕左右边缘 看到整个游戏在转动
  • Rol 滚动 绕着X轴旋转 举个例子 在骑马与砍杀中 按住鼠标右键移动鼠标 可以看到天空底面
  • Walking 移动 沿着Z轴移动 举个例子 骑马与砍杀中控制英雄前进或者后退,可以看到场景所有物体在靠近或者远离自己
  • Strafing 平移 沿着X轴移动 举个例子 骑马与砍杀中 控制A或者D左右调整为止,
  • Flying 飞行 沿着Y轴移动 这个最简单了,剑网3中的轻功技能,释放的时候 整个人都飞了起来 就是通过控制 Walking 和 Flying实现的

视图

投影

将3D场景转化为2D显示到屏幕上,这种从N维转换到N-1维的过程就叫做投影.3D游戏 大家所看到的每一个画面都是投影所得.3D编程中用到的投影 一般都是透视投影.因为透视投影可以使物体投影到屏幕可以根据距离来决定大小.更具真实感觉.

色彩

色彩分为 RGBA,我们之所以能看到五颜六色,主要是由于不同的物体吸收了不同的颜色.例如 植物是绿色,那是由于植物这种物质吸收所有的灯光颜色 除了 绿色光.

灯光

主要有三种灯光.

  • 环境光(Ambient Light),这种灯光能被场景里所有物体反射 且照亮全场,例如物体的各个部分都能被照亮.现实生活中 可以理解为白天室内日常光亮
  • 漫反射(Diffue Reflection) 这种灯光按照传输方向特殊传播,漫射光在所有方向上都均匀的反射.
  • 镜面反射(Specular Reflection) 这种灯光按照传输方向特殊传播,在特殊的方向才可反射.

材质

材质(Meterial),材质可以看成是材料和质感的结合。在渲染程式中,它是表面各可视属性的结合,这些可视属性是指表面的色彩、纹理、光滑度、透明度、反射率、折射率、发光度等.

纹理

纹理(texture)是材质的子集,纹理映射是一种允许我们为三角形赋予图像数据的技术.纹理中每个元素(texel)都通过 纹理坐标系统表示(u,v),坐标原点 在 左上,在游戏中我们可以直接通过一个图片文件来创建纹理.

光栅化

光栅化就是计算每个面(三角形)中的每个点的颜色值的过程.

裁剪

拣选超出可视范围的几何图形的过程 叫做裁剪,裁剪分为三种情况:

  • 完全在可视范围内 则保持渲染不变
  • 完全不在可视范围内 则被拣选 不会被渲染出来
  • 部分在外部分在内,则超出可视范围的部分 不会被渲染出来.

裁剪一定程度上提高了渲染效率

顶点法线

Vertex Normals,顶点发现能够确定灯光照射到物体表面的角度,并且计算每个顶点的灯光.例如某个圆形物体,灯光照射过去 看起来象反光.反光并不是随便反光 而且根据每个顶点的顶点法线方向来反光.

光源

有了灯光 必须有光源才能够发出光.所以一般3D游戏引擎都有光源这种组件,拿Direct3D来说 它支持三种光源:

  • 点光源 这种光源在世界坐标中有一个位置且所有方向都照射光线 类似太阳
  • 方向光源 这种光源没具体位置 但指定方向发出平行光线,
  • 聚光灯 这种光源类似现实生活中的手电筒.有位置并且发出的光在指定方向上按照圆锥形照射.

缓冲区

缓冲区分为 顶点缓冲区 和 索引缓冲区.

  • 顶点缓冲区 是一块连续的存储了顶点数据的内存 通常保存在显存中,这个缓冲区主要记录的是渲染物体的全部顶点,每个顶点的大小由顶点属性决定,一般可以的是 立体坐标(x,y,z),顶点法线(nx,ny,nz),纹理坐标(u,v),颜色(r,g,b,a) 共 12个float 也就是 48字节.
  • 索引缓冲区 是一块连续的存储了索引数据的内存 通常保存在显存中,这个缓冲区主要是记录渲染顶点的顺序.是可选的缓冲区,每个索引大小都是int.所以一个索引大小为 4 字节.

一般情况下我们可以通过一个美术资源有多少个面(三角形)来计算这个资源在内存中占用多大的地方.例如一个有5000面的物体.一般 索引数 = 顶点数 = 面数.所以这个资源的大小为:

(5000x4 + 5000x48)/1024 = 260KB.

缓冲区 可以通过参数申请动态的和静态的,分别放在不同的地方,我们机器有三个地方可以存放数据:ACP 显存 系统内存,ACP供CPU写的速度很快,所以动态缓冲区一般都放在这里.静态缓冲区放在显存中.ACP是系统从系统内存(内存条)中借用的一块内存.一般来说 渲染普通物体的顶点索引数据都是静态的,但是对于粒子系统 变化频繁的顶点数据 则申请为动态的缓冲,存在ACP中.

缓存

渲染缓存一般分为三种:

  • Target Buffer目标(后备)表面缓存
  • Z Buffer 深度缓存
  • Stencil Buffer 模版缓存

着色

高洛德着色 - gouraud shading

高氏着色从名字上看,这个高氏(gouraud)其实是以研究该着色的Henri Gouraud来命名的。高氏着色又叫高洛德着色或高氏渲染(Gouraud Shading):这是一种光影渲染技术也是目前较为流行的着色方法,它可对3D模型各顶点的颜色进行平滑、融合处理,将每个多边形上的每个点赋以一组色调值,同时将多边形着上较为顺滑的渐变色,使其外观具有更强烈的实时感和立体动感,不过其着色速度比平面着色慢得多但是效果要好得多。高氏着色可以对多边形的顶点之间的颜色进行补间,高氏着色的计算负荷并不是太高,但是,可以实现很漂亮的渲染,所以经常被使用。Gouraud着色处理方法首先计算三角形每个顶点处的光照,然后用顶点颜色通过插值来计算三角形内部各点的光照。

平面着色 - Flat Shading

Flat着色处理方法以三角形为单位进行颜色计算,然后用各种颜色对三角形进行填充。平面着色是最简单也是最快速的着色方法,每个多边形都会被指定一个单一且没有变化的颜色。这种方法虽然会产生出不真实的效果,不过它非常适用于快速成像及其他要求速度重于细致度的场合 ,如:生成预览动画。

补色着色 - Phong Shading

补色着色的名字跟高氏着色一样,都是以人名(Bui Tuong Phong)来命名的。使用补色着色的话,会克服高氏着色的弱点,即使顶点数少的时候也能得到很自然的效果。Phong着色处理方法用三角形过顶点处的法向量通过插值的方式计算每个像素处的法向量,然后根据各个像素的法向量计算光照效果,补色着色是在像素之间对颜色进行补间

扫描线着色 - Scanline Renderer

它是一种基于一组连续水平线的着色方式,由于它渲染速度较快,一般被使用在预览场景中。

光线跟踪着色 - Ray-Traced

光线跟踪是真实按照物理照射光线的入射路径投射在物体上,最终反射回摄像机所得到每一个象素的真实值的着色算法,由于它计算精确,所得到的图象效果优质,因此制作CG一定要使用该选项。

未完待续

《3D基础编程笔记(一)》有7个想法

      1. 我也是业余时间学习,不过一直感觉效率很低,平时项目也用不到3d这块,有没有好点的学习路线或者书籍推荐下呢?先谢谢了

          1. 3Q,已经购买了,最近加班很严重,有空每天抽空

  1. 看了这篇文章,对 3D 的概念更理解了,有两个问题请教一下:
    1.资源占用缓冲区内存的例子,“一个有 5000 面的物体.一般 索引数 = 顶点数 = 面数”,三角面不是由顶点构成的吗,为什么顶点数 = 面数?
    2.面法线在这里并没有提及,它是一个无关紧要的元素么,可否解释一下它跟顶点法线有什么区别和联系?

    1. 抱歉 回复慢了Orz

      1.“三角面是由顶点构成的” – 正确,但是某一个顶点不仅仅是一个三角面的顶点,一个顶点有可能是三个三角面的共同顶点。
      2.面法线的确漏了,他们的主要会应用在光照上 ( shader, 渲染),如果说区别与联系 我能想到的是他们大多情况下是相同的,当他们不同的时候 说明相邻的面不是平整的

Rect进行回复 取消回复

邮箱地址不会被公开。 必填项已用*标注