基于Ogre1.9开发的3D场景编辑器

来源:互联网 发布:淘宝 小作坊 生产许可 编辑:程序博客网 时间:2024/05/07 14:11
相信每个图形程序员都有过开发一款属于自己的3D图形引擎的想法,但现实中这个想法往往如同童年的梦想般遥不可及,因为完成这项任务需要耗费经年累月的时间精力,还需要坚实的技术积累,再者现代游戏引擎,如CryEngine、UnrealEngine等,仅靠一人的努力,只怕穷尽一生也无法实现。本人长期以来一直是图形引擎开发的爱好者,也一直从事相关工作,早在09年大学刚毕业的时候就想独立开发一套场景编辑器,但苦于时间和本身技术条件限制,直到最近才完成了这一夙愿,下面简要介绍个人独立开发的场景编辑器——“无极场景编辑器”,名字取得不好莫笑(( ̄▽ ̄))。本来想发个展示视频,但好像论坛不支持,程序的下载链接地址:[url=http://pan.baidu.com/s/1gf1EKlP][/url]
为什么选择Ogre1.9呢?首先因为Ogre是较为成熟的纯粹的开源3D图形引擎,任何人都可以在网上免费下载其源代码;其次市面上有不少游戏基于Ogre开发,较成功的产品如《天龙八部Online》、《火炬之光》等,因此存在一定的用户基础;再者相对其他引擎个人更加熟悉Ogre。Ogre官方最新版本已经到了2.1,我之前也研究过一阵子Ogre2.1,Ogre2.0以后的版本对Ogre1.x的改动非常大,核心的渲染队列、场景图、材质系统、阴影系统都发生了深刻变化,Ogre2.0以后的版本增强对新图形API(如D3D11、OpenGL3.0等)的支持,相对之前的版本整体设计更加合理,渲染效率也大大提高,可惜Ogre2.1版本还有部分功能未完善,如hlms(高级材质系统)还有很大的优化空间,PBS(Physically based shading)组件的扩展性也不足,加上Ogre2.1尚未流行,因此暂不使用。这里不想比较各个引擎的优劣,要说功能及画面效果,Unreal、Cry等无疑是行业的佼佼者,可惜这些次世代引擎对团队的要求非常高,无论是程序还是美工,目前国内能够发挥这些引擎80%以上性能的团队只怕还没有,市面上也有不少号称用Unreal开发的游戏产品,可惜大多数这些产品无论画质和游戏性都没能给玩家带来惊喜,更多的用Unreal开发的项目最后以失败告终。因此不能简单根据画面要求来选择引擎,还要根据产品自身定位,更重要的是团队的能力;再者画面效果固然对游戏宣传有极大的帮助,但也绝不是游戏的全部,耗费巨大资源来研发一款基于先进引擎的游戏,往往投入与产出不成正比。另外,如果你对图形引擎的原理有深刻的理解(当然这需要付出多年的努力,起码对于资质平凡的我来说是如此),就会发现图形引擎的整体架构都是差不多的,核心模块无非就是渲染队列、场景图、材质系统、阴影系统、组合器、骨骼动画、粒子系统等,因此选择哪款引擎并不是最关键的。
本场景编辑器仅支持Direct3D 11图形API,可能有网友要问那Direct3D 9呢?我这里给的回答可能会引发争论,但也算是为了抛砖引玉吧,如有不同意见望轻喷。因为个人认为相对D3D11,D3D9、OpenGL2.0等API根本是反人类的设计,毫不规范效率奇低,用起来极其繁琐,这些东西的存在当然有它的时代背景,但到现在实在是该被抛弃了。其实游戏公司也不必考虑那些现在还在运行着Windows XP系统的电脑,因为这些电脑本来就不是用来打游戏的。
个人在本编辑器的开发过程中严格遵循模块化设计思想,每个独立功能模块都经过“设计—编码—测试”三个阶段,这样可以尽早发现错误,将开发风险降低到最小范围,从而大大提高整体开发效率。另外,本编辑器使用多种设计模式,如观察者模式、工厂模式等。背景介绍了这么多,接下来我们正式进入正题。
首先我们来看程序界面,界面非常简洁,主要分为:菜单工具区、主面板区、属性面板区、场景渲染区、还有状态栏,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481121838_372859.png][/img]
菜单工具区主要包含文件、编辑、以及场景元素创建的相关命令,这些比较简单直白因此不作详细介绍。这里需要详细解释一下“场景元素”这个名词,我将场景中的天空盒、地形、光源、模型等对象抽象为场景元素,天空盒及地形是全局场景元素,而光源(点光源及聚光灯)、模型、水面等属于非全局场景元素,另外还有一个特殊的场景元素,命名为“全局光影”,该全局场景元素包含整个场景的全局光影效果,如全局方向光(一个场景只能有一个方向光),环境光颜色、是否启用阴影,以及延迟渲染的相关选项等。注意,对于一个场景,一类全局场景元素最多只能有一个。
主面板区域分为三个子面板,分别是场景视图、资源视图以及地形纹理面板,场景视图面板显示当前的场景树,场景树中列出所有的场景元素,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481121910_443537.png][/img]
资源视图以树的形式列出Ogre引擎内部管理的所有资源,包括模型、纹理、材质、粒子系统等,可以在资源视图中选中一个模型,然后场景渲染区内点击鼠标左键创建该模型,资源列表如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481121943_328400.png][/img]
地形纹理视图类似于Windows系统的资源管理器,上面列出当前所有用于刷地表的纹理,地形纹理是一个特别定义的资源组,资源组名必须是“Terrain”,这样资源组下面的所有纹理,都会被自动添加到地形纹理视图中,这里要特别提示,用于刷地表的纹理不要用在场景的其他物体上,比如模型上,否则可能会造成错误,因为地形在调度过程中会释放已加载而当前又不被地表使用的纹理,以免浪费显存资源。如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122016_198091.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122032_335289.png][/img]
属性面板显示当前选中的场景元素的所有属性,可以在属性面板上编辑修改场景元素的相关属性,如果修改后发现之前的值更合适,我们可以撤销当前的修改,属性面板如下图所示。既然说到撤销,我们知道任何没有“撤销-重做”功能的编辑器都是耍流氓,撤销功能可以说是编辑器里面最复杂的模块之一,而三维图形编辑软件中的撤销更是如此,因为这种类型的编辑软件涉及到太多类型的数据及状态,以及不同的输入编辑窗口,在本人工作经历中遇到过很多同行开发的编辑器,只要随便撤销几步就轻则状态紊乱功能失效,重则内存泄漏程序出错,这是源于没有良好的整体设计及模块设计。本编辑器的撤销系统经过充分测试,几乎所有编辑命令都可以撤销,撤销的步数上限为50步,这一数量可以在代码中任意设定,出于内存占用考虑,这里限定了50步。
[img=http://img.bbs.csdn.net/upload/201612/07/1481122059_431779.png][/img]
在简单介绍程序界面之后,接下来简单讨论创建一个场景。
首先创建一个全局光影,点击菜单“物体->全局光影”,或者在工具栏中点击[img=http://img.bbs.csdn.net/upload/201612/07/1481122113_190566.png][/img]按钮即可创建该元素,可以根据需要修改该元素的属性,例如修改方向光的方向向量,散射光及镜面光颜色,还可以启用阴影等,这里简单说明我所使用的阴影技术,Ogre1.x内部的阴影机制是非常简单粗暴的,也就是落后的纹理阴影投影算法,该算法首先生成阴影纹理,接着绘制场景,最后将阴影投影到场景中可接受阴影的物体上去,需要渲染三遍,毫无疑问,这是非常低效的阴影机制,而且存在近看阴影粗糙模糊的问题。我使用的是PSSM阴影算法,将视景体分为3块,为每个块分配一张阴影纹理,寻常的PSSM算法虽然能解决近看阴影质量的问题,但是无法解决低效的问题,因为需要三张阴影纹理就得渲染场景三遍,我用几何着色器的重复实例来解决这一问题,创建一个包含3张二维纹理的纹理数组,将不同的块中包含的物体的深度值输出到纹理数组中不同的子纹理,这样只需要渲染场景一遍即可得到三张阴影纹理,渲染两遍即可得到阴影效果。另外,几年前的AMD显卡可能不支持几何着色器重复实例这一技术(我个人一直对AMD显卡的驱动程序抱着怀疑的态度的),如果不支持,请不要打开阴影功能。
接下来创建天空盒,点击菜单“物体->天空盒”,或者在工具栏上点击[img=http://img.bbs.csdn.net/upload/201612/07/1481122124_459682.png][/img]按钮即可创建该元素,同样创建完后可以设置相关的属性。如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122137_317934.png][/img]
现在我们来创建地形,地形的创建分两步:点击菜单“物体->地形->新建地形”,或者点击工具栏[img=http://img.bbs.csdn.net/upload/201612/07/1481122204_828074.png][/img]的下拉菜单,即可创建地形场景元素,接着还要创建地形数据,单击菜单“物体->地形->创建数据”,弹出创建地形对话框,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122219_238340.png][/img]
在对话框中需要指定地形名称,以及地形数据的存放路径。“点间距离”参数指定了地形网格中相邻两点之间的水平距离,“最大细节”参数指定了最高的LOD层级,该参数范围为[0,7],本编辑器使用Geomipmap地形LOD算法,地形由分块组成,“最大细节”参数决定了地形分块在最大细节层级时顶点的数量,假设参数为n,则该数量为2^n + 1,“点间距离”、“最大细节”和纹理的大小共同决定了地表纹理的分辨率,我们以米作为默认长度单位,以我个人的经验,0.1米对应一个纹理像素就能达到非常好的效果,假设地形纹理的大小为256X256,则一张这样的纹理可以对应25.6米X25.6米的地表区域,默认的点间距离0.8米,最大细节为5,0.8X(2^5) = 25.6,刚好满足这一数值。
“横向范围”及“纵向范围”指定了地形的水平空间范围大小。勾选“创建随机高程”选择框可以创建随机地表,也可以根据现有的高度图来创建地形,当高度图的区域小于指定范围时,超出的部分将会置平,默认情况下将会创建一个高度为0的地形平面。如果在弹出对话框之前在地形纹理面板中选择了一张纹理,可以将该选中的纹理作为地表的底层纹理,同时,可以在对话框中设置地形的散射颜色、镜面颜色以及镜面系数。例如,按照上图的设置,我们可以轻易的创建一个简单的随机沙漠地形,效果还挺不错:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122244_721989.png][/img]
如果在地形编辑过程中发现地形范围太大或者太小,不必担心,点击菜单“物体->地形->扩裁地形”,我们可以零成本的扩大和裁剪地形数据范围。
另外需要说明,为了方便编辑地形数据,在编辑器中并不支持地形LOD,需要将场景及地形数据导出之后,使用“无极场景浏览器”载入导出的数据才能看到地形LOD效果。经过几次改版,这个地形算法可以说已经优化到了接近极致的程度,有兴趣的朋友可以自行测试,无论创建多大的地形数据(几十上百公里),在漫游浏览导出数据的时候也丝毫不会感到调度延迟。
编辑器有两种编辑模式,一种是摆放模式,另一种是地形编辑模式。在摆放模式中,可以选择场景中的物体,修改物体的属性,例如平移、旋转、缩放模型等,在地形编辑模式中可以编辑地形数据,使用工具菜单的“放置”和“地表”菜单项可以切换这两种模式,或者可以使用工具栏上的[img=http://img.bbs.csdn.net/upload/201612/07/1481122306_366235.png][/img]按钮来进行切换。
创建好地形数据之后,就要对地形进行编辑,本编辑器集成了地形编辑模块,首先我们编辑地形的几何表面,创建一个默认的平面地形,切换到地形编辑模式,点击菜单“工具->雕刻”,或者点击工具栏上的[img=http://img.bbs.csdn.net/upload/201612/07/1481122326_974444.png][/img]按钮,打开雕刻工具窗口,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122342_157169.png][/img]
用户可以选择圆形或者正方形形状工具,例如选择正方形形状之后,地表上绘制的“刷子”就变成方形,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122362_781780.png][/img]
接下来用户可以选择工具,地形雕刻一共支持6种工具,分别为:上升、下降、抓拽、平推、平滑、粗糙,例如下图演示使用上升工具“拔起”一座小山和一个金字塔:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122404_582860.png][/img][img=http://img.bbs.csdn.net/upload/201612/07/1481122414_543056.png][/img]
其他工具有兴趣的朋友可以自行测试,都非常简单,工具下面的参数这里也不做解释了,因为解释起来相当费劲,而用户只需简单使用一下就能明白其用途。
接下来我们给地形绘制纹理,点击菜单“工具->绘制”,或者点击工具栏上的[img=http://img.bbs.csdn.net/upload/201612/07/1481122443_433591.png][/img]按钮,打开地形绘制工具窗口,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122455_220173.png][/img]
地形绘制工具有三种形状,分别是圆形、正方形、图片画刷,圆形工具绘制圆形区域,方形工具绘制方形区域,图片画刷则根据图片的图案绘制地表。选择需要的形状,设置相关参数,在地形纹理面板中选择想要的纹理,鼠标左键单击地表即可将纹理绘制到工具所在的区域上,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122478_11472.png][/img]
当选择图片画刷时,可以选择不同的图案,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122558_820872.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122584_276614.png][/img]
下图是编辑好的山脉,以及绘制纹理之后的效果:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122612_566043.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122625_123123.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122637_860109.png][/img]
关于绘图工具的其他参数这里也不做详细说明,因为用户只需简单使用就能明白其用途,需要说明的是,一个地表块最多能混合5层纹理(混合5层纹理足以给地表提供任意多的细节了),超出5层之后,最底层的纹理将会被第一层纹理完全覆盖,从而被丢弃。另外,地形还支持bumpmap,选中一个地形块,在属性面板中设置它的法线贴图。这个地形编辑模块参考了市面上其他地形编辑软件的一些设计。
场景中除了天空、地形,还有各种各样的模型,如树木、石块、房屋等等,我们现在来介绍如何在场景中放置模型。首先将编辑模式切换到放置模式,在资源视图面板中选择想要摆放的模型,在场景渲染区中单击鼠标左键即可创建该模型,如果此时鼠标点击到地表上,则模型自动被放置到鼠标点击到的地表点上,如果平移模型之后想要模型刚好落在地表上,可以按键盘上的“PageDown”键,这样模型就被自动降低或抬升到地面上。如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122673_171490.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122694_930040.png][/img]
这时候如果我们发现模型的位置、朝向及大小都不是我们想要的,我们可以使用平移、旋转以及缩放工具来修改这些参数,这几个工具与MAYA中对应的平移、旋转及缩放工具的用法完全相同,事实上我就是照着MAYA的这几个工具来做的(AutoDesk不会来告我侵权吧^_^),也可以在属性面板中直接给这些参数赋值,我们在工具栏上点击[img=http://img.bbs.csdn.net/upload/201612/07/1481122724_20384.png][/img]按钮来打开平移工具,点击[img=http://img.bbs.csdn.net/upload/201612/07/1481122737_583641.png][/img]打开旋转工具,点击[img=http://img.bbs.csdn.net/upload/201612/07/1481122752_588438.png][/img]打开缩放工具,如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122767_309392.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122787_822665.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481122799_772379.png][/img]
当场景中一个模型摆放在不同的位置,有着不同的朝向或缩放倍数时,可以使用复制粘贴功能,也可以批量复制,批量粘贴,这样就省了一个个去创建的麻烦。
室外场景中往往存在池塘、河流、湖泊等水域,场景中添加水面可以大大增加真实感,本编辑器支持添加水面,设置水面的相关属性,点击工具栏上的[img=http://img.bbs.csdn.net/upload/201612/07/1481122826_497916.png][/img]按钮,然后在场景渲染区中点击地表(注意一定要有地形才能创建水面,后面会进一步说明),即可创建水面,如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122842_973119.png][/img]
水面的范围自动与地表计算交叉,例如在地表上挖了一个坑,则水面填充的范围就只在这个坑内,这样设计有很大的好处,如河流的水面只会填满河床,而不会超出河床的范围,这也是为什么必须有地形才能创建水面的原因,现在我们将水面的位置抬高,将坑填满,如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481122875_310232.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481123002_431975.png][/img]
我们还可以设置水面的相关参数,例如水面的颜色、水面的透明度,菲涅尔因数,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481123061_170999.png][/img]
虽然我们可以在场景中创建多个水面,但是在同一个可见区域内,尽量不要创建超过一个水面,如果要创建多个尽量确保它们的水面高度相同,因为水面的渲染比较耗时,需要渲染反射图、折射图,如果有不同水面有不同高度,则需要渲染多个反射图,这将大大影响场景渲染效率。注意,目前我仅实现了水面效果,水下效果如扭曲、上帝光线等效果尚未实现。可能有朋友问,如果一个场景没有地形只有水呢?例如海洋,海洋表面的实现其实也差不多,而且实际上相对更简单一些,因为海洋表面不需要做交叉计算,也不需要渲染折射图,利用辐射格子拓扑结构,加上D3D11的嵌饰系统(Hull Shader、Tessellation Shader、Domain Shader),可以实现很好的海洋表面网格。另外,放置在水面下的物体,其材质需要特殊处理一下,在渲染反射图时,在像素着色器中将处于水面下的像素裁掉,地形材质我已经做了相关处理。水面的模拟可以说是3D场景中最难的效果之一了,为了实现水面效果,我甚至改动了引擎核心的渲染循环,改动渲染系统增加深度纹理的支持,当然我对Ogre引擎代码的改动也不是一处两处地方了,水面渲染还有很多技术细节,这里就不一一探讨了。
现在我们讨论创建一个使用延迟渲染机制的场景,有些场景例如室内场景、洞穴等,使用延迟渲染机制更加合适,因为这些场景往往有多个局部光源,而在多光源的场景中使用ForwardRender显然是不合适的。首先,新建一个空场景,创建“全局光影”场景元素,关闭全局阴影,打开延迟渲染,把全局方向光的散射及镜面颜色调暗,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481123093_470538.png][/img]
接着我们创建一个随机地形,如下图所示:
[img=http://img.bbs.csdn.net/upload/201612/07/1481123117_393336.png][/img]
接着创建一个点光源,一个聚光灯,点击工具栏上的[img=http://img.bbs.csdn.net/upload/201612/07/1481123142_201152.png][/img]及[img=http://img.bbs.csdn.net/upload/201612/07/1481123153_331399.png][/img]按钮分别创建点光源及聚光灯,创建方式与创建水面一致,设置光源的范围及衰减系数,如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481123170_536234.png][/img][img=http://img.bbs.csdn.net/upload/201612/07/1481123188_284012.png][/img]
我们在聚光灯下放置一个模型,打开延迟渲染阴影(注意该选项仅对聚光灯有效),如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481123212_40703.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481123233_62104.png][/img]
我们也可以查看延迟渲染中GBuffer的内容,通过切换延迟渲染模式,如下图:
[img=http://img.bbs.csdn.net/upload/201612/07/1481123257_229638.png][/img]
[img=http://img.bbs.csdn.net/upload/201612/07/1481123273_690590.png][/img]
最后在创建完场景后,可以将场景导出,点击工具栏上的[img=http://img.bbs.csdn.net/upload/201612/07/1481123300_231884.png][/img]按钮导出场景,注意如果电脑性能较慢,CPU没有空闲时间,导出进度对话框可能要过一会才能弹出来,这时候仅需将相机朝天空上看,减少场景渲染复杂度,让CPU有空闲时间,导出进度对话框就能显示出来了,导出的场景可以在“无极场景浏览器”中载入漫游浏览,导出后的场景的渲染效率将大大提高,内存占用也将大大减少。
通过上面的篇幅,我给大家简单介绍了无极场景编辑器的主要功能,本来我想做一个漂亮的场景展示给大家看,可惜奈何我只是一个程序员,而场景制作需要专业的美工才能完成,我在前面介绍中所用的美术资源,包括模型、纹理,甚至连UI图标都是在网上找的,因此自己制作场景这个想法只能落空了,多少有些遗憾。不过希望将来能有专业的美工人员用本编辑器制作出精美的场景,无论是用于制作游戏场景,或者展示规划方案,毕竟这个编辑器是可以免费使用的。如果大家在使用或测试过程中发现bug,或者有更好的改进建议,我会很高兴收到这样的反馈,因为毕竟这套编辑器从设计到编码到测试都由我自己一人完成,所以可能存在我尚未发现的问题。
场景是游戏世界的基础,一个实用高效的场景编辑器能大大提高游戏开发的效率,场景编辑器可以说是游戏产品的首要生产工具,也是游戏引擎的核心也是难点所在,如果有朋友对我的这套解决方案感兴趣,欢迎与我联系,邮箱地址:wangyiuestc2005@163.com,Mr.吴。
0 0
原创粉丝点击