(4) 摄像机、光照和阴影

来源:互联网 发布:http文件上传java 编辑:程序博客网 时间:2024/05/16 14:15

简介
这篇教程主要介绍如何使用灯光对象以及如何产生阴影。我们还会稍微了解一下摄像机的用法。

 

从这里开始
在上一教程的基础上,将文件TutorialApplication.cpp和TutorialApplication.h替换为如下两个文件:
  BasicTutorial2.h
  BasicTutorial2.cpp

 

摄像机
摄像机是用来观察我们所创建的场景。摄像机是一个特殊的物体,他的工作方式有点类似于场景节点。
摄像机对象有方法:setPosition, yaw,rollpitch,并且他可以绑定到任何场景节点。就像场景节点一样,摄像机的位置跟父节点有关(就好像尊重长辈一样)。对所有的移动和旋转来说,你可以把摄像机考虑成场景节点。
对于Ogre摄像机来说,有一点跟你想象不一样的是同一个时间内你只能使用一台摄像机(当前)。我们不能这么干:
    创建一个摄像机观察场景中的一部分,而在创建第二个摄像机观察场景中的另一部分,就好比你的眼睛同时只能看你前方的东西一样。

 

如何创建一个摄像机
我们重载了基类BassApplication的createCamera方法,自己来实现摄像机的创建,代码如下:

当你创建完一个摄像机,可以通过其名字取得摄像机对象的指针:getCamera("PlayerCam")

然后我们设置摄像机的位置和朝向,我们将设置摄像机朝向坐标原点,所以我们需要设置一个恰当的Z轴距离。添加下面的代码到createCamera:

lookAt方法非常灵活,你能够设置它面向任何你想要的角度。场景节点也有同样的方法,能够通过此方法在任何情况下,很容易的达到你想要的方向。

最后,设置一个5单位距离的近距离裁剪。通过设置摄像机的裁剪距离,来规定该距离内的事物是你看不到的。设置近距离裁剪后,你能够在离实体很近的时候,很容易的透过实体看到场景。还有一种很微小的情况就是,当你和某个物体很近时,这个物体将填满你的整个视野。同样,你也可以设置远距离裁剪。这个值的设置能够让引擎不去渲染远于它的物体。这主要在你需要远距离渲染大场景的时候,用来增加帧速。添加如下代码,以实现近距离裁剪:

现在,我们将摄像机创建出来了,需要将它作为默认的相机:

OK,createCamera方法最后的代码应该如下:

 

视口
了解"当渲染一个场景时Ogre是如何决定使用哪个摄像机的"是非常重要的。在同一个时间内Ogre中可能有多个场景管理器在运行。也有可能把场景分为多个区域,然后用分开的摄像机去渲染场景中不同的区域(例如:思考一下控制台游戏中两个人的观察)。
然而我们可能去做这些事情的时候不用考虑他们是如何被做到的,这是后面高级教程的内容。
为了了解Ogre是怎样渲染场景的,考虑一下Ogre中建立的这些东西:摄像机,场景管理器,和渲染窗口。
    渲染窗口我们还没有涉及到,但是她是所有物体呈现的最基本的窗口。
    场景管理器创建摄像机去观察场景。
    你必须告诉渲染窗口哪些摄像机去呈现场景,哪部分窗口被渲染进来。
    你告诉渲染窗口的摄像机所呈现的区域就是视口,并且这里只有一个视口实体。

 

建立视口
我们重载了基类BaseApplication创建视口的函数:createViewports。代码如下:

呃,创建了这个视口可以干什么用呢?可以干的事情不多,最重要的事情我们可以做的是调用setBackgroundColour方法给背景设置任意我们选择的颜色。因为在这章中我们要处理光照因此我们把背景设置为黑色。

最后也是最重要的事情是我们需要设置摄像机的纵宽比。如果你用的是一些非标准全窗口视口,而未能设置这个的话结果会出现一个非常奇怪的场景图。


我们添加完代码后函数应该长成这样:

这就是所有的我们对视口的简单运用。
这时你应该首先去编译一下然后运行这个应用程序,什么也呈现不了只是黑的场景(用Esc来退出)。确保你可以运行这个程序不会崩溃再继续。

 

光照和阴影

OGRE支持的阴影类型:
1、调制纹理阴影 (SHADOWTYPE_TEXTURE_MODULATIVE) - 是这3种中最节省资源的。她创建一个阴影投射者的黑与白渲染到纹理,然后用于场景中。
2、调制模板阴影 (SHADOWTYPE_STENCIL_MODULATIVE) - 这项技术是在所有的非透明体被渲染到场景以后再渲染所有的阴影体来调制阴影,她耗费资源没有加成模板阴影强,但是也不是非常精确。
3、加成模板阴影 (SHADOWTYPE_STENCIL_ADDITIVE) - 这项技术是渲染每一个光源作为分离的部分附加到场景中。 对显卡来说这是比较麻烦的,因为在场景中每一个附加的光源需要一个附加渲染通路。

 

在Ogre中使用阴影
只要你创建了一个实体,调用setCastShadows方法来设置这个实体是否投射阴影。我们现在将设置环境光全变暗,然后设置阴影类型。找到BasicTutorial2::createScene成员函数添加如下代码:

我们还需要一些东西来安放忍者(就是需要一些东西来接收他投射的阴影),为此我们需要创建一个简单的平面(Plane)。
首先我们需要定义一个平面对象,其初始化参数为平面的法线和到原点的距离:

然后将此平面对象注册到我们的应用程序中,这样才能使用。类MeshManager将跟踪这些Plane对象:

我现在不想探究怎样用MeshManager的细节,我们可以通过模型创建一个实体把她放置到场景中:

对于这个地面,我们还有两件事情要做:贴上漂亮的纹理、不投射阴影:

到目前为止,代码应该是这样的:

运行代码看看效果,我们看到了一片黑色的东西,为什么呢?没有光线,而且环境光是黑色的。我们需要光源来照亮场景,让我们继续吧。

 

光源种类
OGRE提供了3种光源:
   1. 点光源 (Ogre::Light::LT_POINT) - 从一个点发出光放射到四周
   2. 聚光源 (Ogre::Light::LT_SPOTLIGHT) - 聚光灯工作有点像手电筒
   3. 有向光 (Ogre::Light::LT_DIRECTIONAL) - 有向光模拟非常遥远地方的灯光,在场景中从某个方向照射物体。
光源有一个范围属性描述光看上去的样子。两个更重要的属性是光的漫反射颜色和镜面反射颜色(diffuse and specular color)。每一个材质脚本定义有多少漫反射和镜面反射光线由材质反射来,稍后我们将学习如果控制他。

 

建立光源
光源仅仅有两个方法setPositionsetDirection(而且并不是像旋转,偏移,滚动一样有全套的移动函数)。如果你需要移动光源(例如创建一个光源跟随角色),你需要把光源绑定到场景节点上。
首先我们要创建光源设置他的类型和位置:

然后设置她的漫射色和镜面色:红色

编译运行看看效果,可以看到忍者和他猥琐的影子了吧?确认侧面、正面都可以看到。然后自己试着多打几个灯光,设置不同的投影类型,看看忍者的影子和忍者的颜色吧。

原创粉丝点击