2007年2月14日 星期三

Python-Ogre Tutorial 2

請先閱讀「寫在OGRE Tutorial前面」,本文假設您的目錄配置都和我一樣。
本文參考PyOgre Beginner Tutorial 2

先建立C:\Python25\Python-Ogre-0.8\demos\tutorial\tut2.py,貼上這些程式碼:

# coding=big5

import Ogre as ogre
import SampleFramework

class TutorialApplication(SampleFramework.Application):

def _createScene(self):
pass

def _createCamera(self):
self.camera = self.sceneManager.createCamera("PlayerCam")
# 建立PlayerCam (玩家攝影機物件)
self.camera.setPosition = (0, 10, 500)
# 設定位置
self.camera.lookAt((0, 0, 0))
# 設定方向
self.camera.nearClipDistance = 5
# 太近的東西看不到 (距離小於5)

def _createViewports(self):
vp = self.renderWindow.addViewport(self.camera)
vp.backgroundColour = (0, 0, 0)
self.camera.aspectRatio = vp.actualWidth / vp.actualHeight

if __name__ == '__main__':
ta = TutorialApplication()
ta.go()

  • 這次我把註解直接打在程式碼裡面了,如果你的程式碼有中文的話,記得加上第一行coding的宣告,否則會沒辦法執行
  • 注意紅字的地方,position property沒辦法用,要用setPosition

經過了這段修改,我們得到一個....全黑的畫面?是的。

由於TutorialApplication是繼承SampleFramework.Application類別,就算我們不設定Camera及Viewport,上層的物件也會自動幫我們建立。現在我們只是Override上層的method,手動建立一次而已。

Camera簡單講就是玩家視角,Viewport這裡不用詳細解釋,有興趣深入了解請詳讀wiki吧。

光線與陰影 (Light&Shadow)

重頭戲來了....廢話不多說,我們來試試吧....修改_createScene函式:

def _createScene(self):
sceneManager = self.sceneManager
sceneManager.ambientLight = (0, 0, 0)
# 不要ambient光源
sceneManager.shadowTechnique = ogre.SHADOWTYPE_STENCIL_ADDITIVE
# 設定陰影種類

ent = sceneManager.createEntity("Ninja", "ninja.mesh")
ent.castShadows = True # this is not actually needed
# 設定這個entity要有陰影效果
sceneManager.rootSceneNode.createChildSceneNode().attachObject(ent)
# 在scene中放置一個忍者

plane = ogre.Plane((0, 1, 0), 0)
# 建立地板平面
mm = ogre.MeshManager.getSingleton()
mm.createPlane('ground', ogre.ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
plane, 1500, 1500, 20, 20, True, 1, 5, 5, (0, 0, 1))
# 建立地板平面的Mesh

ent = sceneManager.createEntity("GroundEntity", "ground")
sceneManager.rootSceneNode.createChildSceneNode().attachObject(ent)
ent.setMaterialName("Examples/Rockwall")
# 將地板明面貼上岩石材質
ent.castShadows = False

light = self.sceneManager.createLight("Light1")
light.type = ogre.Light.LT_POINT
# 建立一個點光源
light.setPosition(0, 150, 250)
# 設定光源位置

light.setDiffuseColour(1.0, 0.0, 0.0)
light.setSpecularColour(1.0, 0.0, 0.0)

注意紅色的部份,是與PyOgre API不相容的地方。先看看結果吧:



漆黑的忍者拖著長長的倒影 (驚)

注意我們把ambient光源設定為0了,在這裡我要稍微解釋一下。
一般3D圖學中的打光效果分為:
  • Ambient (我不太會翻譯...這個字是"周圍的"的意思)
    舉個例子,在一個漆黑的房間中,有一個門縫、窗縫透了一點光進來。這時整個房間都會近乎均勻的被打到一點點的光線。這個其實是經過很多反射、散射所造成的效果,但是真的去計算這些物理現像實在太難了,所以我們就假設所有物體都會被定量的光線照到。(就算不是realtime rendering,在photorealistic rendering也是有用ambient的)
  • Diffuse (散射)
  • Specular (鏡面反射)


現在我們將ambient設為零,而光源在忍者的背面,所以從正面看當然就是一片漆黑了。注意程式的最後兩行將光源設定圍紅色。

除了ambient外,Diffuse和Specular都是假定光線是從某種方向照過來的。OGRE裡光源有三種:
  1. Point:點光源
  2. Spotlight:聚光燈、手電筒,需要設定廣角範圍
  3. Directional:指向性光源,假設光源從無線遠處射來(如太陽)。需要設定範圍但不用設定位置。
先來個有三種光源的範例吧,在剛剛的_createScene後再加上:

light = sceneManager.createLight("Light3")
light.type = ogre.Light.LT_DIRECTIONAL
# 從無限遠處射來的光線
light.setDiffuseColour(.25, .25, 0)
light.setSpecularColour(.25, .25, 0)
# 設定顏色
light.setDirection(0, -1, 1)
# 要指定方向,不用指定位置

light = sceneManager.createLight("Light2")
light.type = ogre.Light.LT_SPOTLIGHT
# 聚光燈形式的光源
light.setDiffuseColour(0, 0, 1.0)
light.setSpecularColour(0, 0, 1.0)
# 顏色
light.setDirection(-1, -1, 0)
light.setPosition(300, 300, 0)
# 位置方向
light.setSpotlightRange(ogre.Degree(35), ogre.Degree(50))
# 廣角




看到三個方向的影子了,雖然這張圖看不出什麼差,但這是三種不同光源(藍字)造成的。照慣例,紅字是與wiki不同的地方。

另外,陰影模式也有三種:
  1. SHADOWTYPE_TEXTURE_MODULATIVE 最差,最少運算資源
  2. SHADOWTYPE_STENCIL_MODULATIVE
  3. SHADOWTYPE_STENCIL_ADDITIVE 最強,最多運算資源
有興趣深入了解的請看wiki

沒有留言: