1. 程式人生 > >[圖形學] 《Real-Time Rendering》卡通渲染

[圖形學] 《Real-Time Rendering》卡通渲染

原文:《Real-Time Rendering,Third Version》 Toon Shading章節

11.1 卡通著色

        正如不同的字型能給文字帶來不同的風格一樣,不同的渲染風格也有著自己的情緒,含義和詞義。人們對於NPR的一種特殊形式——卡通渲染(cel or toon shading)給予了大量的關注。由於這種風格和卡通形式相一致,它具有豐富的幻想感和童真感(至少在西方世界)。在最為簡單的情況下,我們使用實線繪製物體邊緣,用純色塊填充不同的區域。McCloud在他的經典著作《Understanding Comics》中描述了這種風格流行的一個原因:"通過簡化來擴充套件"。也就是說,通過簡化和剔除複雜的部分,可以增加表達的資訊量。觀眾會更加認可那些以簡單風格繪製的卡通人物。

        在計算機圖形學中,卡通渲染風格已經發展了十多年,用於將三維模型和二維卡通動畫關聯。和其他NPR相比,它更容易通過計算機自動生成,因為它的定義更加容易。像Okami和Cel Damage這樣的遊戲已經有了很好的表現效果。如圖11.2.

         卡通渲染有著很多不同的方式。對於只有紋理沒有光照的模型,可以通過簡化紋理來近似實心填充的卡通風格。在著色中,兩種最常用的方法是用實心顏色填充多邊形區域(無光),以及使用雙色調來表達光照和陰影區域。實心填充是比較樸素的方式,而雙色調填充,有時候稱作硬著色(hard shading),可以通過將傳統光照方程中的元素重對映到不同的顏色上實現。這一方法和Grooch在NPR技術照明中的光照模型相關聯。此外,輪廓通常使用黑色來表達,它使得物體卡通的效果更加明顯。下一章將描述計算以及渲染輪廓的方法。

        Lake和Lander都提出了一種對每個頂點計算n· l 點積,並作為紋理座標來訪問一維紋理的方法來計算漫反射的思想。這可以在CPU中完成,也可以通過簡單的頂點著色器實現。紋理對映本身只包含了兩個色調,亮和暗。因此,對於朝向光源的面,將使用亮色調的紋理。對於漫反射而言,n· l < 0 意味著表面遠離光照,它處在陰影中。不管怎樣,我們可以將漫反射重對映到任何其它期望的值。例如,在圖11.3中,雙色調填充使用的閾值是0.5。類似地,簡單的一維紋理可以重新對映鏡面高光。Card and Mitchell描述瞭如何在GPU上實現這種陰影演算法。Barla等人使用二維紋理來代替一維紋理,以增加視點相關性。我們通過表面深度或者方向來訪問二維紋理。這允許在遠處或者快速移動的物體能夠表現得比較平滑。例如,Rusinkiewicz等人表達了一個有趣的可變著色模型,他沿著相反的思路進行,通過調整視覺光位置給表面陰影帶來高對比度,超現實的感覺。

11.2 描邊渲染

        NRP演算法的主要主題和技術中包含了卡通輪廓線渲染。Isenberg等人對本課題做了深入的研究。我們的目標是給出一個更加通用,一般性的演算法。使用的輪廓演算法可以根據表面角度,過程幾何,影象處理,向量邊緣檢測或者他們的混合使用進行粗略的分類。卡通渲染中有著不同型別的邊緣:

        •  不被兩個多邊形共享的邊界線。例如,一張紙的邊界。固體物體通常沒有邊界線。

        •  由兩個多邊形共享的摺痕、特徵邊,且兩個多邊形之間的角度(二面角)大於某個閾值。一個較好的預設角度為60度。此外,摺痕的邊緣是頂點在兩個相鄰多邊形之間頂點法線不同的地方。例如,一個立方體有著摺痕邊。摺痕邊可以進一步細分為脊和谷邊。

         •  兩個不同材質或者其它原因導致著色有差異的三角形之間的材質邊。它也可以是美術希望一直顯示的邊緣,比如前額線或者分開相同顏色的褲子和襯衣的線。

         •  兩個相鄰三角形相對於某個方向向量(通常是視線)有著不同的面向的輪廓邊緣。

        如圖11.4,這種分類是基於文獻中的常見用法,但也有一些變化。例如,我們所謂的摺痕以及材質邊緣有時被稱為邊界邊緣。雖然我們在這裡關注的是卡通渲染,但是已經研究了在表面上表示輪廓、脊、谷的繪製線或來自光照的高光。

       對於卡通渲染,我們使用從眼睛到邊緣上某個點的向量來定義輪廓邊緣。換言之,輪廓邊緣相鄰的三角形一個是正面的,另一個是背面的。注意,這與計算機圖形學定義和通常指的輪廓(即物件的外部邊界)稍有不同。例如,在頭部的側面,計算機圖形學定義中包含了耳朵的邊緣。輪廓邊緣的定義有時還可以包含邊界邊緣,也就是那些連線相同三角形前面和後面的邊。我們定義輪廓邊緣不包括邊界邊緣。12.3節討論處理多邊形資料,並建立具有一致面向的連線網格,以及確定邊界、摺痕和材質邊緣。

11.2.1 表面角描邊

        類似於11.1中的表面著色器,我們可以使用視點方向和表面法線之間的點積來計算輪廓邊緣。如果這個值接近0,那麼這個表面幾乎處在眼睛視線的邊緣處,所以可以認為是邊緣。這一技術相當於使用球形環境貼圖在物體邊緣周圍用黑色環進行表面著色,參照圖11.5。在實踐中,可以使用一維紋理來代替訪問環境對映。Marshall 展示瞭如何使用頂點著色著色器來表現描邊,他沒有計算反射方向來訪問環境對映,而是使用視線和頂點法線的點積來訪問一維紋理。Everitt使用mipmap金字塔來執行這一過程,把最頂層繪製為黑色。當表面變為邊緣,它將訪問最頂層,因此著色為黑色。由於沒有使用頂點插值,邊緣會更加清晰。這些方法非常快,因為在一次pass中將完成所有工作,並且紋理濾波會幫助消除邊緣的鋸齒。

        這種技術只適用於某些模型,他們的表面法線和輪廓邊緣存在一定的關聯。對於像立方體這樣的模型,這種方法是失敗的,因為我們通常無法找到輪廓邊緣。然而,通過顯式地繪製摺痕邊緣,這種尖銳的特徵將被正確地呈現,儘管風格和輪廓邊緣有所不同。這種方法的特點或者說是缺點是隨著表面曲率的變化,輪廓線的寬度會變化,大而平的多邊形在接近邊緣時會完全變黑,這通常不是我們所期望的效果。在實驗中,Wu法線對於遊戲《Cel Damage》,這種技術對於1/4的模型給出了極好的結果,而其它的卻失敗了。

11.2.2 過程幾何描邊

       Rossignac和van Emmerik提出了實時輪廓渲染的一種技術,後來由Raskar和Cohen進行了改進。其基本思想是先渲染正面,然後用某種方法渲染背面,使其輪廓邊緣可見。有許多渲染背面的方法,每個方法都有自己的長處和弱點。每一種方法的第一個步驟,都是繪製正面圖,然後開啟正面剔除關閉背面剔除,從而只繪製背面。渲染輪廓邊緣的一種方法是隻繪製背面的邊緣(而非正面),使用偏移(biasing)或者其它技術確保這些線條畫在正面的前面。這樣,除了輪廓邊緣以外,所有的線都是隱藏的。

       製作更寬線條的一種方法是使用黑色渲染背面,在沒有偏移的情況下,這些背面將始終保持不可見。所以,我們要做的是在螢幕z軸上移動背面來偏移它們。這樣,只有背面三角形的邊緣是可見的。Raskar和Cohen給出了一些偏置的方法,比如固定量的平移,或者z-深度的非線性補償,或者使用像glPolygonOffset一樣的呼叫進行深度斜率偏移。Lengyel討論瞭如何通過修改透視矩陣提供更精細的深度控制。所有這些方法的一個問題是,它們建立的線不具有均勻的寬度。要做到均勻,向前移動的數量不僅取決於背面,還要取決於相鄰的正面,參見圖11.6。背面的斜率可以用來使多邊形向前偏移,但線的厚度也取決於正面的角度。

        Raskar和Cohen通過使每個背面三角形沿著邊緣變大,從而解決了這種鄰居以來的問題。也就是說,三角形的斜率和視點的距離決定了三角形的擴充套件程度。

        一種方法是沿著平面向外擴充套件每個三角形的頂點。渲染三角形一個更安全的方法是向外移動三角形的每個邊並且連線邊緣,這樣避免了頂點遠離原始三角形,可見圖11.7。注意,這種方法不需要對三角形進行偏移,因為背面已經擴充套件到了正面的邊緣之外。圖11.8展現了三種方法的結果。Raskar在後面的論文中提出了一種改進的邊緣擴充套件因子的計算方法。

        在剛才給出的方法中,背面的三角形沿著它們原始面進行擴充套件。另一種方法是沿著頂點法線移動頂點,移動距離與到眼睛的距離成比例。這種方法被稱作"殼"或者"暈",因為移動的背面形成了圍繞原始物件的外殼。想象一個球體,先正常渲染球體,然後相對於球體中心5畫素寬擴充套件球體半徑。也就是說,移動球體中心的一個畫素,等於在世界空間中移動球體3毫米。參見圖11.9。對於頂點著色器來說,它能很好地完成將頂點沿著法線外擴的任務,因此加速器可以在沒有任何CPU幫助的情況下繪製輪廓。這種型別的擴充套件有時稱作殼(shell)對映。頂點資訊是共享的,因此可以渲染整個網格,而不是單個多邊形。該方法實現簡單、效率高、魯棒性好、效能穩定,是遊戲《Cel Damage》所使用的方法,可參照圖11.10。

        這種殼(shell)技術有許多潛在的缺陷。想象從正面觀察一個立方體,只有一個面是可見的,形成輪廓邊緣的四個背面的每一個都將沿著其對應的立方體面方向移動,因此在角落處留下間隙。這是因為每個拐角處都有一個頂點,每個面都有不同的頂點法線。問題在於,展開的立方體並不真正形成外殼,因為每個角頂點都在不同的方向上展開。一種解決方案是在同一位置上強制頂點共享一個新的、平均的頂點法線。另一種技術是摺痕上建立退化幾何,然後按區域擴充套件成多邊形。

      殼(shell)和擴充套件技術都會比較浪費,因為所有的背面都進行了渲染。擴充套件技術不能作用於曲面,殼技術可以作用於曲面,只要曲可以沿著曲面法線向外移動。z軸偏移適用於所有曲面,因為唯一的修改是z深度的偏移。所有這些技術的侷限性在於,無法控制邊緣外觀,半透明表面很難使用輪廓渲染,並且沒有某種形式對邊緣做抗鋸齒。

       這一類幾何技術的一個值得注意的特點是不需要鄰居資訊或者邊緣列表。每個多邊形獨立於其餘部分進行處理,因此這種技術適合於硬體處理。然而,這裡討論的所有方法都一樣,每個網格都應該進行預處理,保證面是一致的。

       此類演算法只渲染輪廓邊緣,其它邊緣(邊界,摺痕和材質邊)必須以其它方法呈現。這些可以使用11.4節中的線繪製技術之一來繪製。對於可變性物體,摺痕線可隨著時間變化。Raskar給出了繪製脊線的一種很好的方案,無需建立和訪問邊緣連線資料結構。其思想是在渲染三角形的每個邊上生成一個附加多邊形,這些邊緣多邊形通過使用者定義的臨界二面角來確定何時應該看到摺痕。現在,如果兩個相鄰的三角形大於這個臨界值,那麼邊緣多邊形將是可見的,否則,它們將被三角形隱藏。對於谷邊,該技術可以通過使用三次模板緩衝區實現。

11.2.3 影象空間中的描邊

        上一節中的演算法有些被分類為基於影象的因為螢幕解析度決定了它們是如何執行的。另一種演算法是更直接地基於影象的,因為它們完全根據儲存在緩衝區中的資料進行操作,並且不修改(甚至不知道)場景中的幾何形狀。

        Saito和Takahashi第一次引入了G-Buffer的概念,也稱作延遲渲染。Decaudin擴充套件了G-Buffers在卡通渲染中的應用。基本的想法非常簡單:NPR可以通過在各種資訊緩衝器上執行影象處理技術來完成,通過尋找相鄰z緩衝區中的不連續性,可以找到大多數輪廓邊緣的位置。相鄰表面法線值不連續的地方指向了(並且常常是輪廓)邊緣。使用環境顏色渲染場景也可以檢測其它兩種技術可能遺漏的邊緣。

        Card和Mitchell首先使用了頂點著色器將場景中的世界空間法線和z深度渲染成紋理,從而實時執行這些影象處理操作。法線被寫入顏色的一般通道,z深度被寫入alpha通道。

       一旦建立了這個影象,下一步就是找到輪廓、邊界和摺痕邊緣。其思想是使用法線圖和z深度圖(在alpha通道中)渲染填充螢幕的四邊形並檢測邊緣的不連續性。想法是在一次pass中對同一紋理進行六次取樣,並實現sobel邊緣檢測濾波器。通過對四邊形的使用6對不同的紋理下標來訪問進行六次取樣。這個濾波器實際上被兩次應用到紋理上,一次沿著一個軸,最終合成兩個結果影象。另一個特徵是,所產生的邊緣的厚度可以通過進一步的影象處理技術來膨脹或者腐蝕。相關結果可以參照圖11.11。

       該演算法有許多優點。該方法處理所有基元,甚至曲面,不像大多數其它技術。網格不必保持一致或者連線,因為該方法是基於影象的。從效能的角度來看,CPU不參與建立和遍歷邊緣列表。

       該技術的缺陷相對較少,對於處於邊緣的表面,z深度比較濾波器可能會錯誤的檢測表面上的輪廓邊緣畫素。z深度比較的另一個問題是,如果差異最小,那麼可以忽略輪廓邊緣。例如,通常會忽略一張紙的邊緣。類似的,法線濾波器也會跳過這張紙的邊緣,因為法線是相同的。檢測這種情況的一種方法是在場景的環境光或者物件id顏色渲染上新增一個濾波器。但這仍然不是萬無一失的,例如,摺疊一張紙依然會產生邊緣重疊的不可檢測的邊緣。

       由於z深度資訊是保留的最重要的位元組,所以比紙張更厚的特徵也可能丟失,特別是在z深度範圍更大的大場景中。可以使用更高精度的深度資訊來避免這一問題。

11.2.3 輪廓邊緣檢測

        迄今為止所描述的大多數技術都有著需要兩個pass來渲染輪廓的缺點。對於過程幾何方法來說,第二個pass中的背面渲染通常會檢測出比實際邊緣更多的畫素。隨著邊緣變厚,會出現更多的問題,而且也無法控制渲染的風格。影象方法也有著類似生成較粗線條的問題。另一種方法是檢測邊緣輪廓並直接渲染它們。這種形式的輪廓邊緣渲染允許我們更好的控制如何渲染線條。由於邊緣和模型無關,因此可以建立像網格在衝擊中凍結導致輪廓發生意外跳變的效果。

        輪廓邊的兩個相鄰三角形一個面向觀察者一個遠離觀察者,測試公式為:

        其中n0,n1代表三角形的法線,v代表從眼睛指向物體的實現方向(到任一末端)。為了使測試正確工作,表面朝向必須保持一致(參見12.3節)。

        找到模型中的邊界線的標準方法是迴圈遍歷邊緣列表並進行測試。Lander指出一種可行的技術,即提出平面多邊形內的邊緣。也就是說,給定一個連線的三角形網格,如果一個邊緣的兩個相鄰三角形位於同一平面上,不要將這個邊緣新增到邊緣列表中,來測試它是輪廓邊緣。在一個簡單的時鐘模型上實行這個測試將邊計數從444個降到了256個。提高輪廓邊緣搜尋效率的方法還有很多。Buchanan和Sousa通過對每個單獨面重復使用點積測試,避免了對每個邊緣進行單獨點積測試。Markosian等人從一組輪廓環開始,使用隨機化搜尋演算法來更新該集合。對於靜態場景,AILA和Miettinen採取了不同的方法,將有效距離和每個邊緣相關聯。這個距離是觀察者可以移動到的,仍然存在輪廓,且內部邊緣保持狀態的最遠距離。通過仔細的儲存,可以最小化輪廓的多餘計算。

       在任何模型中,每個輪廓總是由一個單一閉合曲線組成,稱為輪廓環。因此,每個輪廓頂點必須有偶數的輪廓邊緣。請注意,表面上可以有不止一個輪廓曲線。類似的,輪廓邊緣可以僅屬於一條曲線。這並不意味著輪廓曲線上每個頂點只有兩個輪廓邊緣。例如一個形狀類似於數字8的中間點就有4條邊緣。一旦在輪廓線上找到了邊緣,那麼也可以去測試它的鄰居是不是也是邊緣。我們重複這一步驟直到整個輪廓被找到。

        如果幀與幀之間相機和物件移動較小,那麼可以合理地假設來自先前幀的輪廓邊緣仍然可能是有效的輪廓邊緣。因此,這些部分可以用於下一幀開始檢測輪廓邊緣。當模型改變方向時,輪廓環也在建立和破壞。 Hall討論了這些檢測,以及大量的實現細節。與暴力演算法相比,Hall報告的效能提高了七倍。主要缺點是,如果沒有成功找到它們,新的輪廓環可能丟失一幀甚至更多。

        該演算法可以傾向於更好的速度或者質量。一旦找到了輪廓,立即畫出線條。顯式地找到輪廓線的一個優點是可以使用線條、紋理或者其它方式進行繪製。需要某些型別的偏移來保證線條在表面前的適當位置繪製。如果繪製了較厚的邊,也可以適當地拼合而沒有間隙。這可以通過在每個輪廓頂點處繪製一個螢幕對齊的圓來完成。

        輪廓繪製的一個重要特點是它突出了模型的多邊形性質,也就是說,模型的輪廓是由直線構成的這一點特性更加明顯了。Lake給出了一種繪製曲線輪廓邊緣的方法。這個想法是根據輪廓邊緣的性質來使用不同紋理的筆觸。這種技術僅在物件本身被賦予與背景相同的顏色時才起作用,否則筆刷和填充區域可能不匹配。輪廓邊緣檢測的一個相關問題是,它不適合頂點混合,N-patch或者其它加速器生成的表面,因為這些多邊形在CPU上是不可用的。

        顯示邊緣檢測的另一個缺點是它是CPU密集型的。一個主要的問題是潛在的非連續記憶體訪問。如果可能的話,以一種有利於快取的方式同時對錶面、邊緣和頂點進行排序是困難的。為了避免CPU處理每一幀,Card和Mitchell使用頂點著色器來檢測和渲染輪廓邊緣。其思想是將模型的每個邊緣作為退化的四邊形沿著渲染流水線傳送,每個頂點連線兩個相鄰的三角形法線。當我們發現一個邊是輪廓的一部分時,四邊形的點被移除,此時它不再是退化的(此時可見)。這使得一個退化四邊形“展開",這意味邊緣的繪製。這和頂點著色器的陰影體積建立技術的思想是一致的,這在頁碼347中提及。只有一個相鄰三角形的邊界邊緣,也能通過傳入這個三角形法線的相反數作為第二個法線來處理。以這種方式,邊界邊緣總是能被處理成一個待渲染的邊緣。這種技術的主要缺陷是,通過渲染流水線傳送的多邊形數量大大增加,並且如果網格進行了非線性變換,其效能會下降。McGuire和Hughes提出了一種使用endcaps能提供更高質量的方法。

       如果幾何著色器是流水線的一部分,這些額外的多邊形不需要在CPU生成並存儲在網格中。幾何著色器本身可以根據需要生成退化四邊形。例如Gooch等人使用了高斯對映來確定輪廓邊緣。在14.2.1的最後一分鐘,討論了快速將多邊形集合分類為前向或是後向的分層方法,請參照Hertzman的文章或是NRP著作,以瞭解有關這方面的內容。

11.2.5 混合描邊

        Northrup和Markosian同時使用了影象和幾何元素的方式來渲染邊緣。他們的方法是使用一個輪廓邊緣的列表,然後,渲染所有物體的三角形和輪廓邊緣,併為每個物體一個不同的id號(例如,制定一個唯一的顏色)。我們讀取id的緩衝區,並根據它來決定可見的輪廓邊緣。之後,對這些可見的片段進行重疊檢查,並連線在一起形成平滑的路徑。然後根據這些重構出的路徑進行渲染。這些路徑本身可以用不同的方式來處理,包括錐度、擺動、漸變以及深度和距離等。圖11.12顯示了一個示例。

         Kalnins等人在他們的工作中使用的方法涉及到了NPR的重要研究領域:時間相干性。在某個方面,獲取輪廓僅僅是個開始。當物體以及觀察者移動的時候,輪廓邊緣發生改變。通過筆畫提取技術,可以通過跟蹤單獨的輪廓環來獲得連貫性資訊。然而,當兩個環合併在一起時,需要採取一些糾正措施,否則會在幀與幀之間出現明顯跳動。可以使用畫素搜素和“選舉”演算法來嘗試保持輪廓幀與幀之間的連貫性。