WEBGL 2D游戏引擎研发系列 第一章 <新的开始>
~\(≥▽≤)/~HTML5游戏开发者社区(群号:326492427)
转载请注明出处:http://html5gamedev.org/
目录
HI,朋友们,欢迎来到本系列教程的第二季,WEBGL2D游戏引擎研发系列,不知道你是不是和我一样有梦想,内心永远有一篇属于自己的游戏世界呢,技术快速发展的今天,每当我们到一个新的领域去学习如何制作游戏,但是迎面而来的就是各种引擎,不知道你是否和我一样渴望学习底层的知识,你是否也和我一样没有安全呢,对于工作而言,效率永远是第一,能快速通过引擎开发出商业项目肯定是好的,但回想一下,我们这么多年努力究竟学习到了什么?创建一个地图,加入寻路算法?做一个背包系统?现在的新技术会越来越多,新的硬件平台也越来越多,难道我们每跨越一个新领域都要期待是否有合适的引擎吗?或者你可以考虑业余时间自己也专研专研,当你了解底层的渲染原理后对引擎的使用也会更加顺手,优化的想法也会越来越丰富,很多人想写是出属于自己的引擎却发现需要很多的数学公式而放弃,或者是API很难理解,现在,不用担心,我会毫不保留的把的公式留给你,我也不会发一大段没有注释的代码让你自己琢磨,HTML5游戏开发者社区和9tech与你同在,有什么不明白的地方欢迎来我们交流。
好了,如果你现在正在听歌建议换抒情一点的歌曲,因为我们即将进入一个复杂而美妙的世界,老规矩,在开始讲解代码之前,我会把实现的原理告诉你,告诉你我们为何要这样使用API,当你了解原理之后再去使用代码会有一种亲切的感觉,如果你跟随本章的学习之后掌握了WEBGL的知识那么恭喜你,你也同时掌握了opengl的原理,它将伴随你跨越任何平台,现在让我们开始吧.
两个小伙伴的故事
这是一个两个小伙伴的故事,让我们回归的到很早很早以前,那会还没有像现在一样科技发达,能做到的就是在计算机的显示器中某个区域显示某个颜色,这时有一个小伙伴按耐不住了,他提出了一个想法,就是数据共享,小伙伴在它的显示器上通过网格显示出了一副图像,他非常的兴奋和开心,他希望分享给别人,希望能在别人的显示器显示,现在他创作的图像是这样的
他思考了许久,如何才能把这图图像传递给别人呢,或许他应该发明一种图像的格式用来存储这些像素信息,于是他就创造了用于存储这幅图像的数据格式,在我们现在看来,它有的时候叫bmp有的时候叫jpg更多的时候叫png,不管怎么样,他成功了,现在他开心的拿着这幅图像的信息找到了他的小伙伴,HI,朋友,我这里有一副超越毕加索的画你要看看嘛,于是,两个小伙伴开始商量着如何才能在另外一台电脑上显示这幅图像,小伙伴说,HI,朋友,你能通过我的数据创建和我的图像宽度高度一样的网格吗?另一个小伙伴说,没问题,那我们就叫这个过程是栅格化吧,于是,这样一个空的网格出现了,
哇,两个小伙伴都惊呆了,他们成功了第一步,现在某人有说了,HI,朋友,那你能采集我的图像信息的像素并且记录他们的坐标在你的网格里填入相同的颜色嘛?,另一个小伙伴说,没问题,那我们就叫这个过程为纹理采样吧,于是他们开始纹理采样,过程是非常愉快的
又一副超越毕加索的画要出来了,在作品完成之际,小伙伴又有了新想法,HI,朋友,如果我们对这幅图像放大或者缩小会怎么样?小伙伴说,没问你,那你可以先创建这图图像的2倍大小的网格吧,然后我们让他们的数据信息都乘以2怎么样,于是两个小伙伴又开始了新的创作,比如这样
细心的小伙伴发现原来在(0,5)的点在放大的图的(0,5)*2=(0,10)的点上了,原来长度为6的像素格子现在为12了,这正好是他们想要的效果,小伙伴说,这太神奇了,要不我们叫这个过程为插值计算吧,后来,小伙伴又有了新的想法,如果我们要移动这图图像怎么办呢?那我们之前的逻辑是不是移动到新的位置后还要再计算一次呢?小伙伴说,之前我们用的是绝对坐标系,这样太麻烦了,我们新创建一个坐标系吧,叫它UV怎么样?U代表X轴的取样范围,V代表Y轴的取样范围,他们的范围值是0~1,1代表原图的最大值,这样我们就不用关心这个图像在什么位置或者如何缩放了,于是小伙伴开始了新的创作
通过UV坐标系小伙伴不用再关心图像的XY究竟在什么位置了,而只关心取样的范围是多少,只要利用插值计算后对应最大值就可以了,小伙伴开始了各种各样的实验
把U的最大取样范围设置为0.5
这样就等于再原图最大取样到50%,或者也可以说是用原图的50%填充了新的网格,下面再把V的最大值设置为0.5
哇,通过UV,小伙伴们成功的新网格里显示了原图的某一个部分,或者可以说原图在新网格里放大了,不仅可以放大,还可以缩小,但是缩小会遇到一个问题,缩小后采样范围会大于原图,比如你可以设置U和V的最大值为2,但是原图的UV坐标系是0~1,2是超出范围的,所以小伙伴们决定做2个选择,其中一个选择叫边缘重复,也就是取样超过边缘了,那么就用最后一次取样的数据填充后面的数据,比如这样(实际上这张图重复的应该是透明区域,为了方便演示,我们假设它的边缘像素是有颜色的)
这样的好处在于,如果最边缘的像素是透明的,那么他们就会重复透明的像素,这样看起来图片周围都是空的一样,还有一种重复的方式为纹理重复,也就是说取到了边缘处又回到0开始重新取样,这样的效果看起来是这样的
这样采样的好处就是可以在一个网格里循环重复渲染纹理的滚动,你可以上下滚动或者左右,再或者上左一起,只需要让UV同时加上或者减去某个值,比如
两个小伙伴越来越开心,因为他们利用UV坐标系可以让图像在新的网格里任意缩放和位移了,这时候一个小伙伴说了,HI,朋友,之前我们创作图像的过程太复杂了,能不能把这个过程交给计算机去处理呢?另一个小伙伴说,那你如何才能让计算机知道你在画什么呢?这很简单啊,两点成线,三点成面,我们可以利用3个点的坐标让计算机知道我们将要在哪个位置生成一个面,我们可以定义2组信息,一组是顶点的接受循序,另外一组信息是顶点的实际坐标点,,因为计算机肯定要知道我们哪个顶点的循序对应哪个顶点坐标对吧,比如我们这样设置第一组信息(0,1,2),这样设置第二组信息(0,0)(0,6)(6,6) ,这样计算机器就应该知道怎么定位这3个点了,比如这样
小伙伴说,计算机怎么知道你的顶点呢?我们需要一个自动程序来识别他们吧,另一个小伙伴说,没错,我们创建一个小程序叫顶点着色器吧,它专门负责我们传递过来的顶点信息,和顶点相关的逻辑,每个顶点都会运行一次这个着色器,通过这个着色器我们可以栅格化我们的网格,比如这样
看吧,这样我们就很简单的让计算机识别我们的新网格了,但是如果我们需要是矩形呢?另一个小伙伴说了,那就定义2个三角形吧,因为2个三角形其中有2个顶点是共享的,所以我们只需要设置一个新的顶点循序和新的顶点坐标就好了,比如这样(0,1,2)(0,3,2) 顶点坐标是(0,0)(0,6)(6,6)(6,0),这样我们又节省资源又可以绘制出一个矩形.
现在计算机能根据我们的指示绘制出新的网格,那剩下部分就是开始采样咯?没错但是在这里之前我们需要把UV信息也传递到顶点着色器里去,因为只有通过顶点着色器我们才能计算出他们的中间插值,因为实际上我们并没有传递给计算每一个格子的UV坐标,这个坐标可以很容易的让计算机器算出来,比如,0~1之间的插值是0.1,0.2,0.3,0.4,0.5 …..,最后我们需要把这些属性传递给一个叫片段着色器(像素着色器),它是每个像素运行一次,当像素着色器接受到UV的插值坐标后就会开始从原图开始取样了,它会把取到的结果最终输出到画面上,实际上这个过程还有很多种选择,比如线性采样,也就是说我们可以获取当前像素片段周围的像素点然后通过算法计算出一个合理的平均值来当作本像素的颜色值,这样图像会显得真实一次过度也会平滑一些,还有一种是临近采样模式,这个速度比较快,但是图像的效果不是很好,因为它只是简单的从周围的像素取一个值没有复杂的算法,除了他们还可以有其他的采样算法,但目前来说我们常用的就是这2种了,比如你正在拼接某个图块时发现有细缝你可以利用临近采样模式降低细缝的显示,现在,我们经过了一系列的步骤终于成功的显示出了图像,小伙伴们很兴奋,要不我们总结一下吧.
1.创建顶点索引循序
2.创建创建顶点坐标数据
3.创建UV坐标数据
4.生成纹理
5.创建顶点着色器
6.创建片段着色器
7.上传顶点索引
8.上传顶点坐标到顶点着色器栅格化
9.上传UV坐标到顶点着色器计算插值
10.上传纹理数据到像素着色器并且接受UV的插值坐标
11.通过UV插值坐标从原图采样获得颜色输出到屏幕
这是大致的流程了,于是两个小伙伴开心幸福的生活在一起了,故事讲完了,你现在对这套渲染流程有没有一个大概的了解了?我们这里列出的只是一个初略的框架而已,实际具体的流程可能比这个还要复杂,不过你可以放心,复杂的部分通常都是计算机底层的硬件帮你完成了,一般情况你只需要按照上面的步骤去绘图就可以了,现在你可以回味一下,我们下一个章节就要利用WEBGL的API对应到这个步骤了,我相信你如果读完了两个小伙伴的故事的话,对后面的章节应该会有极大的信心了.
转载请注明:HTML5游戏开发者社区 » WEBGL 2D游戏引擎研发系列 第一章 <新的开始>