OGRE基础教程 二 Cameras, Lights, and Shadows

英语水平有限,欢迎大家批评指正微笑

本文并没有将原文全部翻译,只是将其中的一些知识点翻译总结了一下,想要查看详细讲解的话,可以到原文处看一下,附上英文原文地址:http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Basic+Tutorial+2&structure=Tutorials

Cameras

    Cameras是用来查看我们所创建的场景的,它是一个功能有点像SceneNode的特殊的对象(Object)。Cameras对象有 setPosition, yaw,rollpitch 三个功能函数,可以把Cameras对象和任意的SceneNode绑定(attach)。就像SceneNode一样,Cameras的位置是相对于他的父节点(parent)的。对于所有的动作(movement)和旋转(rotation),都可以把Camera看做一个SceneNode.

    Ogre Camera同时只能使用一个,就是说,我们不能创建一个Camera来查看场景的一部分,再创建另一个Camera查看场景的另一部,然后根据我们想要查看的那一部分场景来决定哪个Camera有效或无效。而是创建SceneNodes作为“camera holder” ,这些SceneNodes只是放在场景中并指向Camera要看的方向。当要显示窗口的某一部分时,Camera只需要绑定到对应的SceneNode上即可。

Creating a Camera

    我们使用SceneManager对象来创建Camera:

                                                                            void  createCamera ( void )
                                                                            {
                                                                                    // create the camera
                                                                                    mCamera= mSceneMgr->createCamera("PlayerCam" ) ;
                                                                            }       

   我们使用上面的代码创建了名为“PlayerCam”的Camera对象,如果不使用指针保存所创建的Camera对象,可以使用SceneManager对象的getCamera函数通过Camera对象的名字来获取Camera对象。           

    下面设置Camera对象的位置和他所面向的方向:

                                                                                // set its position, direction 
                                                                                mCamera->setPosition(Ogre::Vector3 ( 0 , 10, 500 ) ) ;
                                                                                mCamera->lookAt(Ogre::Vector3 ( 0 , 0 , 0 ) ) ;

    lookAt函数很好用,你可以让Camera对象朝向你想要的任意方向,而不需要yaw,rotate和pitch。SceneNodes也有这个函数,很多情况下可以使对Entity朝向的位置的设置变得更容易。   

     最后来设置一个5个单位的近裁剪距离(near clipping distance),Camera的裁剪距离是指多远或多近你回看不得东西。设置近裁剪距离使你距离Enitiy很近时可以看穿他(而看到他后面的东西)。另外一种情况是距离一个Object太近而看不到屏幕,只能看到这个Object的一部分。也可以设置远裁剪距离(far clipping distance),当距离某一个事物的距离超过给定的远裁剪距离值时,将停止引擎对该事物的渲染。如果你在屏幕上渲染大量事物的时候,这对于提供帧率(framerate)有很重要的作用。

      设置近裁剪距离:mCamera->setNearClipDistance(5 ) ; 设置远裁剪距离要用setFarClipDistance函数。

Viewports

      当你处理多Cameras时,Viewports类的概念对你将会很有用。Viewports对你理解Oger如何决定使用哪个Camera来渲染场景很重要。Oger可能同时会有多个SceneManager运行(running),也可能屏幕被分成了多个部分,并且让不同的Camera来渲染不同的屏幕区域。   

      理解Oger的三个组成部分:Camera,SceneManager和RenderWindow。RenderWindow是所有东西显示的窗口,SceneManager对象创建Camera来查看场景。必须告诉RenderWindow使用哪个Camera来渲染窗口,以及渲染窗口的那一部分。你告诉RenderWindow渲染的那一部分就是你的Viewport。在Ogre的很大一部分的情况下,你只需要创建一个Camera,把Camera注册给你的RenderWindow,这样就只有一个Viewport对象。

Creating the Viewport

    我们调用RenderWindow的Viewport函数来创建Viewport并分配(supply)给正在使用的Camera。代码如下:

    // Create one viewport, entire window
    Ogre ::Viewport * vp = mWindow-> addViewport( mCamera ) ;

    //mWindow就是RenderWindow

    我们可以调用setBackgroundColour函数来设置背景颜色:vp->setBackgroundColour(Ogre::ColourValue (0 , 0 , 0 ) ) ;

   最后也是最重要的是要设置Camera的图像纵横比,如果你除了标准的全屏视口外还在使用其他的东西,那么如果没有设置图像纵横比的结果会导致一个很奇怪的场景。所以即使我们正在使用默认的图像纵横比,我们也将要设置一下:

   // Alter the camera aspect ratio to match the viewport
    mCamera ->setAspectRatio (Ogre :: Real ( vp-> getActualWidth( ) ) / Ogre :: Real( vp -> getActualHeight ( ) ) ) ;

   完整的视口创建函数如下:

                                           void   createViewports( void )
                                            {
                                                    // Create one viewport, entire window
                                                   Ogre:: Viewport* vp =mWindow -> addViewport ( mCamera ) ;
                                                   vp-> setBackgroundColour( Ogre :: ColourValue ( 0 , 0 , 0 ) ) ;
                                                   // Alter the camera aspect ratio to match the viewport
                                                   mCamera-> setAspectRatio( Ogre :: Real (vp -> getActualWidth ( ) ) /Ogre :: Real ( vp-> getActualHeight( ) ) ) ;    
                                            }

Lights and Shadows

Shadow Types that Ogre Supports(Ogre支持的阴影类型)

Ogre现在支持三种类型的阴影类型:

1.Modulative Texture Shadows (Ogre::SHADOWTYPE_TEXTURE_MODULATIVE) (Ogre::SHADOWTYPE_TEXTURE_MODULATIVE) - The least computationally expensive of the three. This creates a black and white render-to-texture of shadow casters, which is then applied to the scene.

2.Modulative Stencil Shadows (Ogre::SHADOWTYPE_STENCIL_MODULATIVE) - This technique renders all shadow volumes as a modulation after all non-transparent objects have been rendered to the scene. This is not as intensive as Additive Stencil Shadows, but it is also not as accurate.

3.Additive Stencil Shadows (Ogre::SHADOWTYPE_STENCIL_ADDITIVE) - This technique renders each light as a separate additive pass on the scene. This is very hard on the graphics card because each additional light requires an additional pass at rendering the scene.

Ogreshadows.jpg          

    Ogre不支持柔和阴影(soft shadows)。                

 

Using Shadows in Ogre

    我们可以使用SceneManager类的setShadowTechnique成员函数来设置我们所想要的阴影类型。每当你创建Entity是就调用setCastShadows函数来设置阴影,无论他是否投(cast)射阴影。

    现在把环境光(ambient light)设为全黑,并设置阴影类型:

        mSceneMgr->setAmbientLight(Ogre::ColourValue (0 , 0 , 0 ) ) ;
        mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE ) ;

    现在我们创建一个对象到场景中并给他加上阴影:

        Ogre :: Entity* entNinja = mSceneMgr-> createEntity( "Ninja" , "ninja.mesh") ;
        entNinja ->setCastShadows (true ) ;
        mSceneMgr -> getRootSceneNode ( ) ->createChildSceneNode ( ) ->attachObject (entNinja ) ;

   我们还需要Ninja站立的地方(这样才能把阴影投射上去),为此我们创建一个简单的平面(plane)。首先是通过指定一个法向量(normal)和到原点(origin)的距离来定义Plane对象,我们可以使用平面来组建世界几何体的部分,这样处理指定距离原点的距离0外还有指定一下其他的东西。现在我们只想要一个Y轴正方向作为法向量(即这个平面朝上)并且距离原点为0的平面:

       Ogre :: Plane plane (Ogre :: Vector3 :: UNIT_Y , 0) ;

   现在需要注册创建的平面,这样就可以在程序中使用了。MeshManager类管理着我们程序所中加载的所有mesh(网格)(比如他就管理着我们所加载的ninja.mesh网格)。createPlane函数注册我们所要使用的平面:

  Ogre :: MeshManager :: getSingleton( ) . createPlane( "ground" , Ogre :: ResourceGroupManager:: DEFAULT_RESOURCE_GROUP_NAME,
   plane , 1500 ,1500 , 20 , 20 , true, 1, 5, 5, Ogre :: Vector3 :: UNIT_Z );

   我们所注册的平面是大小为1500乘1500、新的网格名叫“ground”。现在可以从这个网格创建一个Entity(实体)并把他放到场景中:

       Ogre :: Entity * entGround= mSceneMgr-> createEntity( "GroundEntity", "ground") ;
        mSceneMgr -> getRootSceneNode ( ) ->createChildSceneNode ( ) ->attachObject (entGround ) ;

   在完成之前还有两件事要做。第一,要告诉SceneManager我们不想他投射阴影,因为“ it is what's being used for shadows to project on”。第二,我们需要给他加一个纹理(texture)。ninja网格一家有了为他而定义的材质脚本,创建ground(地面)网格时,我们不知道使用什么纹理。我们将使用Ogre包含在他的例子里的"Examples/Rockwall" 材质脚本:

       entGround -> setMaterialName ( "Examples/Rockwall" ) ;
        entGround -> setCastShadows ( false ) ;

Types of Lights

  Ogre提供了三种光源(light)类型:

 

  1. Point (Ogre::Light::LT_POINT) - Point lights emit light in every direction equally.
  2. Spotlight (Ogre::Light::LT_SPOTLIGHT) - A spotlight works exactly like a flashlight does. You have a position where the light starts, and then light heads out in a direction. You can also tell the light how large of an angle to use for the inner circle of light and the outer circle of light (you know how flashlights are brighter in the center, then lighter after a certain point?).
  3. Directional (Ogre::Light::LT_DIRECTIONAL) - A directional light simulates far-away light that hits everything in the scene from a direction. Let's say you have a night time scene and you want to simulate moonlight. You could do this by setting the ambient light for the scene, but that's not exactly realistic since the moon does not light everything equally (neither does the sun). One way to do this would be to set a directional light and point in the direction the moon would be shining.

    Light有很多描述light的属性,其中最重要的两个属性就是diffuse和specular(反射)颜色。每个材质脚本都定义了light可以反射多少diffuse和specular(反射)颜色。

Creating the Lights     

    我们调用SceneManager的creatLight函数来创建Light并设置light的名字, 就像我们创建Entity或Camera一样。 创建好light后就可以设置他的位置或把它绑定到SceneNode上。与camera对象不同,light只有setPosition和setDirection两个成员函数,所以当你要创建固定光源时可以调用serPosition函数,如果需要光源移动(比如创建一个跟随角色的light),这要就需要把它绑定到一个SceneNode上。

    创建light并设置类型和位置:Ogre::Light* pointLight= mSceneMgr->createLight("pointLight");
                                                 pointLight->setType(Ogre::Light::LT_POINT);
                                                 pointLight->setPosition(Ogre::Vector3(0,150, 250);           

    设置diffuse和specular颜色:pointLight->setDiffuseColour(1.0,0.0, 0.0);
                                                 pointLight->setSpecularColour(1.0,0.0, 0.0);

    directional light(方向光)的创建:    Ogre::Light* directionalLight= mSceneMgr->createLight("directionalLight");
                                                                directionalLight->setType(Ogre::Light::LT_DIRECTIONAL);
                                                                directionalLight->setDiffuseColour(Ogre::ColourValue(.25,.25, 0));
                                                                directionalLight->setSpecularColour(Ogre::ColourValue(.25,.25, 0))

由于directional light被假定为距离很远,所以不用设置其位置,只用设置其方向即可,我们设置光源的方向为Z轴正方向和Y轴负方向,相当于来自正上方45度:directionalLight->setDirection(Ogre::Vector3(0, -1, 1 ));

   点光源的创建:Ogre::Light* spotLight= mSceneMgr->createLight("spotLight");
                             spotLight->setType(Ogre::Light::LT_SPOTLIGHT);
                             spotLight->setDiffuseColour(0,0, 1.0);
                             spotLight->setSpecularColour(0,0, 1.0);

点光源也需要设置位置和方向:spotLight->setDirection(-1,-1,0);
                                                 spotLight->setPosition(Ogre::Vector3(300,300, 0))

点光源还可以指定其光束的宽度,其中有一道核心光束比周围的光线都要亮。我们可以调用setSpotlightRange函数来设置点光源的宽度:spotLight->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(50))。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值