《Splatoon 2》繪製效果的簡單實現

最終實現效果如下:

參考資料實現效果如下:

問題傳送門:如何用unity實現switch噴射戰士2(Splatoon 2)中的效果 ?

參考資料傳送門:How do they do the painting in Splatoon?

===================================================

好吧,長話短說:

這個實現效果其實很簡單就是:

1.通過在C#中通過射線獲取物體表面的點

2.修改網格附近的頂點的顏色

3.Shader通過顏色的透明度大小,決定要顯示被塗抹的顏色還是顯示紋理本身的顏色。

第一步很簡單,第二步的核心代碼如下:

public void ApplyPaint(Vector3 position, float innerRadius, float outerRadius, Color color) { //將坐標轉化為本地坐標 Vector3 center = transform.InverseTransformPoint(position); //將外半徑轉化為本地坐標 float outerR = transform.InverseTransformVector(outerRadius * Vector3.right).magnitude; //將內半徑轉化為本地坐標 float innerR = innerRadius * outerR / outerRadius; //計算內外半徑平方待比較用 float innerRsqr = innerR * innerR; float outerRsqr = outerR * outerR; //計算差值係數 float tFactor = 1f / (outerR - innerR); for (int i = 0; i < vertices.Count; i++) { Vector3 delta = vertices[i] - center; float dsqr = delta.sqrMagnitude; //拿到距離的平方 //如果大於外半徑則不理會 if (dsqr > outerRsqr) continue; float a = colors[i].a; colors[i] = new Color(color.r, color.g, color.b, colors[i].a); //小於內半徑則把頂點顏色透明度設置為不透明,觸發shader中的比較 if (dsqr < innerRsqr) { colors[i].a = 1; } else { //拿到距離 float d = Mathf.Sqrt(dsqr); float t = 1f - (d - innerR) * tFactor; if (t >= colors[i].a) { colors[i].a = t; } } } mesh.colors = colors; }

第三步分別做如下處理:

1.透明度大於主染色門檻,判斷是顏料的主區域,這一區域必須以塗料顏色為主。

1.1*在1的基礎上,判斷是否大於邊緣染色門檻,是的話就以顏料RGB值與噪音混合一下;如果不是,就拿顏料RGB、紋理RGB和噪音混合:

float paint = IN.color.a;half4 c = tex2D (_MainTex, IN.uv_MainTex);...float edgeDelta = paint - noise;//大於染色門檻,則是主區域的著色if (edgeDelta >= _Threshold) { if (edgeDelta > _EdgeThreshold) o.Albedo = IN.color.rgb * 0.9 + float3(1,1,1) * noise * 0.1; //IN.color.rgb * 0.95 + float3(1,1,1) * noise * 0.05; else o.Albedo = (IN.color.rgb * (edgeDelta / 0.2) + c.rgb * (1 - edgeDelta / 0.2)) * 1 + float3(1,1,1) * noise * 0.2; o.Gloss = 1; o.Specular = 1; o.Alpha = 1;}

2.如果透明度大於次染色門檻,由噪音圖片決定是否著色:

else if (edgeDelta > _SecondThreshold){ half noiseTex = tex2D(_NoiseTex, IN.uv_MainTex); if (noiseTex.r > _NoiseThreshold) {o.Albedo = IN.color.rgb * 0.9 + float3(1,1,1) * noise * 0.1;

3.剩餘的就照常取紋理就好。

=======================================

人生的第一個Shader,我用了將近8小時來寫,寫完一數,有效代碼長度還不到50行。弱雞是這樣的……

要習慣……


推薦閱讀:

Instagram濾鏡,影視級調色演算法實現
2D遊戲開發時有那些驚艷的效果是一定要學會著色器(shader)編程?
編寫Unity Shader的時候,語義POSITION和SV_POSITION的區別?
Shader model 5.0 的片段著色器能不能得到該片段所在的三角圖元實際光柵化後有多少像素?

TAG:Unity游戏引擎 | 游戏开发 | shader |