场景元素:平面、光源、阴影、摄像机、视口。
Plane(平面): 要想理解Plane首先从Plane是如何构造开始学习。
在几何学中,Plane是一个无限延伸没有界限的面,但是在Ogre中Plane是有大小、尺寸的。
Plane作为Ogre中的一个模型,它虽然是2D的,但渲染时我们需要以3D的方式进行渲染,因为在Ogre中场景是3D形式的。就好像我们现实生活中的窗帘,虽然它只是一个面,但是当我们从不同的角度观察时,它却具有的3D的视觉效果。
Normal(法线),在3D图像学中它指法向量(或平面法向量)。它是垂直于平面的向量,长度通常是1。
在3D渲染中,模型的常见描述方式是三角形。可以拼接n个三角形来组合成想要的图形。而这些三角形一般指”切片”,它们是由组合(xsegments,ysegments)确定的。举例说明切片如何划分的:(通过设置摄像机进行线框显示可直观查看效果,在本节介绍摄像机章节有代码)
创建平面:
Ogre::Plane plane (朝向,位置);
createPlane(
const String& name, const String& groupName,const Plane& plane,
Realwidth, Real height,
intxsegments = 1, int ysegments = 1,
bool normals = true, unsigned short numTexCoordSets = 1,
RealuTile = 1.0f, Real vTile = 1.0f, const Vector3& upVector=Vector3::UNIT_Y,
HardwareBuffer::Usage vertexBufferUsage =HardwareBuffer::HBU_STATIC_WRITE_ONLY,
HardwareBuffer::Usage indexBufferUsage =HardwareBuffer::HBU_STATIC_WRITE_ONLY,
bool vertexShadowBuffer = true, bool indexShadowBuffer =true);
参数说明:width,height: 平面的尺寸
Xsegments,ysegments:切片划分
normals:是否法向量是否被计算
shortnumTexCoordsets: 需要多少个纹理坐标系,当我们使用超过1个表面纹理时,变得有用。
uTile,vTile:纹理平铺平面的频率,一般是0~1,(0,0)表示纹理的左上角,(1,1)表示纹理的右上角。
//留空间,以后添加此处详细说明。
upVector:纹理朝向。
其他几项暂不做详细说明。
Light(光源):
三种:点光源(LT_POINT)、聚光灯(LT_SPOTLIGHT)、方向光源(LT_DIRECTIONAL)。
通用方法:
Ogre::Light *light = mSceneMgr->createLight(“name”);
light->setType(Ogre::Light::LT_??);//设置光源类型
light->setDiffuseColour(颜色);
各自特殊:
点光源:无
聚光灯:设置朝向:setDirection(Vector3);
设置内外角度:setSpotlightInnerAngle(Dgree)\setSpotlightOuterAngle(Degree);
下降(falloff)参数:距离越远,光线越暗。
setSpotlightFalloff(float);
方向光源:像太阳一样,将周围物体全部照亮,没有衰减半径,也没用别的特性。
阴影(shadow):
mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
对于阴影的渲染,Ogre3D支持很多种,我们才用的是当渲染场景时,计算所有光源的效果积累,最后得到最终效果。这种技术效果很好,但代价也很高昂,如果对阴影处理感兴趣,可以上网查找相关详细资源介绍,这里就不探讨阴影的详细工作原理了。
摄像机(Camera):
它是在一个确切的位置捕捉我们的一部分场景。但是目前我们一直在使用ExampleApplication中默认的摄像机(mCamera)。现在我们创建自己的摄像机:
void createCamera()//你可以通过ExampleApplication中此函数的定义,查看默认摄像机mCamera是如何定义的。
{
mCamera = mSceneMgr->createCamera("name");
mCamera->setPosition(…);
mCamera->lookAt(…);//设置摄像机的朝向
mCamera->setNearClipDistance(5);//设置视锥
mCamera->setPolygonMode(Ogre::PM_WIREFRAME);//设置为线框显示
}
在3D场景中,并非所有的场景都会被渲染,场景管理器(SceneManager)只是渲染在视锥内部的场景。下图中Near 与 Far之间的区域为视锥。
视口(ViewPort): 是一个被用来渲染的2D表面,它就像一个有背景的桌面一样,需要我们在其上进行渲染操作。
创建视口:我们写的创建视口的代码,必须要添加到createViewport()中去。
Void createViewport()
{
Ogre::Viewport* vp =mWindow->addViewport(mCamera);
//…
}
设置背景颜色:setBackgroundColor(颜色);
设置纵宽比:setAspectRatio();//纵横比:窗口宽度/窗口高度
代码:
#include "ExampleApplication.h"
using namespace Ogre;
class example1 : public ExampleApplication
{
protected:
void createScene()
{
//Plane
Plane plane(Vector3::UNIT_Y, 0);
Ogre::MeshManager::getSingleton().createPlane("plane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500,1500,20,20,true,1,5,5,Vector3::UNIT_Z);
Entity *entplane = mSceneMgr->createEntity("LightPlaneEntity","plane");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entplane);
entplane->setMaterialName("Examples/BeachStones");
//Light
SceneNode *node = mSceneMgr->createSceneNode("Node1");
mSceneMgr->getRootSceneNode()->addChild(node);
Light *light1 = mSceneMgr->createLight("Light1");
light1->setType(Ogre::Light::LT_DIRECTIONAL);
light1->setPosition(0,0,-20);
light1->setDirection(Ogre::Vector3(0,-1,1));
light1->setDiffuseColour(Ogre::ColourValue::White);
node->attachObject(light1);
//add a entity
Entity *ent = mSceneMgr->createEntity("MyEntity1","Sinbad.mesh");
SceneNode *nodeent =node->createChildSceneNode("Node2");
nodeent->setPosition(0,5,0);
nodeent->attachObject(ent);
//Shadow
mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
}
//创建摄像机
void createCamera()
{
mCamera = mSceneMgr->createCamera("MyCamera1");
mCamera->setPosition(0,100,200);
mCamera->lookAt(0,0,0);//设置摄像机的朝向
mCamera->setNearClipDistance(5);//设置视锥
mCamera->setPolygonMode(Ogre::PM_WIREFRAME);//设置为线框显示
}
//创建视口
void createViewports()
{
Viewport* vp = mWindow->addViewport(mCamera);
//set the background color
vp->setBackgroundColour(ColourValue(0.0f,0.0f,1.0f));
//set the aspect ratio
mCamera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
}
public:
example1(){}
~example1(){}
};
int main()
{
example1 ex1;
ex1.go();
return 0;
}