1. 程式人生 > >Ogre中的材質(Material)

Ogre中的材質(Material)

     在Ogre中,Overlay、Entity、Particle等都會用到材質。 Ogre中的材質指令碼只不過是指定程式該如何去使用紋理(Texture),具體關於材質指令碼的編寫及引數可參考ogre中文手冊。下面來說說一般的材質應用:

    材質做為一種資源,它也有它自己的資源管理器(MaterialManager)。 一般管理器都是使用了單件模式,在程式中都只有一個對像。 要獲取一個材質在程式中就可以這樣MaterialPtr mat= MaterialManager::getSingleton().getByName(strName),其中strName就是材質指令碼中定義材質的名字了。這樣我們就可以通過mat(可以是在當指標的方式用)在程式動態修改我們的材質了。

    在材質指令碼中,第一行應該是定義材質名,如:material Example/CloudSky。那麼“Example/CloudSky”就是這個材質的名字了(在Ogre中名種指令碼資源名並不是用檔名來定義的,因為一個檔案中可以存在多個資源指令碼,包括Overlay、Particle也是這樣)。下面來個最簡單的材質指令碼:

material Template/texture_map
{
   technique
   {
      pass
       {
         texture_unit
         {
           texture image.png
         }
      }  
   }
}

在該材質指令碼中,定義了一個技術(在指令碼中可以有多個技術存在,以支援不同的配置的電腦,一般對硬體要求高的技術會放在前面),定義了一個通道和一個紋理單元。

在材質中實現透明貼圖。 很多時候,我們希望在我們使用的材質能夠透明地貼在已有的紋理上(透明的地方不顯示),這樣我們可以在Pass裡面的scene_blend設定為alpha_blend來實現。同樣,如果我們要在程式中實現可以這樣:mat->getTechnique(0)->getpass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA)。當然,我們可以以一定的透明度來顯示,可以在TextureUnit中通過設定alpha_op_ex

來實現。如我們要實現0.5的透明度:在指令碼中:alpha_op_ex modulate src_texture src_manual 0.5  ;在程式中,我們可以這樣設定mat->getTechnique(0)->getpass(0)->getTextureUnitState(0)->setAlphaOperation(LBX_MODULATE,LBS_TEXTURE,LBS_MANUAL,1.0,0.5);

   深度緩衝。在材質中我們還可以在Pass中把深度緩衝(depth_check)關掉(在指令碼中加入:depth_check off),這樣應用該材質的實體或其它就不會被其它前面的東西所遮住了。有時我們需要這樣做,比如在Overlay中加入一個3D實體,不能讓移動時Overlay加入的3D實體讓場景中的實體給遮住了。

  材質繼承。 材質指令碼是可以繼承的(其實叫複製更準確),但確實讓我們少寫了很多重複的設定。當我們的幾個材質的大部分設定相同的時候(比如二個材質僅僅是使用的紋理不同),那使用材質繼承最好不過了。比如:

material OldMaterial
{
   technique
   {
      pass
       {
          lighting off
          scene_blend alpha_blend
         texture_unit
         {

           texture_alias StateTexture       // 在這裡需要給紋理單元設定一個別名
           tex_address_mode  clamp       // 設定紋理定址模式,具體請看Ogre手冊
           texture OldFile.png
         }
      }  
   }
}

現在我們的新材質 NewMaterial  要繼承 OldMaterial 。僅僅只設定不同的紋理,而其它屬性和OldMaterial 相同,我們可以這樣寫:

material NewMaterial  : OldMaterial  // 像不像C語言裡面的繼承,只是沒有了修飾型別而已。 

{

      set_texture_alias StateTexture newFile.png   // 設定新的紋理,這裡紋理別名就重要了

}                         是不是我們要寫的指令碼更方便,更準確了呢?

當然我們還可以在材質繼承中設定或修改屬性。比如在 NewMaterial  繼承 OldMaterial  時把光照開啟:

material NewMaterial  : OldMaterial 

{
   technique
   {
      pass
       {
         lighting on
         texture_unit
         {
           texture newFile.png     // 這樣就用不著紋理別名了
         }
      }  
   }
}

   紋理操作。在材質指令碼中,紋理單元可以用scroll_anim設定一個紋理滾動動畫,後面二個屬性是水平和垂直方向的滾動量,當然在程式中也可以用TextureUnitState::setScrollAnimation();來設定;scroll可以指定紋理的滾動量,在程式中用TextureUnitState::setTextureScroll();。用rotate_anim來指定紋理的旋轉動畫,在程式中可以用TextureUnitState::setRotateAnimation();來設定;rotate可以指定紋理的旋轉量,在程式中用TextureUnitState::setTextureRotate();來設定。  scale 可以用來設定當前大小,程式中使用TextureUnitState::setTextureScale();來設定應用比例。當然,如果你會操作矩陣,你也可以用transform 來設定以上各種效果。 在指令碼中還可以用wave_xform 來實現各種波動效果,這常常用於實現水波等效果。