天天看點

Ogre學習心得

1.ogre的資源檔案用文本格式打開:

.material    可編輯

.mesh      不可編輯(需通過OgreXmlConverter.exe轉換才可看)

.skeleton  不可編輯(需通過OgreXmlConverter.exe轉換才可看)

.particle    可編輯

.overlay    可編輯

2.ogre表層腳本.overlay使用

Examples/MyLogo

{

zorder 100

container Panel(Examples/LogoPanel) // 名字不能重複

{

  metrics_mode pixels

  horz_align right    // 定義x軸的零點為螢幕最右邊

  vert_align top      // 定義y軸的零點為螢幕最上邊

  top 250

  left -500

  width 160

  height 85

  material Core/OgreText

}

}

3.ogre粒子腳本.particle使用

// Example emitted emitters

particle_system Examples/Fireworks1      // 注意前面的命名與overlay不同

{

    material Examples/Flare

    point_rendering            false

    particle_width             10

    particle_height            10

    cull_each                  false

    quota                      1000

    emit_emitter_quota         10

    billboard_type             point

    emitter Box         // 這是盒子發射器,若是point,則為點發射器

    {

        angle           30

        emission_rate   30

        time_to_live    1

        direction       0 1 0

        velocity     0

        colour_range_start  1 1 0

        colour_range_end    0.3 1 0.3

        width           60

        height          60

        depth           60

    }

    // Make em float downwards

    affector LinearForce

    {

        force_vector            0 -100 0

        force_application       add

    }

    // Give em some nice colours

    affector ColourInterpolator        // 顔色按一個粒子的生存期變化

    {

        time0                   0

        colour0                 1 1 0

        time1                   0.5

        colour1                 1 0 0

        time2                   0.9

        colour2                 0 0 1

    }

}

4.ogre的紋理支援

  ogre的紋理最好是用png格式,它是ogre直接支援的格式,如果要用其他格式,如tga,

那必須在用ofusion導出檔案之前,确認紋理已經更新過,否則會出現沒貼圖的情況。

實際中用dds格式圖檔,因為其同比其它類型圖檔最小。

5.ogre中的實體和mesh

  隻能通過實體設定材質,才能顯示實時修改材質的結果。

6.cegui改變滑鼠圖示

  CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "TabButtonScrollLeftNormal");

                                               所用的圖檔名字       圖檔中單個圖示的名字

7.cegui滑鼠坐标

  CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();

8.直接判斷滑鼠是否按下

  OIS::Mouse *inputM

  if (inputM->getMouseState().buttonDown(OIS::MB_Right)){

    mMainNode->yaw (Radian (2 * elapsedTime * inputM->getMouseState().X.rel));

  }

                                              取滑鼠在螢幕的x軸平移量

9.判斷滑鼠滾輪是前滾還是後滾

bool mouseMoved(const OIS::MouseEvent &arg)

{

if (arg.state.Z.rel){

if (arg.state.Z.rel > 0) ...;//前滾

if (arg.state.Z.rel < 0) ...;//後滾

}

}

10.滑鼠點選地面獲得坐标時,應注意滑鼠監聽的使用,如:

bool mouseMoved(const OIS::MouseEvent &arg)

{

CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();

Ray mouseRay = mCamera->getCameraToViewportRay(

mousePos.d_x/float(arg.state.width),

mousePos.d_y/float(arg.state.height));

}

這裡用的是cegui的滑鼠,但arg是ois的滑鼠事件,二者不比對,可能會造成滑鼠點選

螢幕取得的地面位置不正确。原因就是ois的螢幕寬高取的不能與cegui的滑鼠比對。

11.滑鼠移動速度控制

bool mouseMoved(const OIS::MouseEvent &arg)

{

CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);

CEGUI::System::getSingleton().setMouseMoveScaling(2.0);

}

必須先有injectMouseMove,才能使setMouseMoveScaling起作用。

setMouseMoveScaling可以放在cegui定義的時候。

12.cegui改字型

由于先要建立CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"MyLookSkin.scheme");

故先修改.scheme中的字型<Font Name="SimSun-8" Filename="SimSun-8.font" />

對應需建立SimSun-8.font(内容如下)

<?xml version="1.0" ?>

<Font Name="SimSun-8" Filename="SimSun.ttc" Type="FreeType" Size="8"

NativeHorzRes="800" NativeVertRes="600" AutoScaled="true"/>

然後設定預設字型為"SimSun-8":

mGUISystem->setDefaultFont((CEGUI::utf8*)"SimSun-8");

13.ogre的綁定盒

一個對象若沒有綁定盒,其是不會顯示的。

若一個對象的綁定盒太小,則會由于綁定盒離開了錄影機的視口,而整個對象消失。

綁定盒的大小并不是不變的,當一個對象有動作時,其會自動根據對象的頂點的坐标變大或變小

14.ogre的材質腳本中關于從程式獲得的紋理處理原理:

我們通常會在材質腳本中看到如下的定義,

texture_unit

{

texture Refraction

}

這說明我們必須在程式中給予它一個紋理,此紋理名為“Refraction”,如下:

TexturePtr texture1 = TextureManager::getSingleton().createManual( "Reflection",

   ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,

   512, 512, 0, PF_R8G8B8, TU_RENDERTARGET );

材質腳本會自動在記憶體的紋理名字中查找名為“Refraction”的紋理,并将其應用到對應材質中。

當然紋理的建立必須先于材質的應用。同時,也可以通過獲得紋理單元,直接給其賦予紋理。

// 材質中

texture_unit

{

}

// 程式中

MaterialPtr pMaterial = MaterialManager::getSingleton().getByName("test");

TextureUnitState* t = pMaterial.get()->getTechnique(0)->getPass(0)->getTextureUnitState(0);

t->setTextureName( "Tex",  TEX_TYPE_2D);

15.設定視口的背景顔色

mWindow->getViewport(0)->setBackgroundColour(ColourValue::White);

16.把記憶體中紋理内容儲存為圖檔

// 建立小地圖紋理

TexturePtr texSmallMap = TextureManager::getSingleton().createManual("SmallMapTex",

  ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,

  512, 512, 1, 0, PF_R8G8B8, TU_RENDERTARGET);

// 建立小地圖錄影機

Camera* pCamSmallMap = mSceneMgr->createCamera("SmallMapCam");

pCamSmallMap->setPosition(mCamera->getPosition().x,3800,mCamera->getPosition().z);

pCamSmallMap->pitch(Degree(-90));

pCamSmallMap->setAspectRatio(1);

// 用于擷取渲染目标

m_pRttTexMap = texSmallMap->getBuffer()->getRenderTarget();

Viewport *pVP = m_pRttTexMap->addViewport( pCamSmallMap );

pVP->setOverlaysEnabled(false);

pVP->setClearEveryFrame(true);

pVP->setBackgroundColour( ColourValue::White );

m_pRttTexMap->setAutoUpdated(false);

// 更新

m_pRttTexMap->update();

// 儲存為圖檔

m_pRttTexMap->writeContentsToFile("p1.jpg");

注意:通過錄影機拍照得到的圖檔,在地形是正方形平面時,才可以得到完整的小地圖。若地形有

高低起伏,則在地形邊緣凹下去的地方,拍照獲得圖檔部分是缺失的,這是由于凹下去的部分離

錄影機比較遠一些,以至于這些像素被忽略了。

17.材質中設定紋理的雙面都可見

直接添加以下到pass中:

cull_hardware none

cull_software none

18.粒子挂接骨骼會受骨骼的縮放影響的情況

當在粒子腳本中添加local_space true之後,粒子隻相對于挂接骨骼的對象空間移動,并受到骨骼

的縮放影響。一般,骨骼都是在3d max中給一個模型設定的,我們常常隻關注骨骼在模型上的位置,

而忽略了其縮放,但是在導出骨骼檔案時,縮放也會跟着一起導出來。以至于,粒子在挂接到對象

時會縮小,甚至小到看不到。解決辦法就是檢視骨骼檔案,看其是否有縮放值。

19.材質中需要在建立紋理單元時才可以設定的函數

// 若存在同名的紋理單元,則移除

if (mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(mTextureName)!=NULL){

mMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();

}

// 建立新的紋理單元

TextureUnitState* texUnit =

  mMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(mTextureName);

// 設定字型的顔色,因為生成的圖檔是黑白相間的,是以要通過設定的顔色與圖檔混

// 合才能達到設定字型顔色的目的.

texUnit->setColourOperationEx(LBX_MODULATE,LBS_TEXTURE,LBS_MANUAL,mColor,mColor);

如上,setColourOperationEx函數就是必須在建立紋理單元後才可以使用的函數,若是你想單獨擷取

一個紋理單元,再設定setColourOperationEx函數,就會出錯,不知為什麼。

20.屏蔽實體的滑鼠選擇

一般我們使用滑鼠選擇,會先判斷滑鼠是否選擇了地形,然後在判斷是否選中模型實體。如下:

// 執行查詢

RaySceneQueryResult &result = mRaySceneQuery->execute();

RaySceneQueryResult::iterator itr;

// 周遊

for (itr = result.begin(); itr != result.end(); itr++, ++j)

{

if (itr->movable && itr->movable->getName().substr(0, 23)

   != "ETTerrain/Terrain/Tile["){

......

}

}

同樣的道理,我們可對實體的名字做一些修改,使其名字包含和地形一樣的判斷特征,就可以屏蔽了。

例如:

m_pEnt = mSceneMgr->createEntity( "ETTerrain/Terrain/Tile[robot", "robot.mesh");

21.ogre材質屬性iteration

此屬性可以設定目前pass使用的光源類型和渲染次數,如下

pass DynLighting

{

lighting on

iteration once_per_light point

scene_blend add

vertex_program_ref ET/Programs/VSDynLighting

{

}

fragment_program_ref ET/Programs/PSDynLighting

{

}

}

其中的shader是專門用于點光源的,若是程式中有其他類型的光源,則會顯示出錯誤的效果,為了避免

此類錯誤,在其前面做了一個限定iteration once_per_light point,這表明對每一個點光源隻渲染

一次。

22.陰影

目前ogre支援3種陰影,還不支援軟體陰影。要實作陰影,首先至少要有一個可投影的光源,以及一個

可以接受陰影的實體(在材質中有一項是專門處理陰影接受的,預設receive_shadows on)。

例如:

// 點光源

m_pLit = mSceneMgr->createLight("Light1");

m_pLit->setType(Light::LT_POINT);

m_pLit->setDiffuseColour(1.0, 0.0, 0.0);

m_pLit->setSpecularColour(0.0, 0.0, 0.0);

m_pLit->setVisible(true);

m_pLit->setPosition(280,160,280);

m_pLit->setAttenuation(10000,1,0.6,0.0);

m_pLit->setCastShadows(false); // 不投影

// 直射光源(預設是投影的)

m_pLit2 = mSceneMgr->createLight("Light3");

m_pLit2->setType(Light::LT_DIRECTIONAL);

m_pLit2->setDiffuseColour(1.0, 1.0, 1.0);

m_pLit2->setSpecularColour(1.0, 1.0, 1.0);

m_pLit2->setDirection(Vector3( 1, -1, 1 ));

mSceneMgr->setAmbientLight(ColourValue(0.7, 0.7, 0.7));

mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);

mSceneMgr->setShadowColour(ColourValue(0.5,0.5,0.5,0.1));

m_pRobot = mSceneMgr->createEntity("robot","robot.mesh");

m_pRobot->setCastShadows(false); // 初始是否接受投影由實體的材質決定,這裡強行改為了不投影

SceneNode* robotNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("robotNode",

        Vector3(250,150,170));

robotNode->attachObject(m_pRobot);

robotNode->setScale(0.4, 0.4, 0.4);

23.查找資源是否存在

String meshName = "robot.mesh";

// 此判斷是查詢在media下的資源名字meshName是否存在

if(!ResourceGroupManager::getSingleton().resourceExists("General",meshName)){

assert(FALSE && "meshName is not found.");

}

// 此判斷是查詢在程式中是否已經建立了名字為meshName的模型

if(!MeshManager::getSingleton().resourceExists(meshName)){

assert(FALSE && "meshName is not found.");

}

24.彈出式消息框

MessageBox(NULL,"此模型不存在","error",MB_TASKMODAL);

25.ogre的日志管理器

可在某個函數或步驟要運作前添加:

LogManager::getSingleton().logMessage ("Caelum: Initialising Caelum system...");

在Ogre.log中檢視其資訊。

26.基于ExampleApplication.h加快錄影機速度

bool frameStarted(const FrameEvent& evt)

{

......

mCamera->moveRelative(mTranslateVector*5);

......

}

27.調整遠裁剪面和近裁剪面距離時出現的怪現象:

當你移動錄影機時,會發現模型上互相之間挨的比較近的面會重疊出現,産生閃爍現象,以下是出錯時

使用的遠裁剪面和近裁剪面距離設定:

mCamera->setNearClipDistance(0.01);

mCamera->setFarClipDistance(1000);

28.模型對光照的反應問題

假設環境光為黑色,場景中有一盞白點光源。

若是模型比較小,并在光照的範圍内,顯示沒問題。

若是模型比較大,而光照的範圍比較小,可能會出現模型全黑的情況。

我遇到的問題是,當有一塊比較大的地面模型時,無法對其進行局部照明,考慮是ogre對其先進行了包圍盒

檢查,發現地面模型在燈光範圍外,是以直接設定其無光。若是用ogre自帶的Plane,則沒問題。

29.ogre模型的陰影

若是不要求陰影很精确,可以用SHADOWTYPE_TEXTURE_MODULATIVE模式,此模式消耗最低,但最好效果在近看陰影時,也會呈現鋸齒邊緣,可通過投影基礎,過濾方式,紋理大小3個方面去優化,還有此模式下一個紋理隻儲存一個燈光産生的陰影:

  mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);

  mSceneMgr->setShadowTexturePixelFormat(PF_L8);

  mSceneMgr->setShadowTextureCasterMaterial(Ogre::StringUtil::BLANK);

  mSceneMgr->setShadowTextureReceiverMaterial(Ogre::StringUtil::BLANK);

  mSceneMgr->setShadowTextureSelfShadow(false);

  mSceneMgr->setShadowColour( ColourValue(0.3, 0.3, 0.3));

  mSceneMgr->setShadowTextureSettings(2048,1);

  mSceneMgr->setShadowFarDistance(600);

若是想用其它模式,可以用SHADOWTYPE_STENCIL_MODULATIVE模式,此模式下的模型需要EdgeList,若是你是用ofusion導出模型的,那在最後導出界面就有一個選項是EdgeList,選中就可以在此模式下看到陰影,否則,是看不到的。還可以對沒有EdgeList的模型使用OgreMeshUpgrade更新,同樣會産生EdgeList。但産生EdgeList的模型檔案明顯比以前大将近3倍,而且此模式下産生的陰影邊緣沒有過渡。

最後一種SHADOWTYPE_STENCIL_ADDITIVE同樣需要EdgeList,其支援多光源産生的多個陰影,但耗資源。

30.暫停粒子

ParticleSystem::setSpeedFactor(0.f)