在5月18日的Qualcomm驍龍游戲和圖形開發(fā)者研討會上,Qualcomm資深工程師張濤就移動平臺上如何創(chuàng)建高級3D特效進(jìn)行了分享。從卡通渲染、皮膚、衣服、毛皮、景深到隨深度衰減的霧、上帝之光以及復(fù)古色等,深度講授繪制各種材質(zhì)的方法。
卡通渲染
卡通渲染是一類使圖像具有手繪圖風(fēng)格的技術(shù),換句話說,這種技術(shù)可以將渲染圖像“卡通化”。與傳統(tǒng)的真實(shí)感渲染技術(shù)不同,卡通渲染的光照計算結(jié)果被有意離散化,它們被映射到離散的色調(diào)中,并且通過突出模型邊緣來產(chǎn)生“勾邊”的效果。
實(shí)現(xiàn)
卡通渲染類似手繪圖,它的風(fēng)格看起來非常簡潔,但算法實(shí)現(xiàn)卻比較復(fù)雜,需要經(jīng)過多步渲染才能得到最終結(jié)果。具體步驟如下:
- 第一步:得到平坦化、條帶狀的圖像。這是通過把光照計算的結(jié)果當(dāng)成紋理坐標(biāo),用于索引一張顏色坡度紋理得到的。光照計算可以采用任意的光照模型。
- 第二步:渲染法向圖。場景模型的法向被渲染到一個臨時的離屏render target上,這個法向圖只是用來做邊緣檢測,并不會對最終結(jié)果產(chǎn)生直接影響。
- 第三步:對法向圖進(jìn)行邊緣檢測,并將其結(jié)果與第一步的圖像混合得到最終結(jié)果。
皮膚
皮膚渲染是實(shí)時計算機(jī)圖形學(xué)的難題之一,一方面,這是因?yàn)槠つw光照的復(fù)雜性,另一方面,觀察者對皮膚太熟悉了,一旦結(jié)果看起來“不像”,他們就很難接受。關(guān)于皮膚的光照模型有幾個,比如Hanrahan和Krueger在1993年的Siggraph上首次將皮膚進(jìn)行分層模擬計算光照反射。他們的方法看起來非常逼真,但是每個光照計算需要100個指令,這對于實(shí)時的要求來說太昂貴。
張濤在實(shí)例中展示了一個經(jīng)過優(yōu)化過的皮膚渲染算法,它可以運(yùn)行在移動設(shè)備上。這個技術(shù)通過在陰影區(qū)域的漫反射中加入暖色調(diào)來逼近次表面散射。并在漫反射計算中加入Minnaert光照項,能得皮膚看起來柔嫩,最后,通過加入鏡面高光使皮膚看起來富有光澤。
實(shí)現(xiàn)
該實(shí)現(xiàn)的光照方程如下:
Final color = Ambient color+ Minnaertdiffuse color+ Subsurface scattering color+ Specular highlights
除了傳統(tǒng)的輻射反射,Minnaert光照模型還記錄了從皮膚反射的光輻射度,因此它被用來模擬皮膚的漫反射。它比別的光照模型看起來更柔軟,而且它還可以關(guān)閉自陰影,從而讓藝術(shù)家可以控制皮膚的“粗糙度”。
// General Minnaertformula:
// Result = Color * (cos(NL)^k * cos(VN)^(1-k))
floatA = saturate( pow( max( 0.02, NL ), g_MinnaertExponent) );
floatB = saturate( pow( VN, 1.0-g_MinnaertExponent) );
gl_FragColor.rgb+= Color.rgb* ( A * B );
衣服
衣服無處不在,通常人體90%的部分被衣服覆蓋,因此想要創(chuàng)建逼真的人物模型的話,一個好的衣服著色器是必不可少的。需要注意的是,即便是最普通衣服上的一塊布料也有著大量的凸起、褶皺和變形扭曲。衣服可以看起來是柔軟的,也可以看起來像閃亮的絲絨。
馬塞爾Minnaert在1941年提出一種各向異性光照模型,這個模型至今在現(xiàn)代計算機(jī)圖形學(xué)的衣服渲染中仍被廣泛使用。Minnaert渲染使用雙向反射分布函數(shù)生成該各向異性光照函數(shù)。與其它的光照模型不同,該模型通過考慮視角來計算衣服模型的粗糙度,因此在光線和觀察方向匯聚的時候漫反射顏色不會過飽和,另一方面,從接近模型平行的角度看去的話模型會顯得較黑,看起來有絲絨的感覺。
實(shí)現(xiàn)
實(shí)例演示中的著色器使用了一個經(jīng)過修改的Minnaert公式,從而可以得到出高光區(qū)域和陰影區(qū)域光滑過渡的效果。
// General Minnaertformula:
// Result = Color * (cos(NL)^k * cos(VN)^(1-k))
// float A = saturate( pow( NL, g_Minnaert) );
// float B = saturate( pow( VN, 1.0 -g_Minnaert) );
// float Diffuse = ( A * B );
// Enhanced Minnaert:
floatDiffuse = NL * pow( max( NL * VN, 0.1), 1.0-g_Minnaert);
在兩個公式中,如果g_Minnaert為1.0,這個方程就是標(biāo)準(zhǔn)的Lambertian模型。隨著Minnaert指數(shù)的變化,邊緣的顏色會隨之變深。
這個經(jīng)過修改的公式更好的模擬了像衣服一樣的模型表面,因?yàn)樗テ搅四P偷挠策?。在一般的Minnaert方程中,硬邊在Minnaert參數(shù)較小的情況下會出現(xiàn)在NL == 0的地方。這對某些視角或者在有諸如次表面散射等其它光照項存在的情況下很有用,它強(qiáng)化了這種自然過渡的感覺。
毛皮
渲染個人的頭發(fā)非常耗時,因此毛皮著色器只能使用逼近的方法。做到這一點(diǎn)的一種方法是在越來越大的同心卷中多次渲染一個表面,并且同時漸縮圖像的細(xì)節(jié)(創(chuàng)建毛發(fā)越靠近端部越稀疏的感覺),這種技術(shù)被稱為“脫殼”或“殼紋理”。
實(shí)現(xiàn)
這個示例程序的著色器使用shell技術(shù)來近似模擬皮毛,頭發(fā)長度可以實(shí)時調(diào)節(jié)。
算法如下:
- 打開alpha混合,渲染物體N次;
- 在每一次渲染物體的時候,通過頂點(diǎn)著色器將模型變大一點(diǎn);
- 同時在每一次渲染的時候?qū)㈩^發(fā)的顏色調(diào)深一點(diǎn)。
頭發(fā)密度通過漫反射紋理的alpha通道控制,斑點(diǎn)圖通常最為有效,它有助于將“胖”像素(大于一個紋素)在皮毛上逐步變小。如果密度圖的像素太小,毛發(fā)看起來像圓柱體而不是錐體,這樣在毛發(fā)末梢就會顯得不夠柔軟。
該細(xì)化算法減掉從密度圖中取出的值,而不是乘以它們進(jìn)行縮放,這看起來像是在毛發(fā)末梢“雕刻出”小細(xì)節(jié)。毛皮的絨毛感正是通過這種變薄的過程獲得。
gl_FragColor= vec4( Color.rgb* NL, saturate( Color.w-g_FurThinning);
景深
景深出現(xiàn)在圖像中可以清晰顯示場景的部分,這是因?yàn)橥哥R只能聚焦在某一個距離。在透鏡每一側(cè)的焦距處,隨著距離增加清晰度逐步降低,這是與針孔鏡頭不同的。針孔鏡頭只讓一條光線通過,因此圖像是非常清晰的,在很長的一段時間里,計算機(jī)生成的圖像看起來就是這種感覺,現(xiàn)在可以通過模擬諸如景深這樣的透鏡效果來達(dá)到更逼真的感覺。
實(shí)現(xiàn)
張濤表示,有幾個不同的方法來實(shí)時達(dá)到景深效果。Qualcomm使用的技術(shù)是通過深度緩沖來區(qū)分清晰的圖像和經(jīng)過模糊的圖像,并將它們混合達(dá)到最終效果。這種技術(shù)具有非常高效的優(yōu)點(diǎn),這是因?yàn)槟:\(yùn)算的開銷是固定的,而且還可以通過使用四分之一屏幕的尺寸的render target進(jìn)行加速。
具體步驟如下:
- 將整個場景渲染到一個離屏render target;
- 選取一個小的render target,對第一步的渲染結(jié)果進(jìn)行模糊處理;
- 利用深度緩沖,將模糊圖像和清晰圖像融合得到最終結(jié)果。
隨深度衰減的霧
霧是當(dāng)云接近地面,能見度下降時發(fā)生的自然現(xiàn)象。能見度的衰減程度正比于觀察者到物體的距離,這種衰減效應(yīng)并不是只在有霧的情況下才有。即使在晴朗的天氣下,遠(yuǎn)處的物體也會呈現(xiàn)衰減,一個典型的例子是地平線上的山脈,雖然空氣非常干凈,但它其中仍然含有顆粒物,而光只有在真空中才不會衰減。
實(shí)現(xiàn)
與景深類似,這種特效依賴于從深度緩沖區(qū)中重建深度值。開發(fā)者并不需要通過變換矩陣的逆矩陣來得到變換之前的完整坐標(biāo),只需要它的深度值。通過深度緩存的值來計算世界坐標(biāo)系里深度值的公式如下:
World Depth = (-Zn * Q) / (DepthVal-Q)
Q = Zf/ (Zf-Zn)
其中,DepthVal是深度緩沖區(qū)的值,Zn是近平面距離,Zf是遠(yuǎn)平面距離。
上帝之光
“上帝之光”是光線經(jīng)過空氣中的顆粒物散射而成的。它們在日出和日落,山川和云層部分遮擋太陽光的時候最常見,也可以通過人工燈光在朦朧混沌的環(huán)境中生成。散射光的計算非常復(fù)雜,但它也可以通過把光線按某種模式進(jìn)行拉伸來近似模擬。這些模式可以通過深度緩沖區(qū)和一些關(guān)鍵信息產(chǎn)生,光線可以通過按照遠(yuǎn)離光源的方向?qū)ο鄳?yīng)模式進(jìn)行模糊處理來創(chuàng)建。
實(shí)現(xiàn)
這是一種基于屏幕空間創(chuàng)建“上帝之光”的技術(shù),它只需要訪問深度緩沖區(qū)和一些臨時render target進(jìn)行處理。
首先,將場景渲染到一個離屏render target,這個render target的深度緩沖區(qū)在下一階段中被當(dāng)做sampler(GLSL中的紋理采樣對象)來生成遮擋物體形狀。接下來縮小得到的圖像并進(jìn)行模糊處理,然后把像素按照光源進(jìn)行radical blur(徑向模糊)處理。
復(fù)古色
復(fù)古色是一種色彩空間,它用來給圖像一種陳舊或古老的感覺。為了達(dá)到好的復(fù)古色效果,Qualcomm使用了1953年用來編碼NTSC視頻的YIQ色彩空間,這需要對RGB和YIQ顏色空間進(jìn)行相互轉(zhuǎn)化。
實(shí)現(xiàn)
可以通過下面的GLSL代碼將RGB變換成Y:
vec3IntensityConverter= vec3(0.299, 0.587, 0.114);
floatY = dot(IntensityConverter, Color.xyz);
通過下面的代碼變換回RGB:
vec4sepiaConvert= vec4(0.191, -0.054, -0.221, 0.0);
gl_FragColor= Y + sepiaConvert;
更多Qualcomm Snapdragon游戲和圖形開發(fā)研討會資料,請點(diǎn)擊這里。
更多Qualcomm開發(fā)內(nèi)容請詳見:Qualcomm開發(fā)者社區(qū)。
評論
查看更多