程序设计

在3D游戏中采用场景管理的意义

0

我们常说3D引擎应当包含若干功能:材质,模型,动画等等,这些功能我们很好理解,模型是我们需要渲染的几何体,材质表现的是几何体如何对光照如何做出回应,动画(特别的,骨骼动画)往往是3D世界中可运动模型的基础。除了这些与渲染直接关联的概念之外,往往还有个与渲染看似无关的概念:场景管理。

游戏渲染当中常用的场景管理往往被称为Scene Graph:它的实现通常采用树状结构,构成它的基本单位是节点,一个节点可以有若干个子节点,并且(除了根节点之外)往往有且只有一个父节点。

在实际游戏当中,对于需要渲染的几何体,比如静态的Mesh或者有Skeleton的Mesh,其本身不包含世界变换信息,而是由其所处的节点决定其位置与朝向。很久以前读Ogre的源码看到它就是这么做的,然而问题是,为什么必须要这么做?我一直心存疑惑,如果不采用Scene Graph的方案,我们给每一个需要渲染的模型赋予世界变换信息,那么这个模型不是一样可以渲染么?为什么非要把变换信息与模型本身分离开?分开有什么好处?而不这样做又有什么缺点呢?

(more…)

halfwayvector.png

D3D基础 – 光照,材质与着色#1

0

初接触d3d时,相信许多初学者和我一样,虽然对3D实时渲染的原理有所了解,但是却对整体的管线结构有所困惑,包括可能许多做3d游戏的程序员,由于常常采用封装好的引擎做上层逻辑开发,因此对底层的架构也未必了解得十分透彻。

长久以来,对3d图形学的底层技术,我一直也是只了解个只鳞半爪而已,最近一段时间,在工作中不断的接触到这方面的知识,才有了比较系统的思考与总结,本文记叙了我学习dx管线的一些思考,由于水平所限以及尚未对最新的DX11架构有所关注,所以本文不涵盖DX11的最新架构,只涉及DX9及以前的知识结构,虽然如此,但是相信如果系统的掌握了这块知识,对了解后续的新技术也是有所帮助的。

本文主要是针对对3D渲染知识有一定了解,然而对D3D的结构却不是很清楚的同学,把DX8/9的管线结构做了一番说明,将固定管线的光照、纹理混合与可编程管线加以对比,期望对这一块知识有一个比较完整的总结。

 

目录

1. 硬件加速的3D渲染

2. 材质与光照

3. 变换,光照与顶点着色器

4. 纹理与像素着色器

5. Alpha测试,深度测试与Alpha混合

6. 更多话题

(more…)

DissolveMiddle.jpg

溶解效果的原理与实现#1

0

在游戏中实现溶解效果,往往有两种选择:其一是采用多重纹理;其二是采用模板缓冲。

本文说明采用多重纹理方案时如何实现溶解效果,采用模板缓冲的方案容后再补。

Dissolve-Middle

上图是一个利用PixelShader达成的效果,其原理是,当我们把一个面片绘制到渲染表面上时,将特定像素的Alpha值设为0,从而在绘制到表面与背景混合时,达到镂空的效果。镂空的图案由美术指定一张Mask纹理确定。譬如在上图的效果中,我利用了下面这样的两张纹理图(左图是前景贴图,右图作为Mask),美术可以通过指定不同的Mask图,实现不同类型的逐渐消解/生成的效果:

06_11_2_moon dissolve

实现此效果需要两张贴图,一张是物体表面的纹理,另一张作为溶解的Mask图。

 

 

(more…)

b08ef0f1c195.png

简述游戏逻辑及编辑器的抽象

0

最近一段时间以来,本人参与了公司下一代游戏编辑器的开发,从而有机会针对编辑器设计做一些简单的思考——如何设计更好的抽象,从而达到在客户端,服务端,以及游戏编辑器中复用尽可能多的代码?如何能够尽可能的缩短游戏设计师(策划)及美术设计师(3D/2D场景美术)的工作流程?市面上优秀的引擎往往都附带有所见即所得编辑器,这样的编辑器应当如何设计?网络游戏编辑器又有哪些可以从中借鉴和学习之处?

将尚不是很成熟的思考结果总结成本文。本人水平所限,许多错漏之处难免考虑不周全,如果有同学对本文所述的问题有任何想法,亦或是有其他文章与此相关,欢迎一起交流。

客户端逻辑的复用

把游戏客户端进行拆解,可以将其看成一个拥有输入、输出及内部逻辑循环的系统。玩家通过鼠标键盘发送消息给客户端,服务器通过网络接口发送消息给客户端,然后客户端于每一帧把当前对应的表现绘制到屏幕上。

客户端输入包括:Windows消息(键盘,鼠标,windows的其他消息,快捷键,定时器,摇杆等),网络消息(通过服务器或者其他玩家发送来的消息);输出包括:屏幕显示,网络消息(发送给服务器的响应或请求)。

事实上一个游戏编辑器也可以简单的看成类似于上述的系统,其输入包括:Windows消息(键盘,鼠标,windows的其他消息,菜单快捷键等,定时器等);输出则包括了屏幕显示,正常情况下编辑器不需要接受或发出任何网络消息(这里指与服务器进行逻辑上的通信,而非指通过版本控制系统进行数据的同步管理)。

实际上编辑器与客户端程序实际上都拥有相似的输入接口(Windows消息),只是同样的消息引发了不同的逻辑——在这里我们可以对输入接口做以抽象,并使用不同的实现来分别实现其逻辑,从而达到在编辑器中拥有热切换编辑状态和游戏状态逻辑的能力。(许多知名的游戏引擎都拥有类似上述的可在编辑器中切换编辑/游戏状态的功能,比如Crysis的SandBox编辑器,再如RunicGames的TorchLight编辑器等)。 (more…)

2ae8af3cdeb4.png

Hermite Curve 在绘制轨迹中的应用

0

 

在3D游戏的粒子系统中,往往可能有这样一类需求——伴随着人的动作,一条光带划过,或者伴随着武器的劈砍动作,一条刀光划过。

如果我们简单的在每次Tick的时候采样当前的位置朝向,并创建一截新的面片,往往会形成类似于如下图的粗陋效果:

不连续轨迹

之所以会产生一截一截的感觉,是由于在每次进行采样的时候,我们只能得到当前时刻的位置信息。因此尽管在从上一次到本次采样的过程中,轨迹实际经过的路程是一条平滑的曲线,可由于每一帧之间的时间不可能小到足够提供平滑曲线的采样精度,我们所能获得的总是一截截的折线。

怎样才能够通过为数不多的关键点,创造出一条平滑的曲线来呢?

Charles Hermite 提出的Hermite Curve解决了上面的问题。通过一系列的三维空间关键点,可以得到每个点处的切线,再经过Hermite Base Function的多项式计算,则可以得到插值点。

如图:

HermiteCurve示意

设P1,P2为平面上的两个点,T1,T2为两点处的切线,由点及点的切线,Hermite Spline就可以给出一个平滑过渡的曲线。

Hermite Base 多项式的参数如下表,其中t是从上一个点到当前点的插值系数。上一个点处为0,当前点为1。

Ogre在其Ogre::SimpleSpline类中实现了HermiteCurve。感兴趣的同学可以做以参考。

 

  expanded factorized
h00(t) t3 − 3t2 + 1 1 + 2t)(1 − t)2
h10(t) t3 − 2t2 + t t(1 − t)2
h01(t) − 2t3 + 3t2 t2(3 − 2t)
h11(t) t3t2 t2(t − 1)

事实上,上述做法也不过就是对Hermite Curve类型的样条曲线的利用而已。样条曲线实际上并不陌生,贝塞尔曲线就是一种我们关注最多的样条曲线。尽管其不适用于我们前述的场合——原因是贝塞尔曲线通过控制点计算出的曲线并非一条依次经过控制点的曲线。如下图所示(图片来源于:http://escience.anu.edu.au/lecture/cg/Spline/printCG.en.html):

bezier_spline 

参考资料:

1. Hermite Curve Interpolation. Hamburg (Germany), the 30th March 1998

2. Cubic Hermite spline

Go to Top