需求變更
我哩個天天,需求這東西就是你做完一個又回有新的一個,做了個普通的,就會讓你做高級的。
這不之前做了循環長箭頭,領導就說要分段顯示,怎么個分段顯示咧?能夠顯示兩種顏色的箭頭,一種是你還沒有走完的路,一種是已經走完的。恩,需求很簡單,容我思考下人生。
看來又要學習啦
對unity的shader一直沒有深入研究,到目前為止都是停留在能用就行的階段。復雜一點的shader基本也用可視化的編輯插件進行處理,手打的也就能寫寫固定功能的shader。可視化的插件很方便,所見即所得,缺點是需要微調的時候就麻煩了。固定著色器功能再多也有限,到頭來寫Shader還是離不開HLSL和CG語言直接寫。當然在Unity中,unity為我們包裝了ShaderLab的殼子為我們方便的實現需要的功能,同時不至于代碼過于的冗余和晦澀。
同樣的Unity提供了官方文檔,內容嘛,老規矩全而不細,需要的朋友出門左轉,可以翻閱一下:Unity ShaderLab 官方文檔
先想想問題,別急著動手
當前的需求是分段顯示兩種不同顏色的箭頭,用于區分哪一部分是已經走過的路線,哪一部分是為走過的路線。在這個需求中需要處理兩個貼圖,用來表現不同的狀態。
方法一:
常規情況下可以直接制作兩個箭頭的組件,因為在第一版的基礎下已經實現了從點A到點B的箭頭。分段顯示只要處理點A到中間點A'和A'到B兩段就行。
這樣做表面上看起來沒有任何問題,實際上也沒有任何問題!就是有一點比較麻煩,首先,你需要處理兩個箭頭,其次,A'點在實際游戲中是移動的,因為人是不斷移動的,你就需要不停的調整兩個箭頭的長度,也就是需要控制兩個變量。這種雖然能有但是哪里又有點不對的感覺就好像...
方法二:
不就是顯示兩個材質嘛,直接shader處理,把中間點A'當做屬性值傳入到shader中,然后就行判斷,未到A'點的顯示材質一,A'點之后的顯示材質二,這樣就只需要維護一個箭頭,同時移動的時候只需要改shader中傳入的A'參數就可以了。恩,很完美,方便使用,一般用起來方便懶的方法,寫起了都有些費勁。別問我怎么知道的~~
想好了就動手做
目測原來會的固定功能shader無法實現判斷的功能,需要直接寫頂點著色器和片段著色器,基礎有限就有惡補。涉及到圖形圖像shader這方面的資料少之又少,中文的就更不多了。推薦大家兩個不過的博客,兩位大佬也都是出過書的,大家也可以看看:
淺墨的Unity3D
candycat
Shader的實現代碼不算復雜,該有的東西也都有,注釋也寫的很清楚,算是個不錯的入門作業,需要的同學可以拿走,記得順手點個贊哦
Shader "Custom/雙色Shader"
{
//屬性
Properties
{
_MainTex("MainTex(RGBA)", 2D) = "white" {} //材質1
_GrayTex("GrayTex(RGBA)",2D) = "white" {} //材質2
_CurrentPos("CurrentPos",Range(0,1)) = 1 //當前位置
}
SubShader
{
LOD 100
Cull Off Lighting Off ZWrite Off ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Tags
{
"Queue" = "Overlay"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass{
CGPROGRAM
#pragma vertex vert //定義頂點著色器處理單元
#pragma fragment frag //定義片段著色器處理單元
#include "UnityCG.cginc"
//變量定義
uniform sampler2D _MainTex;
uniform sampler2D _GrayTex;
uniform fixed _CurrentPos;
uniform fixed4 _MainTex_ST;
//頂點輸入結構
struct vertexInput {
fixed4 vertex : POSITION;
fixed4 texcoord0 : TEXCOORD0;
};
//片段輸入結構(頂點輸出)
struct fragmentInput {
fixed4 position : SV_POSITION;
fixed4 texcoord0 : TEXCOORD0;
fixed2 uv:_MainTex_ST;
};
//頂點著色器處理單元
fragmentInput vert(vertexInput i) {
fragmentInput o;
o.position = UnityObjectToClipPos(i.vertex); //轉換物體空間到相機空間
o.texcoord0 = i.texcoord0;
o.uv = TRANSFORM_TEX(i.texcoord0, _MainTex); //應用材質的Tilling和offset屬性
return o;
}
//片段著色器處理單元
fixed4 frag(fragmentInput i) : SV_Target{
//判斷
if(i.texcoord0.y >= _CurrentPos)
return tex2D(_GrayTex, i.uv);
else
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}
為了優化性能,同時游戲里的需求也不高,所有精度都為fixed,具體項目中可以更具需要進行實際修改。
結語
該學的東西還是要學,總是無法回避的,誰讓選擇了程序員這條路,就是一條終生學習的路。路上的兄弟共勉之。加油。