游戏人生

不积跬步,无以至千里;不积小流,无以成江海。

导航

引擎设计跟踪(七) Mile sone 1: terrain 基本完成

最近最大的工作是添加Atlas多贴图支持,使一个大块地形即可以支持更多的贴图,又可以通过一个Drawcall绘制


另外一个工作是地形的保存和加载, 这个虽然很早已经完成,但最近在完善框架的Enitty加载和Stage加载.同时把地形的加载集成到框架里面.
Entity和Stage使用同一种加载方式, 并且加入了XML的方式.之前只有Stage的binary方式.现在可以判断格式并选择对应的解析器.(第一行的注释就是标记).

 

基础框架方面

主要是添加了编辑器的PropertyGrid,其实用的还是以前的UI,主要是实现了对象的数据绑定.


另外一个大的工作是窗口布局的完善: 以前的窗口虽然分了Panel,但是不能拖动,现在拖动功能已经激活.更主要的完善是添加了窗口的布局保存.每次打开编辑器的UI布局会跟上次打开的一样.
计划加入的功能是:保存每个工具的配置选项(右键点击工具按钮后的的配置窗口,比如画刷工具的大小,形状,强度,等等).这个应该不难,因为每个工具的配置选项也是插件通过数据绑定/配置接口添加的,可以统一保存加载.

还有就是给MediaLibrary加入了Preview功能,同时加了PreviewPanel,比如在选择贴图的时候,可以显示选中的贴图.

地形特性:

1.参数可配置

地形块16x16,32x32,64x64可在运行时切换,

地形三角形分布"米"字型和x型,可运行时切换

法线贴图运行时开关

地形创建时可选择nxn的总大小和可见大小,如果1x1可见就是一般地形,3x3可见或者5x5可见就是无缝式地形.

运行时批次合并选项 - 完全合并: 一个tile一个DrawCall(d3d dp), 不合并:逐个block绘制, 平衡:目前感觉这个有点鸡肋,是根据DXAPI的自动Batch合并策略,组织block的顶点,索引和DP顺序,实现部分地形的block的batch合并,需要额外的顶点缓冲处理.

运行时可修改参数:

创建时参数:

2.顶点LOD:

支持4-6个级别, 跟块大小相关.

3.多层贴图Atlas:

目前一个tile的diffuse贴图为128x128,Atlas大小为512,最多支持4x4=16张贴图.

法线贴图512x512, Atals大小为2048,与diffuse对应,16张

3.材质LOD

两级LOD. lod0法线贴图, lod1无法线的diffuse. 开启法线贴图时, 修改地形材质中的LOD距离参数,即可调整LOD的距离.
下图近处有法线贴图LOD0,远处没有法线贴图,黑白接缝处是LOD的切换边界.

4.地形编辑

高度编辑和贴图混合编辑,支持4个混合通道

其他相关:

场景目前支持八叉树:

注:

1. Coordinator主要用于大无缝地形的坐标修正,以及多个场景管理之间的管理和协调,比如Portal等等.

2.上图中右边的选项,跟前3个图中的选项界面,以及1个property grid界面, 是同一种UI,UI中的内容不是UI模块自己添加,而是通过良好定义的接口添加,保证业务逻辑与UI分离,从而保证稳定性和复用性.否则我一个人硬编码,拼了小命也很难完成这么大的工作量,而且维护成本太高了.

3.左边的文件选项+右边的详细选项, 是插件注册的内容.如果移除插件,此UI界面将没有选项显示.

 

从4年前业余学习设计模式,写的一些模式,以及写一些小的类库,比如string,一开始随便写写,到后面几乎业余全部时间花在这上面,一直到现在有一个稍微大点儿的框架,虽然还很不完善,但这几年真的觉得很辛苦,但还是要坚持.

最近会休息一段时间.今年和明年的Mile Stone 2将会考虑model,animation,以及对应的文件格式,Max/Maya导出和Editor集成入ModelViewer,并完善deffered shading这一套,除了Model和Animation的算法实现,以及Max的SDK,需要时间学习以外,相信有了现在的编辑器框架,将近到了插件的量产阶段,后面的ModelViewer工作相对会轻松一点儿.
再往后,MileStone3将加入渲染效果,雾,水面,Realtime Shadow,反走样,以及PostEffect各种效果
MileStone4计划是做Effect和引擎级的EffectEditor.
再往后就是项目级的(Client Oriented)CharacterEditor和MagicEditor.
所有的过程都将以学习(知识积累)为主, 代码积累为辅.

 

 

再说下最近几天的工作,地形加载的profiling: 因为IO全部在另外的线程了,但是IO完成以后,资源处理花费太多时间. 于是临时加入了轻量级的profiling工具, 经过profiling,发现手动更新Atlas的mipmap很耗.大概在100-200ms

查看代码发现以前随手写的Mipmap更新是这样的:
Mip0 ---> Mip1
Mip0 ---> Mip2

...
但是因为Mip0太大,采样很耗,而且不了解DXT的surface降级,是否需要解压/压缩,(如果自己写,我可能会做,但目前调用的是D3DX的辅助函数,就是那个LoadSurfaceFromSurface).即便不需要解压和压缩,Mip降级的采样仍然是很耗的.于是改为:
Mip0 ---> Mip1
Mip1 ---> Mip2
...
这样效率大大提高,大概需要20ms.但是仍然觉得慢,索性改为使用updateTexture(),以前为updateTexture(src,dest),现在为updateTexture(src, dest, srcRect, destRect) -(类似这种)
将加载的贴图,载为带mipmap的,(如果本身没有,就在IO线程自己生成,这个很早就已经做了),然后把加载好的Mipmap chain直接更新到Atlas的子区域,这个填充过程几乎不消耗时间.
另外,VertexBuffer和NormalBuffer的创建也是在IO以后的同步过程创建的,也改为在IO线程先创建好内存格式的buffer,然后在同步线程直接复制到硬件缓冲.
目前效果还算满意,从以前的200ms降到现在的30-40ms(主要消耗在四叉树中地形块的添加和删除操作上约占了20ms),在debug下会有稍稍的卡顿,后面有时间了会继续做优化.

posted on 2013-03-14 23:55  crazii  阅读(514)  评论(7编辑  收藏  举报