最牛的游戏引擎之一--Source剖析(转片老贴)
cs:source吧
全部回复
仅看楼主
level 8
leeshichina 楼主
原文地址:http://17de.com/library/HL2/D3DTutorial10_Half-Life2_Shading.pdf
  在Half-Life 完成之后不久,Valve开始筹备他们的下一个主打游戏--Half-Life2。在商讨游戏引擎的采用问题上,开发小组明白到原版游戏所采用的改良Quake 1引擎对于Half-Life 2来说显得过于破旧,而且在很多的方面都不符合这一代游戏发展的要求。于是,vlave的开发小组决定从美工设计以及游戏代码开始,设计出一个全新的游戏框架,并在其中加入了一套来自havok的定制物理引擎。
  对于一个游戏来说,“引擎”就是一个系统,就像是一辆汽车的发动机一样,他能输入来自加速器的动能,并输出到轮子的转动。软件(在这里为游戏)的引擎实现的东西和汽车的发动机一样,输入来自框架(某些程序或者文件的片段),然后输出程序员们想要的结果。再次拿汽车的发动机为例,一个软件的引擎不能自行运作,他必须依靠另外一个系统,就好像,你只能开着“一台汽车”而非“一台发动机”去上班。在Source中,一个纯粹的引擎只能是一堆代码,完全不具有可玩性。所以不难对引擎下这样的定义:引擎就是一套让游戏元素发生互动关系并将其编译成可玩程序的代码或程式,依靠框架进行操作。
Source引擎总览
  Source并不是一套简单的3D引擎,也可以是说,他并非只是一套渲染器。Source引擎包含了很多不同的模组,程序员可以在引擎的程序包中方便地取出以及添加进其他的元素。
  在这篇文章里面,我将会为大家展示这些模组是什么回事并且对游戏产生怎样的影响。在下面将要陈述的问题主要讲解在Source引擎中一些令人惊奇的模组是怎样对整个游戏的画面以及游戏效果产生影响,而不是去解释Source引擎的代码怎样去运作。对于此,可能大家会觉得比较枯燥,毕竟,这些在程序实现上的问题针对的是对游戏有一定研究的玩家。我们并没有打算深入到Source的程序代码进行研究,因为这些已经不属于我们一般老百姓可以研究的范畴了。在这里必须要给读者澄清一下,由于目前Source引擎的非公开性,我们并不能准确地将Source引擎中每一个模组的特性都准确地表示出来,如果你一定要深入研究的话,请参考Half-Life 2发布之后的 SDK 参考文档以及Valve以后的白皮书。本文的章节细分以笔者对Source引擎的了解为依据。请根据实际情况印证并参考其他专著以及文献。
· 3D 引擎
o 渲染器
§ Pixel 、vertex shaders
§ 光影效果
§ HDR (High Dynamic Range)
o 动画以及角色面部表情
o 几何构成
o VGUI游戏界面
· 物理引擎,基于Havok 定制的物理引擎
o 刚体的动力学模型以及关节约束机制
o 弹性机构、绳索机构、布纹处理、车辆系统
o 水以及火光
o 粒子系统
o 怪物/NPC/程序 上的物理学系统
· 材质系统
· AI 系统
在这里,我尚且用3D engine来描述造Source引擎中,生成引擎输出图像及其几何体的模组。
2013年06月25日 06点06分 1
level 8
leeshichina 楼主
渲染器
  这部分最能体现显卡的功力,也是玩家最为注重的一个重点。渲染器的作用主要主要功能就是采集画面几何体和材质的数据,通过一系列繁杂的过程,生成一个三维的图像。Valve并没有重新创造Source引擎的渲染器而采用了Microsoft DirectX 9.0 的 API,并借助Half-Life SL高阶编程语言编写引擎,在很大程度上节省了宝贵的时间,这归功于 DirectX9良好的硬件兼容性以及先进的代码设计流程。原有的Half-Life 1引擎被设计成支持 OpenGL and Direct3D的双模式,但正如各位所见,这个引擎在Direct3D模式下的渲染十分糟糕,特别是在目前主流的显卡上工作时,其效率以及画质远不及OpenGL模式下的表现。在设计Source引擎的时候,Valve放弃了ogl的渲染模式进而采用DirectX架构,以增强其硬件兼容性以及对未来特效的支持,比如是Shader2.0b甚至是Shader3.0 Model的支持。
Pixel and Vertex shaders
  Shader就是一些能够在GPU/VPU上执行的程序句段。目前市面上流行的游戏中,采用实时渲染的画面均大量运用了Shader,你的显卡无时无刻在处理着这些Shader信息。现代显卡主要的改进就是用Shader代码替代沿用自GeForce GTS时代固定的硬件T&L (Transform and Lighting)。Shader允许程序员创建他们喜欢的Shader特效程序片段以取代有限个数的固化在显卡核心中的预设特效。经过Shader编程之后,如果有一个关于bump mapping的技术推出,程序员只需改写或者加入该部分的Shader代码便能使这些特效运行在现今的显卡上,而不需等待下一代的显卡出现。于是,显卡的处理特性便得以最大程度地延伸。在程序接口方面,由Microsoft推出的HLSL、nVIDIA推出的Cg、以及OpenGL小组推出的GLSL都是编写Shader的工具。能和目前个人PC、工业用电脑上的DirectX以及OpenGL很好地对应。
  Source对directx中的pixel/vertex shaders version 2.0提供了完整的支持,Valve最近的声明指出Source引擎将在未来硬件成熟的时候提供对Shader3.0的支持。目前的Source引擎中,所有的directX 9 Shader均在 (high level shader language)下完成,对代码的运用上只需简单地插入片段,省却了在底层使用汇编语言重编译的麻烦,增加了Source引擎的弹性。在引擎代码方面,所有的代码均用C/C++ using Visual Studio 6.0进行开发,有很大的开放度以及可扩展性,目前已经有数家公司得到Valve授权采用Source引擎进行下一代游戏的开发,除传统的FPS游戏之外,还有aRPG,SPD等模式,相信在明年开初将会见到很多采用Source引擎制作的佳作。
  对于玩家,Shader就能实现依靠驱动程序实现更加多以及更富弹性的特效,在Half-Life 2中最为凸出的Shader2.0特效就是那些吸引眼球的充满反射和折射的水纹效果。在目前推出的基于Source引擎的CS:Source选项设置中单独对水纹效果提供了一个现实效果设置选项。
2013年06月25日 06点06分 2
level 8
leeshichina 楼主
环境光立方体贴图
《半条命2》动态物件和人物模型的光影效果
前面介绍了静态场景的光影效果,下面我们来看看在《半条命2》中的动态模型是如何绘制的。
核心技术-基于环境光立方体 (Ambient cube)的光能传递凹凸贴图技术
由于动态模型的位置和形状都有可能发生变化,所以就不能像静态场景那样处理了。动态模型所受到的光照也是由直接光照和间接光照组成的。在Source引擎中,只能从照射一个模型的所有直接光源中选出有两个最主要的来使用比较复杂的光照公式进行实时计算,而其他比较次要的直接光源以及场景中的间接光源都会被预先保存到一个称为“环境光立方体”的东西中。
环境光立方体
首先Valve的技术人员在关卡场景中放置一个虚拟的立方体,然后地图编辑器就分别对立方体的每个面计算出垂直通过这个面的环境光的颜色和强度。场景里那些比较次要(远或暗)的直接光源,也被计算在内。
对于每个面都计算一个光照颜色,可以得到六个颜色,基本上代表了从四面八方射来的穿过这个体积中的所有比较次要的光线的信息。这六个颜色是可以预先计算出来保存在关卡场景数据里的。
通 过模型表面的法线来决定取这六个颜色的比重并将它们混合,就可以得到一种类似于光能传递的效果。在环境光立方体的六个面中,必然有至少三个面会在法线的相 反方向,这些面的颜色忽略不计。所以一般只有另外三个面的颜色会用到。法线方向越正对哪个面,这个面对应颜色所占的比重就越大。
用环境光立方体技术渲染的蚁狮模型,虽然没有加入凹凸贴图,但是已经有一种类似光能传递的效果。
从立方体环境贴图中获取光照的着色器代码:
float3 AmbientLight( const float3 worldNormal)
{
float3 nSquared = worldNormal * worldNormal;
int3 isNegative = ( worldNormal< 0.0 );
float3 linearColor;
linearColor = nSquared.x * cAmbientCube[isNegative.x] +
nSquared.y * cAmbientCube[isNegative.y+2] +
nSquared.z * cAmbientCube[isNegative.z+4];
return linearColor;
}
在前面说道为了结合使用法线贴图,对于静态场景,一个面对应着三张光照贴图。而在这里也是类似的,一个动态模型对应着三个环境光立方体。这三个环境光立方体面上的颜色是分别根据各面局部坐标系的三个基向量来计算出来的。
a.b.c分别使用相对于三个基向量的环境光照图和环境光立方体的效果
我们把法线贴图贴到场景中看一看:
法线贴图
按照和静态场景类似的方法用法线贴图来寻址环境光立方体的颜色,就可以得到下面的效果了:
和前面没有凹凸细节的图对比一下吧:
不要忘了,模型本身也是有材质贴图的。我们把它贴上去看一看:
模型自身的材质贴图,没有光照
如果把光照效果和它混合,就成了这个样子:
混合操作依然是颜色各通道相乘。角色表面具有凹凸细节。
和没有使用法线贴图的效果对比一下:
没有凹凸贴图
漫反射的部分完成后,就该加入高光了。对于角色的高光,Source引擎仍然使用高光环境反射贴图。
完全的高光环境反射,也没有加入凹凸贴图,好一只光滑的金属蚁狮
加了凹凸贴图
高光强度贴图,也是越白的地方高光越强,
我们可以看出蚁狮表面的高光并不是很强的
用高光强度贴图去过滤高光
把高光叠加到漫反射部分上去,得到最后的效果。
折射效果:
折射效果用于场景中的玻璃或者水面之类的特效。如果我们把场景中的一个多边形面所挡住的东西画到贴图上,再贴到这个面上去,那么这个面看起来就是透明的了。Source 引擎中使用 StretchRect() 从场景渲染后暂存的帧缓存中复制出一个纹理,就是我们常说的实时渲染到纹理。如果我们在贴这个贴图时做一个扰动,比如加一些水波或者凹凸的扰动,那么这个面看起来就像是水面或者凹凸不平的玻璃的折射的效果了。这个纹理将参照 dudv 凹凸贴图或法线贴图在屏幕空间中做适当的偏移,然后再投射到几何体上。借助法线贴图和最新的DirectX 9.0 Pixel Shader技术,加入这个扰动的过程十分容易实现。
部分着色器代码:
sampler RefractSampler: register( s2 );
sampler NormalSampler: register( s3 );
sampler RefractTintSampler: register( s5 );
const float3 g_EnvmapTint: register( c0 );
const float3 g_RefractTint: register( c1 );
const float3 g_EnvmapContrast: register( c2 );
const float3 g_EnvmapSaturation: register( c3 );
const float2 g_RefractScale: register( c5 );
struct PS_INPUT
{
float2 vBumpTexCoord: TEXCOORD0;
float3 vWorldVertToEyeVector: TEXCOORD1;
float3 x3tangentSpaceTranspose: TEXCOORD2;
float3 vRefractXYW: TEXCOORD5;
float3 projNormal: TEXCOORD6;
};
float4 main( PS_INPUT i ) : COLOR
{
// Load normal and expand range
float4 vNormalSample = tex2D( NormalSampler, i.vBumpTexCoord);
float3 tangentSpaceNormal= vNormalSample * 2.0 -1.0;
float3 refractTintColor= 2.0 * g_RefractTint * tex2D( RefractTintSampler, i.vBumpTexCoord);
// Perform division by W only once
float ooW= 1.0f / i.vRefractXYW.z;
// Compute coordinates for sampling refraction
float2 vRefractTexCoordNoWarp= i.vRefractXYW.xy * ooW;
float2 vRefractTexCoord= tangentSpaceNormal.xy;
float scale = vNormalSample.a * g_RefractScale;
vRefractTexCoord = vRefractTexCoord * scale;
vRefractTexCoord += vRefractTexCoordNoWarp;
float3 result = refractTintColor * tex2D( RefractSampler, vRefractTexCoord.xy);
return float4( result, vNormalSample.a);
}
2013年06月25日 06点06分 4
level 8
leeshichina 楼主
材质系统
  在Source引 擎中的材质系统被赋予了物理特性以及贴图外观的特性。例如,给一块板赋予木材的材质,这块板便具有了木材的所有物理以及外观特征,重力、韧性、声学特性等 均被附加到这块板上。材质特性方面保留了诸如密度、表面材质、耐压度、以及当折断或者敲击时发出的声响,虽然这些在众人眼中看是一些很简单很必然的事情, 但在游戏中,这些细节将会是游戏增加其感染力的最佳途径。此外,AI系统还能就材质系统提供的信息,反馈给NPC以使其对战术作出相应的调整。当然,玩家 也可以充分利用材质的特性从而得到更多的通关方法。
木板被赋予了物理刚节点之后,破裂之后的断层不再如一般游戏那样刀切般平整。
AI系统
   AI,Artificial Intelligence,近年来在电脑领域是一个突飞猛进的科研领域,一个优秀的AI系统,能对其周围的环境智能地作出非线性的反应并采取相应的行动。 最重要的是具有依据周围环境参数的变更而决定系统行动的能力,否则,就不能称之为真正的AI。一个惯常的AI系统,会使角色根据当前任务的可行性、对主要 任务影响的重要性以及目前的周遭环境作出判断以选择达到预定目的的最佳途径,而怎样选择最佳的动作以达到这个目的,就是一个AI系统优秀与否的体现。
聪明的NPC借助矮墙以及队友在对角线火力的掩护下弓身前进。
  老实地说句,笔者并不完全明暸Source的AI系统所能够完成的任务,Valve关于Half-Life 2的白皮书中就说过很多的东西表明Source里面的AI系统是多么的强大,大意就是下面的几点(已经足够让目前每一个游戏汗颜的了)。
允许关卡设计师以I/O接口联系游戏中的实体以控制AI系统。
成熟的导航系统,可以实现角色的跑动、飞行、跳跃、下蹲、上楼梯和爬手扶梯甚至在地下的挖掘动作。我们在cz中的机器人已经见识过新一代的导航系统是如何地高超。
AI系统能依靠视觉、听觉以及嗅觉感知到物体 的存在
AI的关系决定敌友以及其他实体的关系
战斗AI允许AI角色进行团队攻防,他们知道何时推进、何时撤退、何时伏倒寻找掩护等等的战斗动作
如果一个NPC看到你向一个关键的物体跑去的时候,他会判断你对该物体要作出的动作而采取相应的行动
大规模的NPC进攻将一道桥弄垮这些细节将会脱离Valve的剧本随时地,在不可预见的情况下发生
AI知道移动重型物体是难以被快速移动的。
AI能清楚地知道他看到你的最后位置,并会对你逃跑的路线作出判断,以采取相应行动。
NPC会拒绝执行来自玩家的愚蠢的命令
AI能使用物理存在的物体。
   在游戏中NPC的AI着实让笔者大吃一惊,比如在TrainStation的一幕,主角刚刚到达City17,被NPC带到一个阴暗的长廊上准备接受洗 脑,途中听到一间房间内发出人类疼苦的哀嚎,好奇的主角把头凑过去那个房门上打开的小窗户想了解里面发生什么事情,这时,屋内的NPC会判定屋子里面发生 的事情不是主角所应该看到的,于是,NPC会走过来,唰地一声将小窗户关上……类似这种行为判定的例子在游戏中往往会是通关的关键。Source引擎做到 了主角和NPC之间很好的互动以及沟通
2013年06月25日 06点06分 8
level 8
leeshichina 楼主
2013年06月25日 06点06分 9
level 14
一会睡觉前用手机阅读一番哈哈
2013年06月25日 14点06分 10
欧了![星星月亮]
2013年06月26日 04点06分
这个办法不错
2013年06月29日 16点06分
1