梁东东游戏开发.docx
- 文档编号:20726167
- 上传时间:2023-04-25
- 格式:DOCX
- 页数:10
- 大小:1.49MB
梁东东游戏开发.docx
《梁东东游戏开发.docx》由会员分享,可在线阅读,更多相关《梁东东游戏开发.docx(10页珍藏版)》请在冰豆网上搜索。
梁东东游戏开发
OGRE——阴影
姓名:
梁东东
班级:
0411102
学号:
2011211646
日期:
2014年6月19日
负责:
代码的编写和作品展示
OGRE—阴影
一、摘要
游戏引擎是一个为运行某一类游戏的机器设计的能够被机器识别的代码(指令)集合。
它像一个发动机,控制着游戏的运行。
游戏引擎提供了丰富的游戏资源,包括图像、声音、游戏动画等,游戏引擎则是按游戏设计的要求顺序的调用这些资源。
OGRE作为一款3D游戏引擎,其自身带有很多网格实体,如ninja、penguin、robot等,还有相应的骨骼动画,我们可以实现一些简单的角色的动作。
游戏中往往会有很多视觉上的效果,例如光晕,水滴,风吹草动等等,当然了还有阴影效果。
增添一些游戏特效会使得游戏本身比较接近显示世界,同时玩家在游戏世界里会更好的体验。
本文将介绍OGRE游戏引擎中的阴影效果。
二、引言
通过对《游戏开发与设计》这门课的学习,在课堂上,老师引导着我们了解游戏,了解一些游戏引擎OGRE,在本学期中期的时候老师布置了这门课程的大作业,我们组分到的题目是“阴影”。
起初我们并不了解如何实现阴影和用什么引擎来实现阴影。
因此,我们小组三个成员开始在网上查找资料,首先了解的就是OGRE引擎,而且决定使用的也是OGRE引擎。
然后我们小组3个成员就开始着手开工了,首先我们想要怎么实现阴影,说白了就是要有光源,要有物体才会出现阴影。
紧接着,我们又提出了自己的想法,可不可以实现动态的阴影呢?
因此我们又开始学习如何用OGRE来实现动态的阴影。
最后当我们实现了动态的阴影之后,我们觉得整个场景太单调了,于是想着先构造出摸您出一个日落时分的两个小人在房子旁边跳舞的场景。
最终,整个过程均实现了,同时,我感觉OGRE太强大了,它可以完成好多效果出来,而且我也深刻的明白我现在所学习的只是OGRE中的冰山一角,我好友好长的路要走,但是我坚信我可以做的更好。
而且通过坐本次的大作业,我也深刻的认识到了团队协作的重要性,三个臭皮匠,赛过诸葛亮。
只有一个好的分工,才会有一个好的作品,一个好的作品变会对自己的触动最大,激励着自己不断地学习!
三、方法
引擎摄象机(Camera)
Camera(摄象机)是我们创建来观察场景的,Camera的工作和SceneNode(场景节点)类似,Camera
对象有setPosition,yaw,roll和pitch函数,你可以把它附加在SceneNode上,就象SceneNode
一样,Camera的位置也和它的父亲相关。
象移动和旋转,你都可以认为一个Camera一个
SceneNode。
这个引擎的Camera与你预想不同的一点是一次只能有一个Camera。
就是说,我们不能为观察场景
的一部分创建一个Camera,再创建另一个Camera来观察场景的其他部分,然后在通过enabling或
disablingCamera来显示我们想要的场景位置。
但有一种替代的方法,创建一个SceneNode来作
为"cameraholders"。
这个SceneNode可以简单的设置在场景的位置和指向你想看的方向。
当要显示场景的一部分时,只需要把Camera附加在合适的SceneNode,我们会再看到这个技术在FrameListener的教程里
创建摄象机(Camera)
我们将覆盖ExampleApplication里常用的创建Camera的默认方法
找到 TutorialApplication:
:
createCamera 的成员函数,我们首先要做的是创建Camera
因为Camera是依赖他们所在的SceneManager,我们使用SceneManager对象来创建他们
增加下面这行代码来创建Camera:
//createthecamera
mCamera=mSceneMgr->createCamera("PlayerCam");
创建一个叫"PlayerCam"的Camera,我们可以使用SceneManger的getCamera函数,通过Camera
的名字来获得Camera。
下一件事将要设置Camera的位置和它的朝向,我们将空间对象放在原点附近,因此我们给Camera
设置一个好的距离在+Z方向上,摄象机将朝向原点,把这个加在上面代码的后面。
//setitsposition,direction
mCamera->setPosition(Vector3(0,10,500));
mCamera->lookAt(Vector3(0,0,0));
lookAt函数是很灵活的,你可以将Camera朝向任何位置来代替yaw,rotate,和pitch,SceneNode
也有这个函数,可以简单的设置Entity朝向任何方向在各种情况下。
最后我们要设置nearclippingdistance为5个单位,clippingdistance指定一个Camera多近和多远以外的物体不再看到。
设置nearclippingdistance可以让你看穿屏幕上的Entity
当你非常接近它们时。
当你距离一个物体很近时,它会充满整个屏幕,你只能看到它的很少一部分。
你可以同样设置farclippingdistance,这样引擎就不会渲染比这个值远 的任何事物。
它的主要作用是增加刷新率,如果你渲染远距离大数量物体到屏幕上。
设置nearclipping,增加这行:
mCamera->setNearClipDistance(5);
设置farclippingdistance可以类似的方法调用setFarClipDistance(尽管你不能使用它在后面
使用的模板阴影中)
Viewports(视口)
Viewport的概念
当你开始涉及多Camera时,那Viewport类的概念会对你很有帮助。
提出这个话题是因为我认为对
你理解引擎如何决定使用哪个Camera很重要。
在引擎里可以同时运行多个SceneManger。
也可以把
屏幕分成多个区域,并在屏幕上由分离的Camera渲染分离的区域(可以想象为一个游戏分开屏幕给
两个玩家)。
我们会在后面的高级教程里再讲解。
理解引擎如何渲染场景,要考虑引擎的三个结构Camera,SceneManager,RenderWindow。
RenderWindow我们还没被涉及。
但他是任何物体被显示的基础,SceneManager对象创建Camera
来观察场景,你必须告诉Camera你的Viewport.引擎最常用的,你一般只创建一个Camera,注册
它使用RenderWindow,并只有一个Viewport对象。
在这个教程里,我们学如何让Camera去创建Viewport.我们可以设置这个Viewport的渲染场景时
背景色。
创建Viewport
我们要覆盖ExampleApplication里Viewport的创建方法,找到TutorialApplication:
:
createViewports这个成员函数,我们简单的调用RenderWindow的addViewport函数并向它提供
我们使用的Camera.ExampleApplicationm将Window作为我们的RenderWindow
增加下面的代码:
//Createoneviewport,entirewindow
Viewport*vp=mWindow->addViewport(mCamera);
现在我们有了Viewport,我们能对它做些什么?
答案是:
不多.我们能做的最重要的事是调用
setBackgroundColour函数来来选择哪个颜色作为背景色.因为我们要在这个教程里处理光照
所以把背景设置为黑色
vp->setBackgroundColour(ColourValue(0,0,0));
ColourValue表达为在0和1的范围内红绿蓝颜色值参数.最后,最需要我们去做的是设置Camera
的aspectratio(纵高比例)如果你不经常使用标准的全窗口视口,那么错误的设置会得到一个
怪异的场景.我们先使用默认的比例,进入下一步
//Alterthecameraaspectratiotomatchtheviewport
mCamera->setAspectRatio(Real(vp->getActualWidth())/Real(vp->getActualHeight()));
以上就是我们对Viewport类的一个简单的使用
LightsandShadows(光和阴影)
引擎支持的影子类型
引擎支持3种影子类型:
1.ModulativeTextureShadows(SHADOWTYPE_TEXTURE_MODULATIVE),是三种里最不精确的,
创建黑和白色的render-to-texture阴影投影
2.ModulativeStencilShadows(SHADOWTYPE_STENCIL_MODULATIVE),这个技术渲染所有的
阴影体做一次相乘,当所有的非透明物体被渲染后.他不象AdditiveStencilShadows那么精确.
3.AdditiveStencilShadows(SHADOWTYPE_STENCIL_ADDITIVE)这个技术在场景里渲染分别
每个灯光作为附加的PASS.他对硬件要求比较高,因为每个光源都需要一个PASS
引擎并不支持软阴影,如果你需要软阴影,那你要写你自己的顶点和片元程序.
在引擎里使用阴影
在引擎里使用阴影是相当的简单,SceneManager类有一个setShadowTechnique成员函数让你能设置
需要的阴影类型.当你创建一个Entity(实体)后,调用setCastShadow函数来设置它是否投影
我们需要设置环境光为全黑,并设置阴影类型,找到TutorialApplication:
:
createScene成员
函数并增加下面的代码
mSceneMgr->setAmbientLight(ColourValue(0,0,0));
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
现在SceneManager使用additivestencilshadows的阴影技术.我们在场景创建一个对象并
让它投影
ent=mSceneMgr->createEntity("Ninja","ninja.mesh");
ent->setCastShadows(true);
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
nijia.mesh已经被预装载到ExampleApplication,我们需要让Nijia站在什么东西上(好让阴影
投在它上面).为此,我们为他创建一个简单的平面让他站.这并不意味这是使用MeshManager的教程.
但我们会进行很基础的讲解,因为我们不得不创建一个几何体.现在我们要让正Y轴作为平面的法线,
而与原点没有距离
Planeplane(Vector3:
:
UNIT_Y,0);
现在我们需要将这个平面提交,好让我们的程序可以使用它.MeshManager类会追踪我们程序装载
的所有网格.createPlane成员函数提供了平面的定义和创建网格的参数,让我们的平面可以使用:
MeshManager:
:
getSingleton().createPlane("ground",
ResourceGroupManager:
:
DEFAULT_RESOURCE_GROUP_NAME,plane,
1500,1500,20,20,true,1,5,5,Vector3:
:
UNIT_Z);
我不希望现在就指出MeshManager是如何使用的(去看API的参考,如果你想知道每个参数的细节)
基本的我们已经注册了一个叫"ground"的1500X1500尺寸的新网格,我们可以根据这个网格创建
一个实体并把它放到场景里面
ent=mSceneMgr->createEntity("GroundEntity","ground");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
在完成前,还要对我们的地面做两个处理,第一就是告诉SceneManager我们不想让他投影,而是要让他来接受投影.第二是我们需要给它设置一个纹理.我们的Robot和Nijia网格已经有材质脚本来定义纹理,当我们手动的创建我们的地面网格时,并不能指定它用什么纹理.我们使用
"Examples/Rockwall"材质脚本
ent->setMaterialName("Examples/Rockwall");
ent->setCastShadows(false);
现在我们的Nijia和地面在场景里,让我们编译程序..我们什么都看不到!
在前一个的教程里,我们
添加Robots,并显示的很好啊..Nijia看不到的原因是场景的环境被设置为最暗.因此我们接下来
要添加一个光
光的类型
引擎提供了3种光
1Point(点光源)(LT_POINT)它发射光想艘有的方向
2Spotlitgh(聚光灯)(LT_SPOTLIGHT)一个聚光灯工作就好象手电筒一样.你有一个光的
起始位置和光的方向,你可以告诉光有多大角度,通过设置光内环和外环(innercircle和
outercircle)
3Directional(方向光)(LT_DIRECTIONAL)方向光模拟场景里一个方向上非常远的光.
比如一个夜晚的场景,你希望模拟月光,你可以通过在场景设置环境光,但这样和实际不符,因为
月亮不能平等的照在所有物体上(太阳也一样).而实现的方法就是这个创建一个方向光
光有很多的属性来描述它的视觉效果.两个最重要的的光属性是diffuse和specular颜色.每个材质
描述都定义了diffuse和specular来实现材质的光反射.我们将在后面的教程里学会去控制
创建光
在引擎里创建光,我们调用SceneManager的creteLight成员函数并提供光的名字,这与我们创建
Entity或Camera.创建光后,我们可以手动的设置它的位置或把他附加在SceneNode上来移动
和Camera对象不同,光只有setPosition和setDirection函数.如果你需要创建一个固定的光
你可以调用setPosition成员函数,如果你要让光移动(比如创建一个光追随着角色),那要把
光附加在一个SceneNode上
我们从基础的点光开始,第一件事是创建光,设置类型和位置
light=mSceneMgr->createLight("Light1");
light->setType(Light:
:
LT_POINT);
light->setPosition(Vector3(0,150,250));
我们已经创建了光,可以设置diffuse和specular颜色
light->setDiffuseColour(1.0,0.0,0.0);
light->setSpecularColour(1.0,0.0,0.0);
现在编译运行程序,成功!
我们现在看到Nijia和投影.一个要注意的是你看不到光源,你看的
到光的产生,却看不到光对象本身.一些教材里会添加简单实体来显示光是从那里发射出来的
人物动起来核心代码如下:
_aniState=_ent->getAnimationState("Dance");
_aniState->setEnabled(true);
_aniState->setLoop(true);
_aniState->addTime(evt.timeSinceLastFrame);
_SinbadEnt=mSceneMgr->createEntity("Sinbad","Sinbad.mesh");
_SinbadNode->attachObject(_SinbadEnt);
四、截图
图1最初简易的阴影
图2日落场景图
图3黄昏跳舞的小人图
五、总结
通过对OGRE的学习,我们了解了OGRE引擎工作的机制,更加的感觉到OGRE的强大,当然,最重要的还是我们利用OGRE实现了动态的阴影过程。
最后,本文主要论述了游戏中的阴影效果及其实现原理,而我认为这正是老师希望我们通过这门课程的学习能真正获取的知识。
游戏中所有的景物被启动都比较容易,往往都是一两行代码的是,但是其真正实现原理确实很少有人关系的。
作为一个游戏的玩家、学习者还有希望自己将来从事这个行业的我,希望所有涉及到游戏制作的人们能够真正的去了解游戏画面背后的数学方法,并能够提出新的更好的算法,实现更为接近现实的效果。
六、参考文献及网址
【1】FelixKerger.Ogre3D1.7入门指南翻译版(Ogre_3d_1.7_beginner_guide)
【2】Ogre初中级教程
【3】file:
///D:
/OGRE/Ogre基础教程-搜狐博客/Ogre的基础教程
(二)-饭团推广会-搜狐博客.htm
【4】file:
///D:
/OGRE/Ogre基础教程-搜狐博客/Ogre的基本教程
(一).htm
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 东东 游戏 开发