« August 2014 | Main | October 2014 »

September 27, 2014

随机地形生成

玩过 矮人要塞 Dwarf Fortress 的同学都会惊叹于它的随机地形生成系统。如果你对 ascii art 无感,那么可以 google 一下 stonesense 的图片。

矮人要塞是 3d 的地形系统。在游戏 wiki 上有介绍地形生成系统的参数细节

大体上是这样的: 首先有一张高度图(Elevation),决定了每个坐标的高度。然后给出一张降雨图 (Rainfall),来影响当地的植被和河流。通常降雨图是根据高度图(海岸和季风影响)计算出来的。这里有一篇文章简单描述了这个过程。

温度图(Temperature)一般根据纬度以及当地的海拔计算出来,也会影响当地的动植物。

地质的排水情况(Drainage)可以影响当地能否形成湖泊、湿地和河流。同样影响了当地的土质(进一步影响植被)。

另外还有,火山的分布情况(Volcanism),以及野生物分布图(Savagery) 会改变当地的矿产和动物分布。


其实这些参数图都是可以从外部导入游戏的(而不使用游戏里随机出来的)。有玩家制作了更好的地图生成工具 PerfectWorldDF。 玩一玩这个工具更能体会到这些参数是如何组合到一起的。

在 PerfectWorldDF 里,高度图是用一张湍流图加上 perlin noise 合成的。PerfectWorldDF 不开源,但是可以从另一个开源库 libnoise 中了解到类似的过程的算法。libnoise 的 Tutorials 图文并茂的诠释了随机地形的生成过程和算法。

ps. 关于地形生成,还可以看看这里:Artificial Terrain Generation


最后简单提一下随机地下迷宫的生成算法。比较常用的是 Herringbone Wang Tiles


写这篇东西主要是最近又玩了不少沙盒游戏。简单记录一下这几天的研究。

September 21, 2014

ejoy2d shader 模块改进计划

由于有公司很多同事参与 ejoy2d 的开发,所以 ejoy2d 这个项目已经转移到 ejoy 的 github 名下。

有更多项目的参与的情况下,原来 ejoy2d 的简单构架慢慢显出一些局限性。主要是不同的项目会根据项目的需要(通常是针对某些特定需求的优化,以及特别的效果需求)修改底层 shader 的部分。最早设计的时候,因为考虑到只是用于 2d 游戏的开发,所以把 shader 模块实现的比较简单。特别是 attribute layout 是固定的,而 uniform 管理也没有留下太多扩展性。

在现代手机的 GPU 架构下,从渲染层渲染层 API 看,其实 2d 和 3d 其实没有本质上的区别。都是基于三角片渲染的。需要把顶点上传到 GPU 中由 vs 处理,在最后对像素做 fs 渲染出来。

而 2d engine 和 3d engine 的区别通常在于 2d engine 的顶点变换很简单。不需要用 projection matrix 和 view matrix 做变换。2d engine 中的对象多半是四边形,数量很多,常见的优化手法是将大量的四边型合并到同一个渲染批次中;所以 world matrix (以平移变换为主)在 CPU 中和顶点计算再提交更常见一些。

2d engine 从应用上说,就是在处理一张张图片。所以对图片(四边型)的处理的变化要多一些。这使得 fs 要多变一点,需要引擎提供一定的可定制性。但很少去处理 3d engine 常见的光照投影这些东西。更多的是为了优化贴图用量等目的而技巧性的去使用一些图片。

突出 2d engine 的专门面对的业务的特性,而简化 GPU 提供的模型,用简短的代码构建 engine 框架,是 ejoy2d 设计的初衷。而且我也相信,简单可以带来更好的性能。所以一开始设计 ejoy2d 的时候,shader 模块的很多东西都被写死了,以最简单的方式达到目的。仅暴露了很少的外部接口,再在这些有限的接口上设计数据结构,做性能优化。


事情总要做两遍以上,才能做对。目前 ejoy2d 完成了三个项目,由十多个同学亲身用过。让我看到了局限性:前段时间我个人精力主要放在 skynet 上,而客户端在紧急的情况下,由不同的同学给 ejoy2d 打了好些补丁,来解决实际面临的问题。

我想,还是需要有一个更灵活一些的 shader 模块底层才能更好的发展。而且希望这个模块可以用于未来引入 3d engine 的元素,而又不会增加太多的复杂度包袱。

为了做这件事情,我在最近两个月阅读了 Unreal4 的渲染层代码、horde3d 、还有之前读过的 pixellight

为什么要阅读其他成熟引擎的代码,再自己实现;而不是直接使用这些引擎?在我看来原因是这样几点:

  1. 最重要的一点,编写代码解构问题并解决的过程非常有趣。

  2. 大多数引擎历史悠久,带有或多或少的历史包袱:从计算机图形的发展历史看,有许多东西是曾经被提出来后来又被否定掉的。历史越久的引擎就越多的支持了这些可能不再被使用的可能性。支持多种不同的底层 API 在移动设备上也是没有必要的(虽然提取出不同 API 的共性这件事情本身很有价值,可以提炼出相对正确的模型)。

  3. 移动设备的显卡特性相对统一。许多 PC/Console 高端显卡上才支持的特性,在三年内都不太可能在移动设备上广泛使用。为这些东西增加的结构复杂性非常不值。同时一些为了低端设备考虑的东西,又不太需要兼容,去掉它们年可以简化引擎底层。

  4. 只是实现渲染的基础部分,而不考虑工具的话。无论 2d engine 还是 3d engine 都没有太多的工作要做,并不是一件高成本的事情(控制在一个人半个月到一个月左右的工作量)。关键是正确的去做。

  5. 受够了正在使用的 Unity3D 的闭源策略(尤其是资源管理部分),如果未来有新的项目需要一些 3d 元素,可以多一个选择。


上面提到的几个 3d engine ,从阅读角度讲,我最喜欢 horde3d 。它的渲染底层最简单,只需要读 RendererBase 这一个模块就能理解。

它只封装了 opengl 的可编程管线(但其实扩展到 DirectX10/11 也很简单),没有做那些华而不实的抽象层。在 RendererBase 之上,又根据 3d engine 的需要设计了 Renderer 一层。

所谓封装,就是根据业务的需要裁减你不需要的可能性,简化和合并 API 。(根据你可以预计的使用场合)规划资源的管理,并加入合理的限制(限制可以防止错误的使用,并简化实现)。

在 RendererBase 的层次上,主要是封装显卡驱动级的各种渲染状态切换,创建 shader ,把 attribute layout 抽象出来,和 vertex buffer 一起加以管理。uniform 的管理可以裸露出来,到上一层 Renderer 再说。texture 和 render target 也是在这一层次做封装的。horde3d 很好的把这些东西用自己的 id 管理起来,屏蔽了 opengl 层的 id 。

对于 render target ,在移动设备上其实暂时还不需要对 MRT (multiple render target) 做太多支持。因为短期内还看不到在移动设备上使用 Deferred Shading 的实用性。


周末动手按 horde3d 的思路重新封装了 shader 模块,大约写了不到 2000 行代码。包括了 C 模块和 lua 封装。C 接口定义了不到 30 个 API ,比 hord3d 的 RendererBase 要简单一些(它有 70+ 个 public api ,而 UE4 的 RHI 有 150+ 个);而 Lua 封装可以方便直接在 lua 里使用它做测试。

由于尚未完工,暂时放在了 github 的私有仓库里。

September 08, 2014

2014 IGF 评选

前两天受邀去上海参加今年的独立游戏节评选,准确说是亚洲及太平洋地区的 IGF 。

居然有接近 400 个参选游戏是让我事前没有想到的,尤其是在学生组还发现了不少好作品是个惊喜。

评审用了整整两天时间,从一大早到半夜,中间全部是叫的外卖。基本流程就是看介绍视频,(有兴趣)就试玩,讨论,反复这个过程。但明显还是时间不够用的(想想 20 多个小时看 400 个游戏是啥感觉?平均一小时 10+ 个)。

客观的说,大陆地区的整体水平还排不到前列,但也有几个亮眼的好游戏。有点不可理解的是,有些明显是 100 人以上的公司做出来的商业作品也来凑热闹。所以一般看介绍视频里有 “扫荡” 的基本都没试玩。我个人认为,IGF 还是要强调独立游戏精神的,对于可能获奖的游戏也主要是要设计出彩,好玩,而不太多考虑挖坑赚钱的因素。

出于保密的要求,就不写那些具体的很有意思的游戏了。不过可以泛泛的谈谈评审感受。

据说以往老外比较喜欢做 soul game ,可这次明显感觉反了过来。大陆地区无论是学生组还是职业组都有许多 soul game 。可惜试玩了一下,大多不明白在玩什么,甚至怎么玩都不知道。我想游戏毕竟还是以提供乐趣为住,即使是以往获奖的 soul game ,都还是很好玩的。

有些游戏拼了命的往复杂里做,各种定制元素,连我这个一向以玩复杂游戏为主的玩家都受不了。试玩 15 分钟完全开始不了游戏主线,也想像不到后面的乐趣。

抄袭现象也有许多。如果是商业游戏为了赚钱,复刻一个游戏倒没什么;但对于独立游戏,抄一个热门游戏也可以获奖?这次有 7 个评委,似乎很难瞒过这么多玩家的眼睛。当然,制作精良的疑似抄袭作品我们都仔细玩了一下,试图发现不一样的亮点,可惜很难找到。

这次也发现几款图像向 3A 游戏靠近的独立大作,可是…… 不好玩啊。整个就是炫引擎(以 Unreal 居多)和美术的,就一个人物在绚丽的场景里跑来跑去。只要想想,如果把这些游戏放到大厂家的 3A 游戏中对比,完全不会有因为画面而购买游戏的冲动。而游戏可玩性部分又接近 0 ,最终真是可惜了制作这些人物和场景的人工。


最后给下次还想参加 IGF 评选的同学们一些有用的建议:

介绍视频非常重要。不要太长,3 分钟左右是比较合适的。直接展现设计亮点,不用把太多镜头放在你得意的片头 CG 和游戏菜单上。因为 IGF 评选并不关注游戏完整性。

画面很重要,但绝对排不到第一重要。第一还是游戏性,尤其是可以从 3 分钟介绍视频中可以展现出来让人产生联想的游戏性。不用担心游戏性太独特,据我了解,评委都是硬核玩家,懂得欣赏。当然,画面如果实在太搓,且没有特点,就很可能被错过了试玩流程。(事实上,这次我们还耐心玩了几款文字游戏)

对于平台类游戏,比画面更重要的是关卡设计。一个精心设计的关卡绝对加分。

如果是多年反复提交同一款作品,最好能在文字或视频介绍里谈谈今年比去年增加了哪些新东西,改进了什么,帮助我们发现新亮点。不然,即使去年获奖了,今年也很难再选出一个一模一样的作品出来。

提交的游戏最好能保证可以运行。这次好多游戏死活跑不起来,IGF 的工作人员现场打电话去要新版本,浪费了不少时间 :( 。还有一些游戏只有联网对战部分,可服务器又关闭了。真是实在没有办法。

关于游戏试玩,每款游戏其实大约只有 5~10 分钟的机会。看到几款游戏,在开始菜单就卡了 10 分钟进不去那个急啊。有些片头还不让跳过,只好很有耐心的看完。如果是普通玩家,我还可以忍受,但在时间紧迫想看游戏的主体部分时,心情是很受影响的。如果能在 5 分钟内吸引到玩家继续玩下去那是最好的,这次好几款游戏我都玩了半个小时。如果不能产生这种感觉,最好能让一个核心玩家可以脑补出游戏还会有那些元素。


ps. 不要问我你的游戏是否获奖了。我也不知道。评选还没有结束。