您好,登錄后才能下訂單哦!
Unity噴墨效果Shader實現是怎樣的,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
對于游戲中使用的類似噴墨效果,在射擊類游戲中經常使用比如玩家射擊的子彈會在墻上出現類似噴墨效果,效果如下所示:
在默認情況下,屏幕的整個Alpha通道都是黑色的,直到玩家開始噴射油墨,才會使被油墨濺到區域的Alpha通道變為白色。然后圖像效果就是其原有顏色與灰度進行混合。
實現方式如下所示:
從上圖可以看出,使用Projector將噴漆繪制到物體表面并創建顏色遮罩。每個Projector都使用程序化動態生成,在子彈(空中飛行的白點)接觸到某個表面時進行初始化。Projector帶有一個盒式碰撞體,當子彈落在Projector上時,不會初始化新的Projector,而是讓原先的Projector變大。這樣漆量會變多,而場景中的Projector數量卻保持不變。
默認情況下,Unity標準著色器會為所有不透明對象的Alpha通道寫入1。所以下面使用自定義著色器來替換Unity標準著色器。新建一個標準表面著色器,將其表面函數替換為如下:
void surf(Input IN, inout SurfaceOutputStandard o) { //Albedo 來自帶顏色的紋理 fixed4 c=tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = 0; //只添加此行 }
下面這行很重要,用于避免Unity更改自定義的Alpha值。將#pragma那行代碼改為如下:
CGPROGRAM #pragma surface surf Standard fullforwardshadows keepalphs
注意,該技巧不可用于Unity中的延遲渲染管線,因為它重寫了G-Buffer中的Alpha通道來存儲遮罩數據。
當子彈撞擊某個表面時就會在撞擊處動態生成Unity Projector。這些Projector帶有自定義材質與自定義著色器。材質紋理是一張帶有Alpha通道噴濺形狀圖,本文示例使用的紋理如下圖:
注意,紋理導入設置中要將Wrap Mode設為“Clamp”而非“Repeat”。用于Projector材質的著色器從Unity提供的ProjectorLight修改而來,代碼如下:
Shader "Projector/ProjectAlpha" { Properties { _ShadowTex("Cookie", 2D) = "gray"{} } Subshader{ Tags{"Queue" = "Transparent"} Pass { ZWrite Off Blend Zero One,One One Offset -1, -1 CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fog #include "UnityCG.cginc" struct Input { float4 vertex : LagPosition; float3 normal : NORMAL; }; struct v2f { float4 uvShadow : TEXCOORD0; UNITY_FOG_COORDS(2) float4 pos : SV_POSITION; fixed nv : COLOR0; }; float4x4 unity_Projector; float4x4 unity_ProjectorClip; v2f vert(Input v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uvShadow = mul(unity_Projector, v.vertex); UNITY_TRANSFER_FOG(o, o.pos); float3 normView = normalize(float3(unity_Projector[2][0], unity_Projector[2][1], unity_Projector[2][2])); float nv = dot(v.normal, normView); o.nv = nv < 0 ? 1: 0; return o; } sampler2D _ShadowTex; sampler2D _FalloffTex; fixed4 frag(v2f i) : COLOR { fixed4 texS = tex2DProj(_ShadowTex, UNITY_PROJ_COORD(i.uvShadow)); fixed4 res = fixed4(1,1,1,texS.a); res.a = i.nv; UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(1,1,1,1)); return res; } EDNCG } } }
再介紹一下,關于混合的部分:
當著色器計算某個像素的顏色時,該顏色必須作用于屏幕上該點已經存在的像素顏色之上。默認情況下,新的像素會完全覆蓋原有像素,但新像素也可以與原有像素進行混合。混合通常用于讓對象呈透明或半透明效果,當然也可以實現很多其它的炫酷特效。
關鍵字Blend可以包含在Subshader或Pass標簽中,甚至對同一個著色器的不同Pass進行混合。添加Blend關鍵字后,必須寫入混合因子。混合因子如下:
Src指向著色器用于計算的顏色。Dst指向屏幕上已有的像素顏色。著色器用于計算的顏色會與第一個因子相乘,而屏幕上已有顏色會與第二個因子相乘。將兩個結果相加,就是最終寫到屏幕的顏色。
所以"Blend SrcAlpha One"會將自身Alpha值與當前著色器計算的顏色相乘,此時屏幕上的顏色暫未改動。然后再將屏幕顏色計算后的結果與前者相加。還可以使用逗號分隔兩組因子,逗號前的混合選項用于計算顏色,逗號后的混合選項僅計算Alpha通道。可以查閱Unity文檔了解更多關于混合的內容。
用于Projector的著色器就是“Blend Zero One, One One”,“Zero One”移除了飛濺紋理的顏色,使用子彈所飛濺到的表面顏色。“One One”將飛濺物的Alpha值與表面Alpha值相加。
現在使用上面的著色器與材質來生成Projector,應該將場景視圖的Alpha通道設為白色。
現在可以隨意修改Alpha通道,但還未達到最終效果。下面利用Alpha遮罩來創建游戲所需的圖像特效。
首先,創建要使用圖像特效的著色器。在Unity中新建默認的Image Effect Shader,然后將片段代碼替換為如下:
fixed4 frag(v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); fixed3 bnw = dot(col.rgb, float3(0.3,0.59,0.11)); col.rgb = lerp(bnw, col.rgb, col.a); return col; }
可以隨意更改bnw(Black&White)變量以達到理想的混合效果。最后還需要新建腳本來運行該圖像特效。腳本非常簡單,代碼如下:
using System.Collections; using System.Collections.Generic; using UnityStandardAssets.ImageEffectBase; [ExecuteInEditMode] [ImageEffectAllowedInSceneView] public class ALphaColorSwitch : ImageEffectBase{ void OnRenderImage(RenderTexture source, RenderTexture destination) { Graphics.Blit (source, destination, material); } }
注意,這里用到了ImageEffectBase,該資源在Unity標準資源庫中(Unity 5.5及以上版本推薦使用Post Processing Stack資源庫代替ImageEffects)。導入標準資源庫后,將腳本綁定到相機(確保將相機的渲染模式設為Forward)上,并將公共的著色器變量設為前面提到的著色器。
到此就可以向場景中噴射油墨啦!
關于Unity噴墨效果Shader實現是怎樣的問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。