一个小demo的开发日记
Posted Betairy linkzeldagg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个小demo的开发日记相关的知识,希望对你有一定的参考价值。
啊~Re: 0怎么这么赞啊~
啊~
=====================================================
好吧我知道我很久没更新了。
这不重要!EMT!
=====================================================
嘛,进入正题嗯ww
一、3D几何体的组成
在进入正题之前,请允许我先说些关于…嗯…怎么说呢,基础的东西。
说到底啊,游戏里用到的这些场景。
它们都是什么?
它们怎么组成的?
它们又是怎么被画到屏幕上的?
为什么我在场景中安放了几个光源,它们就能反光,有阴影,各种各样的效果?
我们都知道计算机程序是通过一行一行的指令执行的。那么上述这些过程又是怎么完成的呢?如果不清楚这个过程的话,是没办法对其进行"深入的改造"的 ——
个人认为,这个demo中如果不了解这些内容的话,是没有办法做出来的。
在这个demo里 ——
- 为了让树有平滑的生长过程,还要美观,我需要完全用程序生成这棵树的模型。
而且说到底我也做不出一个像样的树。大概…能做出一个正在长大的史莱姆。
- 为了让树叶能够好看一点,我希望我能够自己控制光照的计算。
而且Unity的PBR / GI我没自信在surface上不卡啊。还丑。
- 为了有一个赞的天空和日夜交替,我希望我能够自己计算整个天空是什么样子的。
而且Asset store里的东西太贵了。买得起的话谁自己写啊(误
- ……
(PBR:基于物理模型的渲染技术;GI:全局光照)
…所以,我需要自己搞。所以,我需要了解这个过程(上面提到的)到底是怎么进行的。
当然,忽略了诸多细节。
那么首先,我们需要表示出整个场景。这大概算是一个切入点吧。
不过在这个demo中我们不需要考虑场景的问题。Unity已经为我们做好了;我们只需要考虑场景中的某个物体的"形状""贴图"等等要素。
我们知道,在现今的渲染体系中,物体都是由一堆小面拼起来的。就像下面这个茶壶:
这一个个四边形面组成了茶壶。不过实际上我们关注的并非是面,而是面的顶点。如果我们调整顶点的位置,它会牵动一些面的变化,最终反应到茶壶形状的变化。
除了位置之外,顶点还有许多别的属性。比如给顶点设置一个"颜色"属性,那我们就可以给这个茶壶上色。而且随着顶点颜色的变化,茶壶表面的颜色也会相应的做出改变。
(下图是一个简化的例子,有三个分别为红色、绿色、蓝色的顶点。)
现在我们有顶点了。为了表示它们,让所有顶点的各项属性分别表示成成一个数组:
[ A的位置,B的位置,… ]
[ A的颜色,B的颜色,… ]
…
好了。但是现在,我们还只有一堆顶点,我们需要把它们组成一个面。为此,我们需要告诉计算机:那些点该组成一个面呢?
假设这里,面都是三角面。我们把它也表示成一个数组:
[ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, … ]
这表示:0-1-2是一个面,0-2-3是一个面,0-3-4是一个面,…
这里数字是顶点的序号,这个例子中A是顶点0,B是顶点1。
好,现在我们有整个模型了。该怎么画它呢?
这部分是显卡(图形处理器,GPU)的工作。首先,我们把这几个数组丢给显卡,随后——
显卡会把这几个数组里的数据转化为空间中的点,这些点具有它们的属性。
这个过程可以人为设定转换的过程,以及最后它们应该具有怎样的属性。这也是通过写一段小程序实现的,这个程序必须包含一个函数,这个函数接收传进来的一堆数组中的某一列,输出空间中这个点的位置,以及它的各种属性值。这段程序称为顶点着色器(Vertex Shader)。
随后,再经过几个可编程和不可编程的过程,这些点最终组成了面。
然后经过了一个叫做栅格化的过程,它们被映射到了一些像素上。有点像画图程序里拉出一个圆,随后它"落入"像素点中,变成一幅图的过程。
注意,到现在为止,这些像素还没有颜色。
不过这些像素各自拥有属性值,这些属性值是从上一步设置好的属性值中计算得出的:就像颜色的渐变一样,每个属性值都会经过"渐变"的过程,然后称为某个像素的属性值。
"渐变"的过程被称为插值。这是一个线性插值。
然后,我们得到某个像素的属性值,需要计算出这个像素该有的颜色。
这一步也是可以编程的。这个函数要实现的目的就是输入属性值,输出一个颜色值(RGBA),这被称为片段 / 像素着色器(Fragment Shader 或 Pixel Shader)。
最后再经过一些乱七八糟的过程(比如扔掉被挡住的顶点之类),最终成为图像呈现给我们。
在上面那个渐变三角形的例子中,颜色值随着顶点位置被传入,在顶点着色器中颜色值原封不动的传出,作为像素着色器的输入值(这时已经拥有渐变了);像素着色器再原封不动的把它输出,就成了那样一副图像。
上面是一个被简化过的渲染流程。
(想看真货吗www?)
不过其实我们大多数情况下,并不关心中间那一坨。所以也不要方w
那么,每个物体都是由什么组成的?
之前说过,物体由顶点组成,而每个顶点有着许多种属性。实际上,上文中用作例子的"颜色"并不是一个什么常用的属性,比较常用的属性大概有这么几种:
位置。这是必须的。
法线。这代表了顶点的朝向,可以用来判断是否朝向光源等。法线是个单位矢量(长度为1)。
纹理坐标。这代表了作为贴图的图片该如何"贴"到模型上。
切线。用来建立切线空间。比较高级的技术会用到,可以先不用在意。
乱七八糟的一些自定义的参数。当然了 —— 你想传一些自有用途的东西到着色器里,不会有人拦着你的。
法线的话大概是这个样子:
纹理坐标(为和坐标加以区别,常用(u, v)的方式表示):
可以这么来理解:贴图上有几个被顶点标记好的点,把图上被标记的点钉在对应的顶点上。大概是这个感觉。
切线:
其实这个东西可以先不在意,不过还是蛮重要的。
有的时候在计算中,我们需要用到切线空间:这个空间的正交基(xyz轴)是以顶点的法线(N)和两个与法线垂直的单位矢量(B & T)组成的。不过事实上,和法线垂直的矢量有无穷多个(一个平面),所以我们需要人为指定一个和它垂直的单位矢量便于计算。这个人为指定的矢量就是切线(T),然后我们可以简单的将N和T叉乘来得到B,这就建立起了切线空间。
N:Normal(法矢(向)量),
T:Tangent(切矢(向)量),
B:Bi-Normal(副法矢(向)量)
一言不合就这么多字了…好吧,那下回见w
E M T!
K M T!
(pixivid = 56926503)
以上是关于一个小demo的开发日记的主要内容,如果未能解决你的问题,请参考以下文章