一个小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)

时间: 2024-10-19 20:23:45

一个小demo的开发日记(一)的相关文章

一个小demo的开发日记(〇)

在大概两周(三周?)前,出于某些原因(w)我做了个小demo.(虽然因为各种各样的原因导致做它的时间只有一周多了…所以它还远没有完成OTL) 在目前看来,它主要的亮点啊啥的之类的东西大概可以用下面的(g)视(i)频(f)来代表w: 大概就是一个树木生长的过程,以及一个日夜交替(晚上的星星被gif几乎快压没了). (实际上才没这么点东西!但是没做完什么的TAT) 所用工具是Unity,不过为了性能全写的是Unlit Shader(按我的理解应该是不参与Unity5.x的GI(全局光照).这个Unl

一个小demo的开发日记(二)

时间倒退回2016年4月10日,这个工程刚开始的时候 —— 就不说做这个的原因和为什么要做个这个了.嗯…感觉好蠢. 一上来什么都没有.我决定把注意力先放到重点 —— 场景最中间那棵树上面. 在这个时候,我手里有一份Ogre(另一个游戏引擎,开源,无GUI)上的分形树.至于分形树是个啥,就先当成一个可以画出三维的树的程序好了. 然而我觉得用Unity能让我更快的完成这个东西,毕竟时间紧迫,离deadline只剩12天了.而现在我手上什么都没有,而且对Unity一无所知,简直…太糟了w 所以第一件事

javascript 跟随鼠标移动的提示框的一个小demo

下面提供一种跟随鼠标移动的提示框的思路,方便在以后工作中应用,主要是应用到鼠标移动产生的数值来进行移动提示框的定位... CSS代码   .box{height:100px;width:100px;background:orange;position:relative;margin:40px;} .move{height:20px;width:20px;background:red;position:absolute;left:0px;top:0px;display:none;} HTML代码

jQuery 中 ajax 提交数据应用的一个小demo

举一个jquery中ajax的应用小 demo 便于以后的更多项目拓展 ,这里要注意的是保存的文件名问题 ... ajax02.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="form&qu

jQuery 中 ajax 请求数据应用的一个小demo

举一个jquery中ajax的应用小 demo 便于以后的更多项目拓展 ,这里要注意的是保存的文件名和文件图片路径问题 ... ajax01.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> ajax小例子 </title> </head> <body> <!--

模仿京东顶部搜索条效果制作的一个小demo

最近模仿京东顶部搜索条效果制作的一个小demo,特贴到这里,今后如果有用到可以参考一下,代码如下 1 #define kScreenWidth [UIScreen mainScreen].bounds.size.width 2 #define kScreenHeight [UIScreen mainScreen].bounds.size.height 3 4 #import "mainViewController.h" 5 6 @interface mainViewController

Cocos实战篇[3.4]——仿COC的一个小Demo总结

[唠叨] 今天结束了本学期任务最为艰巨的项目实训课程,由于项目组里其他成员基本都已经找到实习了,然后他们都去实习了.只留下我和一个小伙伴在一起搞项目实训的小游戏.经过一个月与小伙伴的配合开发,做了一个勉强可以玩的一个小游戏demo,因为平时其他课程也比较繁重,所以游戏做得非常烂~(>_<)~. 我们本来打算做一款类似COC.海盗奇兵.口袋侏罗纪.城堡争霸的城战类的单机Demo.结果--哎说多了都是泪啊,经验不足,吸取教训了. [经验教训] 由于时间比较紧张,加上自身也没有大项目开发的经验,所以

一周一个小demo — 前端后台的交互实例

这一周呢,本K在大神的指导下,完成了一个利用ajax与php文件上传处理相结合的一个留言板功能的小实例,下面就让本K来带大家瞅瞅如何实现这一种功能. 一.界面概览 首先我们来看一下这个小demo的具体效果. 这个demo中,主要包括了三个步骤,也分别对应了三个功能,分别是注册,登录与留言板功能.而这三个功能基本都借助了前后台交互的几种技术,下面,本K就给大家分别展示一下这三个功能实现的代码. 二.功能实现 1.注册功能与登录功能 1.1 代码展示 1.1.1 注册功能 (1)前段部分 <!DOC

原生JS写了一个小demo,根据输入的数字生成不同背景颜色的小方块儿~

昨天练习写了这个小demo,个人觉得通过设置定位元素left和top的值,来实现换行的功能,这种方法很巧妙~ 另外,如下代码中的随机颜色的获取,还请各位前辈多多指教:需要改进的地方:或者有没有更好的方法. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style type="text