Hi-ho, Silver! 在一个商业英雄辈出的年代,让我们用技术做一次华丽的冒险。向Linus致敬,向Stallman致敬!
分类: C/C++
2011-09-05 15:13:23
Sky
Ogre提供了3种不同类型的天空:天空盒,天空穹和天空面。
天空盒
一个天空盒基本上是场景中一个围绕所有对象的巨大的立方体,我们添加代码如下:
mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox");
显示效果:
(注意:天空盒有些斜纹模糊,因为使用的纹理是低分辨率的,如果有高分辨率的纹理,天空盒看起来会更好^-^)
当我们调用setSkyBox的时候,我们可以设置几个有用的参数。第一个参数决定了是否启用天空盒,如果以后你想禁用天空盒,只需简单的调用
mSceneMgr->setSkyBox(false, "");
第二个参数是用于天空盒的材质脚本。第三个和第四个参数对于理解天空盒是十分重要的。第三个参数设置了天空盒离开摄像机的距离。第四个参数设置天空盒是否在场景中其他物体之间绘制。让我们看看把距离参数从默认值5000改成非常近后会发生什么:
mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 10);
效果:
是的,没有变化,这是因为第四个设置是否先绘制天空盒的参数,其默认值为true。如果天空盒先绘制,然后任何之后绘制的东西将被绘制在其之上,从而使天空盒总是出现在背景中(注意:你不应该将距离设置的近于摄像机的近裁剪距离,否则将看不见它)。实际上,最好不是先绘制天空盒,因为这样的话所有的东西都会被绘制。当最后绘制天空盒时,只有可见部分被绘制了,这将少许提升速度。所以,试试最后绘制天空盒:
mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 5000, false);
显示的效果和以前没区别,但是现在,天空盒的不可见部分不会被绘制。当使用这项技术时,有一件事你需要注意,当你把天空盒设置的太近时,你可能会裁减掉部分场景中的物体,如下:
mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 100, false);
效果:
如所见,地面戳穿了天空盒,这肯定不是我们想要的。如果你在你的应用中使用天空盒,你必须决定你想如何使用它们。最后绘制天空盒所得到 的速度提升是非常有限的,并且你不得不注意不要掩盖其他的物体(除非那是你想要的)。总的来说,把第二个参数之后的参数留为默认值是一种安全的选择。
天空穹
天空穹和天空盒非常相似,可以通过调用setSkyDome使用它们。围绕着摄像机的巨大的立方体将被创建并呈现出来,最大的区别在于 纹理以一种球形方式映射到天空盒上。你看到的仍旧是立方体,但是它看上去像纹理围绕着球形表面包裹。这种方法最主要的缺点是在立方体的底部不会映射纹理。 所以,你总是需要一定类型的地形去遮掩。
添加如下代码:
mSceneMgr->setSkyDome(true,"Examples/CloudySky",5,8);
效果:
setSkyDome的前2个参数和setSkyBox是一样的,并且你也可以通过调用'mSceneMgr->setSkyDome(false, "");'禁用天空穹。
第三个参数是天空穹使用的曲率,API参考文献建议使用2到65之间的值,低值用于更好的距离效果,高值用于低失真和平滑效果。
第四个参数是纹理平铺的次数,根据纹理的大小而调整,注意这个参数的类型是Real(floating point),不是integer,你可以设置为1.234。
第五和第六个参数是距离和是否先绘制,在天空盒里已经讨论过了。
天空面
天空面和天空盒、天空穹不同。我们仅仅把纹理映射到一个简单的面上,而不再映射到一个立方体上。
我们先创建一个平面,使其朝下,然后我们将调用setSkyPlane方法,该方法不像天空盒和天空穹的方法那样有一个距离参数,距离被设置在平面的d变量中,见如下代码:
Ogre::Planeplane;
plane.d=1000;
plane.normal=Ogre::Vector3::NEGATIVE_UNIT_Y;
现在我们有了平面的定义,我们可以创建天空面了,注意第四个参数是天空面的尺寸而第五个参数是纹理平铺的次数,代码如下:
mSceneMgr->setSkyPlane(true,plane,"Examples/SpaceSkyPlane",1500,75);
效果:
我们创建的天空面有两个问题,第一,使用的纹理分辨率太低,平铺后效果不好。最主要的问题在于如果你朝边上看,将看到天空面的结束。像这样:
基本观点是当你的景点周围都是高山或丘陵时使用天空面是有用的。
setSkyPlane的第六个参数类似天空盒和天空穹中的定义'是否先绘制'的参数,第七个参数允许你定义天空面的曲率,所以我们可以不再使用一 个平面,而是有曲率的表面。现在,我们还必须设置x和y的段数(初始时天空面是一个大的正方形,但是如果我们想平面有曲率的话需要用许多小的正方形组成平 面),第八和第九个参数用来设置x和y的段数,代码如下:
mSceneMgr->setSkyPlane(true,plane,"Examples/SpaceSkyPlane",1500,50,true,1.5f,150,150);
现在看起来效果好多了:
同样,你可以使用'mSceneMgr->setSkyPlane(false, Ogre::Plane(), "");'来禁止天空面。
至于该使用哪种完全取决于你的应用。如果你要看你周围的一切,甚至是y的负方向,那么你只能选择天空盒。如果你有地形,或者类似地板之类的,那么使用天空穹看起来更真实。如果你看不到地平线,那么使用天空面看起来效果更好并且只需要一点点GPU代价。