1. 程式人生 > >卡通風格的渲染【Unity Shader入門精要14.1】

卡通風格的渲染【Unity Shader入門精要14.1】

卡通渲染的方法之一:基於色調的著色技術(tone-based shading)。P288

實現中,我們往往會使用 漫反射係數 對一張一維紋理進行取樣,以控制漫反射的色調 。(7.3節中用漸變紋理實現過這種效果)

卡通風格的高光往往是一塊分界明顯的純色區域。

除了光照模型不同外,卡通風格通常還需要在物體邊緣部分繪製輪廓,本節使用基於模型的描邊方法


14.1.1渲染輪廓線

在實時渲染中,輪廓線的渲染是應用非常廣泛的一種效果,在《Real Time Rendering,3rd》一書中,作者把這些方法分成了5種類型:

  1. 基於觀察角度表面法線的輪廓渲染:適應視角方向和表面法線
    點乘結果來得到輪廓線的資訊。這種方法簡單快捷,可以在一個Pass中就得到渲染結果,但侷限性很大,很多模型渲染出來的描邊效果都不盡如人意。
  2. 過程式幾何輪廓線渲染:核心是使用兩個Pass渲染,第一個渲染背面的面片,並使用某些技術讓他的輪廓可見,第二個Pass再正常渲染正面的面片。這種方法的優點在於快速有效,並適應於絕大多數表面平滑的模型,但缺點是不適合類似立方體這樣平的模型。          (本節使用這種,第一個Pass使用輪廓線顏色渲染整個背面的面片,並在視角空間下把模型頂點沿著法線方向向外擴張一段距離,以此來讓背面的輪廓可見
    viewPos = viewPos + viewNormal*_Outline;
    但是,如果直接使用頂點法線進行擴充套件,對於一些內凹的模型,就可能發生背面面片遮擋正面面片的情況。為了儘可能防止出現這樣的情況,在擴充套件背面頂點之前,我們首先對頂點法線的Z分量進行處理,使他們等於一個值,然後把法線歸一化後再對頂點進行擴張,這樣的好處在於,擴充套件後的背面更加扁平化,從而降低了遮擋正面面片的可能性
    viewNormal.z=-0.5;
    viewPos=normalize(viewNormal);
    viewPos=viewPos+viewNormal*_Outline;
    
  3. 基於影象處理的輪廓線渲染邊緣檢測方法就屬於這種型別,優點在於可以適用於任何型別的模型。但也有自身的侷限所在,一些深度和法線變化很微小的輪廓無法被檢出來,如桌子上的紙。
  4. 基於輪廓邊檢測的輪廓線渲染:上面提到的方法中一個最大的問題就是無法控制輪廓的風格,想渲染出如水墨風格的輪廓線,為此,需要檢測出精準的輪廓邊,然後直接渲染他們,檢測一條邊是否是輪廓邊的的公式很簡單,只需要檢查和這條邊相鄰的兩個三角形是否滿足下面的條件:(n_{0}\cdot v>0)\neq (n_{1}\cdot >0)   其中,n0和n1分別表示兩個相鄰的三角形面片的法向,v是從視角到該邊上任意頂點的方向。上訴公式的本質在於檢查兩個相鄰的三角面片是否是一個朝正面,一個朝背面。我們可以在幾何著色器(Geometry Sahder)的幫助下實現上面的檢測過程,當然,這種方法的缺點除了實現相對複雜外,還有動畫連貫性的問題,也就是說由於是逐幀單獨提取輪廓,所以在幀與幀之間會出現跳躍性。
  5. 混合上述的幾種渲染:例如,首先找到精準的 輪廓邊,把模型和輪廓邊渲染到紋理中,再使用影象處理的方法識別出輪廓線,並在影象空間下進行風格化渲染。

14.1.2 新增高光

對於卡通渲染的高光反射光照模式,需要計算normal和halfDir的點乘結果,把該值和一個閥值進行比較,如果小於閥值,則高光反射係數為0,否則1。

float spec=dot(worldNormal,worldHalfDir);
spec=step(threshold,spec);

CG 的Step函式:(參考值,待比較值)如果第二個大於第一個則返回一。

但是,這種磁暴的判斷方法會在高光區域的邊界造成鋸齒。原因在於高光區域的邊緣不是平滑漸變的,而是由0突變到1,想進行抗鋸齒處理可以在很小的一塊區域內,進行平滑處理

float spec=dot(worldNormal,worldHalfDir);
spec=lerp(0,1,smoothstep(-w,w,spec-threshold));

CG 的smoothstep函式:w是一個很小的值,當spec-threshould小於-w時返回0,大於w時返回1否則在0到1之間進行插值。

這樣的效果是可以在[-w,w]區間內,即高光區域的邊界處得到一個從0到1平滑變化的spec值,從而實現抗鋸齒的目的。

畫素之間的近似導數值用 CG的 fwidth 函式來得到。