【Visual C++】游戏开发四十九 浅墨DirectX教程十七 三维天空的实现
本系列文章由zhmxy555(毛星云)编写,转载请注明出处。
文章链接: http://blog.csdn.net/zhmxy555/article/details/8685546
作者:毛星云(浅墨) 邮箱: happylifemxy@163.com
这篇文章里,浅墨准备跟大家一起探讨一下三维天空的几种实现方式,然后在几种方式之中选择最常用的一种进行重点突破,用一个C++类把这种三维天空的实现方式封装起来。这样以后要使用三维天空来辅助绘制某个游戏场景的话,准备好天空的纹理图,然后简单地敲几行代码,调用一下这个天空类中我们亲手写出来的函数就搞定了。先放一张程序截图:
程序源码在文章末尾有给出下载地址。
一、游戏行业所用编程语言的认知
上面讲到了类的封装,目前市面上的高性能三维游戏引擎其实就是在做这样的工作,把各种功能封装在一个个C++类中。浅墨经常收到怀揣游戏开发梦想的初学者们的邮件,询问进行游戏开发到底学什么语言最合适。浅墨在这里集中跟大家讲一下得了。
大家都知道,撇开C语言不谈,C++在目前高级编程语言中执行效率和性能首屈一指。大家也知道,三维游戏的画面渲染有着非常高的性能需求。就光这一条对性能的要求,什么C#,什么java等等,全都只有在一旁抹鼻子哭了。
所以,事实如此,现在市面上所有画质精美的单机游戏作品(鬼泣5,上古卷轴5,刺客信条3,仙剑奇侠传5前传,古剑奇谭等等……),所有的大型网络游戏(Dota2,英雄联盟,魔兽世界,龙之谷,剑灵等等等……),所有高性能的三维游戏引擎(虚幻3,Unity3D,Cry Engine3等等……),以及一些高性能的2D游戏引擎(Cocos2d-x等等),都是用C++来开发的。
其实游戏引擎并没有那么神秘,说白了也就是那么回事,用类封装好功能的C++代码而已。C++写出来的游戏引擎自然能跨平台。Unreal Engine3、Unity3D、Cocos2d-x等游戏引擎就是绝好的例子。
学好C++,你可以亲手写出Unity3D,亲手写出 Cocos2d-x,让大家都叫你大神,大家都用你写的游戏引擎做游戏,等着你什么时候心情好了更新一下给引擎加更多功能;而不是只会盲目跟风,今天大家说Unity3D火,就都去学Unity3D,明天大家说Cocos2d-x热门,就来学学Cocos2d-x。你学游戏引擎,学的只是人家某引擎作者某C++大神按心情来定的函数调用方式,学的只是如何调用一些别人写好的一些类,一些API函数。这样在别人规定给你的一些rule中固步自封,大家觉得有技术含量么?
我们是时候该该想一想了,为什么现在全球范围内优秀的三维引擎就是没有我们国产引擎的影子。
所以,无论是哪个平台,Windows也好,iOS也好,Android也罢,如果你真正想在游戏开发领域有所作为,混出个名堂,请学C++,请学计算机图形学,请了解计算机图形API(OpenGL或者DirectX),而不是在跟风某种“热门”的游戏引擎的大潮中随波逐流,在某种移动平台的游戏开发中迷信某某引擎,乐不思蜀,固步自封。
咳,扯远了,而且有些小愤青了,也原谅浅墨,浅墨没有歧视其他编程语言的意思。浅墨只是想表达,无论是哪个平台(Windows,Play Station,Xbox,Android,iOS,WindowsPhone, WUII),在三维或者高性能游戏开发领域,确实就是C++的天下。
如果大家对游戏引擎的概念不太了解,还请看浅墨写过的关于游戏引擎的导论:
【Visual C++】游戏开发笔记三十五 站在巨人的肩膀上:游戏引擎导论
二、三维天空技术阐述
回到正题来吧,讲今天的主题三维天空的实现。
不要看游戏世界中的天空好像是无边无际的,其实我们都被骗了。
在计算机的三维世界中,三维天空的绘制肯定不可能像现实生活中的天空一样,一望无际绵延无尽,往往是通过一种假象来现实的。这种假象与古代人所说的“天圆地方”有着异曲同工之妙。反正就是一个足够大的容器一样的东西把我们罩在里面,让我们像井底之蛙一样以为这就是整个世界,世界就这么大,天空就这么大。而这个足以罩住我们所置身的游戏世界的容器,可以是一个立方体,也可以是半球,甚至是一个足够大的平面。
目前描述三维天空的技术主要包括三种类型:
1.平面型天空(Sky Plane),仅用一个平面放到玩家头顶。这种方案太弱了,太容易被玩家们看穿,真实感太低,技术含量也太低。但是对于并不太注意远景的场景,用天空平面也不失为一种办法。在这种情况下,用纯色的雾来覆盖整个远景,使得远处充满神秘,遮一下羞也效果凑合。
2.天空穹庐(Sky Dome),放到玩家头顶上的是一个曲面,通常都会为一个半球。就像这样:
这种方案其实真实性最强,但是不是目前使用最广泛的方案,它涉及到天空无缝衔接的素材匮乏等的问题。
3.天空盒(Sky Box),即放到场景的是一个立方体。它是目前使用最广泛的三维天空模拟技术,网络上素材丰富,所以这次就用教大家用天空盒来模拟三维天空。天空盒经常是由24个顶点、六个面组成的立方体(或者直接从做好的X模型文件载入天空盒),并经常会随着视点的移动而移动,来刻画极远处玩家无法达到位置的天空。
天空盒对于我们来说并不是困难的事情,但是真正要在游戏中使得天空“好看”,那么,还需要有着漂亮的天空纹理素材图,可以在网上搜罗(下文有讲如何搜索),也可以拜托给美工童鞋们。
另外,在高级一些的应用中,天空盒的纹理可能同时会用来生成Cube Map,并用之来做水面倒影、云影、反光等很眩的特效,大家先有一个这方面的概念就好。
三. 天空盒的设计
本篇文章的核心知识登场。
1,准备天空盒纹理素材
天空盒的纹理自然就是我们这个天空盒子立方体每个面的纹理了,至少5个面,最多6个面,因为底面处是我们所在的土地,是地形,也就不用渲染为天空了。
这5个面可以分别单独成文件,像这样:
这5张纹理需要满足的条件是:按照规定的几个面拼接起来,能构成一幅360度并包含顶部的无缝衔接的全景图:
另外,有些游戏引擎设定了需要把5个面按某种方式连起来和成一幅图来使用,就像这样的天空盒素材:
互联网上关于天空盒的纹理素材资源很丰富,大家google/百度就可以找打很多资源的下载点。
建议用关键 skybox texture或者skybox download来google。
另外,如果想原创天空盒纹理的话,可以用DirectX SDK 中自带的DirectX Texture tool工具完成。
2 天空盒类的设计
好了,开始我们的本职工作,写代码吧。
我们今天的任务是写一个封装了天空盒渲染功能的类,我们给这个类取名为SkyBoxClass。
我们来看下这个类中有哪些内容。
最开始国际惯例,LPDIRECT3DDEVICE9类型的设备接口指针m_pd3dDevice自然不能少。
然后这个类中需要处理24个带纹理坐标的顶点来构成一个立方体盒子,自然少不了FVF灵活顶点格式和一个DIRECT3DVERTEXBUFFER接口的指针。
接着还要有五个纹理对象,分别储存5个面上的纹理图,所以一个LPDIRECT3DTEXTURE9类型的m_pTexture[5]自然也少不了。最后,还需要定义一个float类型的m_Length表示天空盒的边长。结构体和成员变量就是这些了,我们再来看一下需要有哪些成员函数。
首先构造函数析构函数我们写出来,接着再写三个函数就够了,它们分别是初始化天空盒顶点的InitSkyBox函数,加载纹理的LoadSkyTextureFromFile函数,渲染天空盒的RenderSkyBox函数。
SkyBoxClass类的轮廓就是这样了,那么把上面我们的思路实现成代码就是如下,即贴出SkyBoxClass.h中全部代码:
我们依旧只贴出核心代码main.cpp,其他的众多文件大家下源代码回去看就好了。
最后贴上揭露“天机”的镜头一张,大家其实就是在这个盒子中乐不思蜀的:
因为我们在这个程序中并没有限定移动区域。所以是可以任意飞翔的,如果你毅力够大(不去调相机的移动速度的话),完全可以飞啊飞,最后突出天空盒的包围,识破天机。不过,这估计得“飞”个几分钟哦。
文章最后,依旧是放出本篇文章配套源代码的下载:
本节笔记配套源代码请点击这里下载:
【浅墨DirectX提高班】配套源代码之十七下载
以上就是本节笔记的全部内容,更多精彩内容,且听下回分解。
浅墨在这里,希望喜欢游戏开发系列文章的朋友们能留下你们的评论,每次浅墨登陆博客看到大家的留言的时候都会非常开心,感觉自己正在传递一种信仰,一种精神。
文章最后,依然是【每文一语】栏目,今天的句子是:
迷茫时,坚定的对自己说,当时的梦想,我还记得。
下周一,让我们离游戏开发的梦想更近一步。
下周一,游戏开发笔记,我们,不见不散。