天天看點

3D 圖形基本知識

3D的概念和術語

轉換3D物體

材質貼圖

照明燈光

活躍

關于3D圖形的書已經寫了很多,從某種意義上來說,這章是另一個部分。然而,大部分3D圖形的著作都是寫如何執行特殊的算法,隻有一小部分是集中于怎樣最好地表現和操縱圖形結構。因為我們用地是Direct3D,很多3D的概念問題已經解決了。但是,你仍然需要了解3D的核心概念以便使用Direct3D。

3D坐标系統

3D圖形的目标是用二維的圖象來代表三維的場景。之是以圖象是二維的因為觀察場景的媒體--平坦的計算機顯示屏是二維的。是以,3D圖形意味着同一場景的兩種表現--一個是看不見的三維的表現,另一個是在螢幕上顯示的二維表現。我們先來讨論看不見的、三維的表現。

在三維的空間裡表現物體可以使用提供三個不同的軸的坐标系統來實作。這些軸通常呗稱為X,Y和Z軸。

有兩種通用的3D坐标系統的變種:左手系和右手系。兩者的不同之處在于Z軸的動作。在左手系裡,越遠的坐标(從觀察者的角度看好像很遠)Z軸的值越大,越近的坐标Z軸的值越小。在右手系裡,Z軸正好相反;越遠的坐标Z軸的值越小,越近的坐标Z軸的值越大。Dirext3D使用左手系,是以我們将在這裡用它來讨論。

3D空間種的任何一點都可以用三個值的集合來表示。這些值指明了點沿每個軸的位置,并且在這裡用三角括号就像這樣:<1,2,3>。這些值說明點的三個方向XYZ軸的位置是獨立的。

原點

三個軸相交的點稱之為原點。位于原點的點XYZ的值都是零<0,0,0>。值離零越遠,點離原點也越遠。在原點右面的點X的值是正的,在原點左面的點X的值是負的。同樣的,在原點上面的點的Y值是正的,在原點下面的點Y值是負的。

向量

向量,同點一樣,也由值來表示,但是向量描繪的是一個方向和一種速率但不是一個位置。

比如<0,1,0>,如果我們把這些數字當成一個點,那麼這些數字代表了原點上方一個機關的位置(機關可以是任意的:可以代表厘米、米等等)。但是如果我們把同樣的三個數字當成一個向量,我們面對的就是一個方向和一種速率,而不是一個位置。在這個例子裡,方向是向上,速率是1。用三個數字表示一個向量是有一點不對的,因為一個向量通常需要6個點:3個用來表示開始點,3個用來表示結束點。這才給了我們一個方向(從第一個點到第二個點的方向),和一種速率(兩個點之間的距離)。隻有開始點是原點能被了解的時候,向量才可以用三個值來表示。

讓我們再來看另一個向量:<2,0,0>。這個向量代表向右的方向因為向量開始于原點并且沿着X軸向右移動了2個機關。因為向量<2,0,0>代表了向量<0,1,0>長度的2倍,是以向量<2,0,0>的速率是向量<0,1,0>的2倍。

記住向量和點是不一樣的是很重要的。一個點訓示了一個位置;一個向量卻沒有。位置是用來定義向量的,但向量卻不能定義一個位置。

平面

平面是一個可以無限延伸的平的表面。平面不是一個正方形或者一個長方形,因為正方形和長方形有邊和角的。平面的大小是不能定義的。表示平面的最簡單的方法就是用一個軸和一個交集。例如,一個Y軸的值為-3的平面位于原點下方3個機關并沿着X軸和Z軸無限延伸。也就是,這個平面和Y軸垂直地相交于-3。

注意到用一個軸和值來表示一個平面的方法不能描述一個不和軸平行的平面。如果我們像描述一個以45度角切過Y軸的平面,我們需要一種更加複雜的表示。

我們可以使用一個向量來描述平面的方向。如果我們想要一個和Y軸45度相交的平面,我們可以使用向量<0,1,-1>來定義這個傾斜向觀察者的平面(該平面垂直于這個向量)。隻是這個向量并沒有定義這個螢幕安,隻有這個平面的方向。我們仍然需要指出這個平面位于什麼地方。我們可以再次使用Y值-3來訓示這個平面在原點以下3個機關處與Y軸相交。

頂點

頂點是在三維空間中用來代替物體比如面、網(我們馬上就要讨論面和網)等的點。頂點,就像點一樣,是有特定位置的,是以他們是可見的。Direct3D支援頂點被畫成點的模式。這種模式沒有太大的實用價值因為基于單獨的頂點很難決定畫的是什麼。事實上,在這種模式裡呈現的場景看起來好像3D“連接配接了點”的難題。(很好--給我一支鉛筆)

在Direct3D裡,面是一個根據頂點來定義的平面圖形元。每個頂點定義了面的角。面上所有的頂點必須在出現在同一個平面内;它們必須定義一個平的面。由不同平面内的點組成的面是不合法的也是畫不出來的。

一個面最簡單的形式是以三個頂點來定義。很容易就能得到的三角面,有如下幾個原因:首先,不可能定義三個點的集合是不在同一個平面内的,是以這個面是不可能不合法的。其次,三角面總是凸的,而凸面用起來比凹面更有效。

(tip:Direct3D使用三角形 其實Direct3D保留将非三角面分割成三角形的模式,因為快速模式接口(并不正确的翻譯)隻接受三角形)

面通在一個圖形系統中通常是唯一可見的物體。一些圖形系統可以畫曲面但是大多數,包括Direct3D,使用小的,平的面的集合來表示曲面。

網是連起來的面的集合。典型地,在一個場景裡,網表示一個物體。網可以有一個或者多個面,可以很複雜。

法線

法線是為面和網計算風格(color不知道具體應該翻譯成什麼)的向量。有兩種形式的法線:面法線和點法線。

面法線是垂直于面的向量。這種法線決定了面的風格和面的哪一邊是可見的。

點向量是在網中指派給每一個點的向量。每個向量的方向決定于鄰接的面的方向和大小。

用面法線還是點法線決定于表現方式。一些表現方式使用面法線,其它的使用點法線,還有一些表現方式根本不用法線。我們将在這章後面一點講到表現方式。

在大部分例子裡,Direct3D自動地計算和使用法線,是以你沒必要知道它們的存在。然而有一些場合,為了達到細節的表現效果,法線是可以被覆寫的。

轉換

現在我們知道了在三維的空間裡怎樣放置物體。我們可以指定頂點,用頂點來定義面,用面來定義網。現在我們需要的是一種移動周圍物體的方式。有三種常用的操作(或者叫轉換)可以用來移動物體:平移、縮放和旋轉。使用這三種操作,可以将一個物體放在任何位置并面向任何方向。

在我們繼續之前,讓我們構造一個可以讨論平移、縮放和旋轉、操作的簡單的假想。我們将使用一個簡單的網:一個立方體。這個立方體以原點為中心并且尺寸是1*1*1。

注意到因為立方體是以原點為中心的,立方體的每個邊從原點向外延伸了1/2個單元。而且注意到每個面都是和軸垂直的。

平移

平移(translate)的字典定義為:以另一種語言表達出來。這種定義和3D圖形沒什麼關系。在這裡的意思是平移。

讓我們說說我們想讓簡單的立方體向上移動2個單元。我們可以使用一個平移<0,2,0>來實作。

物體可以在單以的平移裡同時沿着幾個軸移動,是以沒必要将每個軸的移動分開平移。例如:平移<2,2,0>可以将立方體向右移動兩個機關同時向上移動兩個機關。

縮放

對一個網或者面執行縮放操作改變了它的大小和位置。首先,讓我們看一下縮放操作是怎樣改變一個物體的大小的。如果我們還是用那個例子1*1*1的立方體,用縮放因子1/2來縮放它,這個立方體每一維上就會變成1/2個機關。如果我們使用縮放因子2,我們将會讓該立方體的每一維加倍,産生一個每一維都有2個機關長的立方體。

正如前面提到的,執行縮放操作還可以改變一個物體的位置。如果立方體不以原點為中心,那麼立方體的位置也和大小一樣受影響。一個縮放操作并不直接縮放物體;他縮放物體的頂點。當縮放因子比1大時,頂點遠離原點。當縮放因子比1小時,頂點向原點移近。

經常的,這種影響不值得因為如果你想要縮放一個物體而不改變它的位置,你必須将物體移動到原點,縮放它,然後再将它移回它原始的位置。一些3D系統(包括Direct3D)允許縮放操作隻改變物體大小而不改變其位置,不管這個物體是不是以原點為中心。這可以用局部或物體軸的方式實作。在縮放一個局部軸上的物體和縮放一個以原點為中心的物體取得的效果是一樣的:物體的大小改變了,但是它的位置(即物體的中心)保持原樣。Direct3D縮放物體預設使用物體的局部軸。

你可以為每個軸指定不同的縮放因子。這樣可以允許物體伸長和縮短。縮放因子1對物體的頂點沒什麼影響,是以1可以用來表示不需要變化的軸。如果我們拿一開始的立方體執行縮放操作<2,1,1>,我們将增大立方體的寬度而不影響其它維。

旋轉

旋轉操作允許我們給物體指派方向。旋轉一個物體需要我們決定旋轉軸和物體要旋轉多大的角度。

我們可以用向量來描述旋轉軸,用一個值來描述物體要旋轉的角度。

讓我們回答立方體的例子并将它沿着Z軸旋轉45度。沿Z軸旋轉的意思是立方體好像被Z軸戳起來一樣旋轉并且可以向任何方向自由旋轉。我們可以用向量<0,0,1>和數字45來表示。

材質貼圖是随着ID軟體非常流行的DOOM(著名3D動作遊戲)的到來而獲得許多關注的。DOOM不是材質貼圖的最初執行者,但是它的确是最受歡迎的遊戲之一。

材質貼圖是一個材質在一個或多個面上的應用或者映射(?)。這種映射的發生和物體在三維空間的位置有關。我們不能隻是将材質拍擊到一個平面上而不考慮物體的位置和觀察者的視角。這樣的場景是很難令人信服的。我們将在這一章後面讨論材質和透視。目前,要記住的是:正确的材質貼圖需要遠物體的材質和近物體的材質進行不同的應用。

材質的自然

材質是二維的顔色值的栅格。材質通常被存儲在我們熟悉的檔案格式比BMP,PCX或者GIF裡。幾乎所有的二維圖象都可以被認為是一個材質。

牢記,雖然你可以把任何一個圖象當作一個材質,但是并不是所有的圖象都是一個好的材質。好的材質通常不是自身用來看的,但它們将物體描繪得現實。圖象完全是完整的場景,通常是差的材質因為你在看一個單獨物體的時候并不期望看到整個場景。3D物體比如鏡子和圖檔是這個規則的例外。

材質縮放比例

材質可以以各種不同的方式應用到物體中來。改變材質的一種方式是改變材質的大小。如果一個材質被應用到一個大的縮放因子,那麼對于一個給定的物體,隻有材質的一部分是合适的。如果縮放因子很小,整個材質将如同一堆重複的瓷磚一樣顯現在物體上。第二種效果對于你要用一個很小的全景來表現一個大的物體很有用。

材質包裝

材質包裝決定了材質怎樣應用到物體上來的方式。最簡單的包裝方式是讓才是好像是從一支槍裡打出來的。材質的各種色彩從物體直直地射出一直到另一端。這種方式通常被稱作平包裝(有點沖突,因為你是不能用一個平的東西來包裝物體的)

這種方式通常被用在大型物體上,尤其當觀察這隻看到物體的一面。平包裝很容易使用因為它們隻需要指明材質應用的方向。因為平材質包裝使得材質隻往一個方向延伸成物體,物體的側面通常看起來是有斑紋的。

另一種常用的方法是圓柱形的。圓柱包裝方式用彎曲或者将材質包裝成一個圓柱形的方法把材質應用到物體。

有一點很重要,材質包裝方式和物體被構成的形狀是完全獨立的。你可以将一個平包裝應用到球體上去,就像将一個球包裝應用到一個立方體上一樣簡單。Direct3D支援平、球、圓柱的材質包裝。

材質活躍

以不同的材質或者不同的材質包裝方式描繪同一個物體叫做材質活躍。一個簡單的例子是将同一個材質應用到物體,但是在每個活躍結構裡改變材質位置。這使得材質穿越物體。這種技術對表現一個移動的物體比如傳送帶很有用處。另一個例子是改變材質的尺寸。這兩種方法執行起來都很簡單(因為它們隻需要一個材質),但在實用方面有所欠缺。

一個更強大的材質活躍技術是在同一個物體上對每一種活躍結構用不同的材質。如果,你想要一個電視機的場面(電視機是打開的),為了每一次電視的更新,你可以在電視螢幕上應用一個不同的材質。這種技術是很有效的,但是需要很大的記憶體如果材質的序列很長或者材質本身很大。

平移、縮放、旋轉和材質物體可以在三維世界裡存在,但是如果他們在黑暗的環境裡就不能被看見。在我們期望看到所有東西之前,我們需要一個光源。當我們看到最後的輸出時,場景裡的物體會根據場景裡光源的性質來被着色。

顔色

所有的光源有一個共同的屬性:顔色。正常情況下光是白色的,意味着所有的顔色都處在最大強度。每個圖形程式包的照明系統都是不一樣的,但是大部分都使用RGB值來定義光源的顔色。在Direct3D裡,RGB中的每個值可以是0(關着)到1(開着),是以白光的RGB值是1,1,1。紅光是1,0,0。藍光是0,1,0。除了紅綠蘭的顔色可以用三種顔色的混合來表現。比如,黃色的RGB值是1,1,0。

照明方式

光源有各種不同的形式。典型的光源包括環境光、點光源和聚光燈。

環境光

最簡單的光源就是環境光。環境光沒有具體的位置并且以相同的強度照亮了整個場景裡的所有物體。這些光是随處可得的因為它們很容易使用。環境光通常和更複雜的光源一起使用。

點光源

點光源朝所有的方向散發光。點光源有一個特殊的位置但是沒有方向。電光源在處理過程中是需求公平的因為要求光向每個方向發散。在處理過程中花費的代價通常是值得的,然而,因為制造電光源的現實效果。點光源有時也叫“全”或者“全方位”光。

方向光

點光源的一個計算更有效的替代是方向光。方向光具有方向,但是沒有位置。方向光發出的光線是互相平行的。方向光有實際意義,在場景裡看起來就像離物體很遠。

聚光燈

聚光燈有方向和位置,并且以圓錐的形狀制造燈光。圓錐的形狀是由本影角和半影角決定的。本影角定義了聚光燈全部照明的圓錐。半影角定義了在本影角周圍減少了燈光的圓錐。聚光燈的半影角通常要比本影角更重要。

Direct3D支援環境光、點光源、方向光和聚光燈。Direct3D還提供了一個方向光的一個變種,叫平行光。

透視轉化

在這章的開始部分,提到了3D圖形的目标是讓二維來表現三維的場景。我們已經講了操作看不見的三維直接,現在我們将要讨論用二維世界制造一個三維世界。

從三維到二維的轉換需要透視轉化。透視轉化確定最終的輸出外觀和正确動作。正确的動作意思是離觀察者近的物體比遠的物體顯得大。也意味着在場景範圍之外的物體或者物體的部分不會被畫出來。這需要我們決定一個物體是否太遠或太近。

從三維到二維需要我們以一種二維空間能容易形成的方式将三維空間分開。這意味着我們需要決定觀察者、照相機位于什麼地方,場景的多少部分觀察者是可以看見的。觀察者位于金字塔的頂點并且向下看金字塔的底部。當金字塔的底部變大時,場景的更多部分被看見了,但是物體卻變小了。當金字塔的底部變小時,場景裡的物體變大了,但是更少的物體進入了場景。金字塔底部的大小由觀察者的視角和視場所決定。

使用不同的觀察平截頭體設定同改變照相機的鏡頭類似。使用長焦鏡頭讓你看清遠處的物體,但是你不用為你的家人拍照片而站在400英尺遠的地方。從另一方面說,你可以為了特寫鏡頭而使用廣角鏡頭,但這并不适合野外觀察鳥(除非你觀察的鳥在一個籠子裡)。

隐藏表面去除技術

3D圖象裡很重要的一個問題是,決定那些物體是可見的,哪些是被其它物體隐藏的。不關注哪些表面離觀察者近,哪些離觀察者遠而表現一個場景,最終的圖象會産生迷惑。解決這一問題的算法就叫隐藏表面去除技術。有很多種隐藏表面去除技術,各有各的有點。Direct3D使用的技術叫做Z-緩沖。

Z-緩沖

Z-緩沖用存儲緩沖器來跟蹤哪些表面是離物體近的。在緩存裡的Z值不必要和Z軸有關;相反地,它們表示表面離觀察者有多遠。當圖象畫出來的時候,Z值可以和緩沖區裡的Z值進行比較。如果在緩沖區裡的值表明目前被畫的表面比任何存在的表面離觀察者近,那麼新的表面就畫在老的表面之上。如果新的表面比一個存在的表面遠,那麼該表面就不被畫出。

将表面從前至後排序可以使得執行優化。這優化了執行因為在場景之前的物體先被畫,之後的表面就根本不用再畫了。幸運的是,Direct3D保留了執行Z-緩沖的模式(包括優化排序)而不需要程式員幹涉。

Z-緩沖:正面和反面

Z-緩沖被認為是最簡單、最快速的隐藏表面去除技術之一。它在象素上還是精确的(一些算法不是)并且可以高效地處理複雜的場景。Z-緩沖最主要的缺點是Z-緩沖需要大量記憶體。Z-緩沖至少要輸出圖象那麼大的存儲空間并且是32位的。例如,一個800*600運作模式的程式使用16位Z-緩沖光是Z-緩沖需要将近一兆的記憶體空間。

表現方式

一旦一個場景可以用三維空間模拟出來,還可以轉化為二維的,它就可以表現出來了。這最後的一步産生了圖象,它可以在你的螢幕上顯示出來,這叫描寫或者留影。有很多不同的表現技術存在;讓我們看一下一些更常用的技術。

再構造

再構造表現看起來不那麼真實并且不需要我們讨論過的所有步驟。再構造模式隻是畫了場景離面的邊,用直線來表現它們。

無光

無光表現是從不把光源考慮進去的事實得到名字的。畫面的時候用指定的面的顔色和材質而并不考慮光的值或面的方向。無光場景可以快速描繪但是物體會趨于輪廓化。

平面描繪輸出的真實性要大于再構造或者無光輸出。平面描繪再表面上将光源考慮進去。每個面都要計算出法線并且法線要用來計算整個面的照明屬性。平面描繪比再構造或者無光表現需要更大的計算性能。

明暗處理

明暗處理描繪和平面描繪類似,除了法線是為每個點計算的而不是每個面。面是由整個面的平均照明強度描繪出來的。這有點類似于網的周邊外貌,單個面變得模糊。明暗處理描繪提供了真實的輸出,但是讓物體看起來模糊和松散定義。因為使用的是點法線而面強度是平均出來的,明暗處理描繪比平面描繪更需要強大的計算能力。

簡單光照

簡單光照描繪是明暗處理描繪的進一步提高。就像明暗處理,簡單光照使用點法線,但是整個面都計算法線而不是去計算平均數。這種額外的工作提供了一個精确的、可預見的外形。正如你可以想象的,簡單光照描繪比明暗處理要慢。沒有特征可以提供,因為在寫這文章的時候,Direct3D還不支援簡單光照。

光線跟蹤

光線跟蹤比任何表現方式産生更真實的輸出。事實上,光線跟蹤因它的照片現實甚至宣傳現實輸出而被知曉。光線跟蹤使用和我們所讨論過的方式完全不同的方法,光線跟蹤算法自動計算陰影、反射和折射(其它表現方式不能自動執行計算)。不幸的是,光線跟蹤慢慢銷聲匿迹了。單一的圖象要用一天或者更長的時間來計算。更不必說,光線跟蹤不适合實時圖形并且不被Direct3D支援。

如果不活躍,實時的三維圖形就沒意思。三維活躍可以通過兩種方式來實作:運動屬性和鍵架。

運動屬性

達到活躍的最簡單的方法之一就是用運動屬性。運動屬性可以是平移、旋轉或者縮放因子在每次螢幕更新時應用到一個或一組物體上。運動屬性對簡單重複的動作是有用的。一旦一個運動屬性指派到一個物體上,物體将會根據屬性移動,不受任何幹涉。

鍵架

鍵架的名字來自于在一個活躍中隻是特定的鍵的幀被畫出來的傳統的活躍技術。剩下的幀用關鍵幀中的中間動作來産生。

三維圖形裡的鍵架意味着你隻要在鍵的時間裡在一個場景中定義物體的位置。計算機負責在剩餘的幀裡放置物體。

鍵架需要你決定在一個活躍中幀的數量并且在特殊的幀定義鍵。例如,如果你想要建立這麼一個活躍:物體從螢幕的左上角運動到右上角然後再到右下角,你可以執行如下步驟:

1.在活躍中定義幀的數量(我們在這個例子裡用30)

2.在第1幀中指定物體要在螢幕的左上角出現

3.在第15幀中指定物體要在螢幕的右上角出現

4.在第30幀中指定物體要在螢幕的右下角出現

在Direct3D裡鍵架有兩種模式:直線的和基于鋸齒的。線鍵架的意思是關鍵幀之間的活躍移動是線型的;物體在關鍵證之間以最短路徑移動。基于鋸齒的活躍在關鍵幀之間行走彎曲的路徑。

用我們的例子來說,線鍵架使得物體徑直地從螢幕的左上角移動到右上角。在第15幀(當物體到達右上角)物體将突然轉向移向右下角。基于鋸齒的活躍在第15幀将使物體園曲地繞過拐角。物體好像期待着将要拐彎這樣一個事實。

在直線和基于鋸齒地活躍裡,場景中的物體都是精确地在你指定的關鍵幀中。

總結

雖然圖形程式包各個都不一樣,但是通常概念和術語都使類似的。這章裡講的概念和術語是很普遍的并且可以應用到大多數圖形系統上。下一章将介紹Direct3D。我們将會看到Direct3D是怎樣執行這些通常的技術的,它和别的圖形程式包有什麼差別。