轉載請標明出處http://www.cnblogs.com/zblade/
最近搗鼓了一下金屬光澤的shader的實現,在一些高模展示的時候或者模型的金屬部分的表現的時候,我們需要給模型添加一些金屬光澤,表現出一個模型某些金屬裝備上有一定的反光。今天我主要寫一種基於貼圖實現的金屬反光的效果。不過我沒有添加最終的效果,大家可以自己理解一下做一些貼圖實現各自的模型效果。
Unity5在更新后推出一種基於物理的shader-standard shader,其中給定了一個參數就是metallic 和 smoothness,可以通過添加一個紋理貼圖來實現模型的金屬表現。大概查看了一下源代碼,主要也是對金屬光澤紋理貼圖的采樣,然后分別賦值。主要的操作代碼:
half2 MetallicGloss(float2 uv) { half2 mg; #ifdef _METALLICGLOSSMAP mg = tex2D(_MetallicGlossMap,uv.xy).ra; #else mg = half2(_Metallic,_Glossiness); #endif return mg }
分析其實現的原理,其實就是如果有貼圖,則采樣貼圖的r通道和alpha通道,如果沒有貼圖,則根據參數進行賦值。基於standard提供的思路,我提供了一個類似的實現方式:首先讓美術提供一個黑白透的貼圖,合並在主紋理貼圖中(通過合並,可以減少貼圖數量),其中的通道值可以用來作為金屬光澤的過濾效果。然后讓美術提供一個貼圖,可以用來實現金屬光澤的光照,常見的為圓形光照,所以這兒我就采用的圓形光照來實現。主要的計算是在頂點shader中計算圓形光照的貼圖采樣坐標,所以我主要給出計算的關鍵部分即可:
v2f vert(a2v) { v2f o = (v2f)0; o.pos = mul(UNITY_MATRIX_MVP,v.vertex); o.uv = v.texcoord; //計算球形光源的采樣坐標,在觀察空間中 half3 viewNormal = mul((float3x3)UNITY_MATRIX_MV,v.normal); half4 viewPos = mul(UNITY_MATRIX_MV,v.vertex); half3 projPos = normalize(viewPos.xyz/viewPos.w); half3 reflectVar = reflect(projPos,viewNormal); half m = 2.0 * sqrt(reflectVar.x * reflectVar.x + reflectVar.y*reflectVar.y + (reflectVar.x+1)*(reflectVar.z + 1)); o.sphereUV = fixed2(reflectVar.x/m + 0.5, reflectVar.y/m + 0.5); } fixed4 frag(v2f i):SV_Target { //基本計算 ... half4 mainVar = tex2D(_MainTex,i.uv); //用主貼圖的alpha通道來做金屬光澤的處理 half3 specular = tex2D(_SphereTex,i.sphereUV).rgb * mainVar.a *_SpecPower; // half3 diffuse = mainVar.rgb * _LightColor.rgb * _MainColor.rgb * max(0,dot(v.normal,lightDir)) ; fixed4 color; color.rgb = diffuse + specular; color.a = 1; return color; }
本文實現的基本思路就是用一個基本的圓形貼圖作為金屬光澤的光照,其具體的調節做在住貼圖的alpha通道中采樣,所以關鍵計算是球形的采樣坐標和通道的計算過濾。大家可以測試一下表現效果,基本的金屬光澤就是這樣,大家有什么反饋可以給我留言,共同討論成長~
