? ?
?
?
本系列文章由@淺墨_毛星云?出品,轉載請注明出處。 ?
文章鏈接:?http://blog.csdn.net/poem_qianmo/article/details/40723789
?
作者:毛星云(淺墨)?? ? 微博:http://weibo.com/u/1723155442
郵箱:? happylifemxy@163.com
?
?
[cpp] ?view plaincopy print?
?? ?? Shader?"淺墨Shader編程/0.TheFirstShader"??? {?? ???? ????Properties??? ????{?? ????????_MainTex?("【紋理】Texture",?2D)?=?"white"?{}?? ????????_BumpMap?("【凹凸紋理】Bumpmap",?2D)?=?"bump"?{}?? ????????_RimColor?("【邊緣顏色】Rim?Color",?Color)?=?(0.17,0.36,0.81,0.0)?? ????????_RimPower?("【邊緣顏色強度】Rim?Power",?Range(0.6,9.0))?=?1.0?? ????}?? ?? ???? ????SubShader??? ????{?? ???????? ????????Tags?{?"RenderType"?=?"Opaque"?}?? ?? ???????? ????????CGPROGRAM?? ?? ???????? ????????#pragma?surface?surf?Lambert?? ?????????? ???????? ????????struct?Input??? ????????{?? ????????????float2?uv_MainTex; ????????????float2?uv_BumpMap; ????????????float3?viewDir; ????????};?? ?? ???????? ????????sampler2D?_MainTex; ????????sampler2D?_BumpMap; ????????float4?_RimColor; ????????float?_RimPower; ?? ???????? ????????void?surf?(Input?IN,?inout?SurfaceOutput?o)?? ????????{?? ???????????? ????????????o.Albedo?=?tex2D?(_MainTex,?IN.uv_MainTex).rgb;?? ???????????? ????????????o.Normal?=?UnpackNormal?(tex2D?(_BumpMap,?IN.uv_BumpMap));?? ???????????? ????????????half?rim?=?1.0?-?saturate(dot?(normalize(IN.viewDir),?o.Normal)); ?//saturate 把輸入的值限制在0到1之間 ???????????? ????????????o.Emission?=?_RimColor.rgb?*?pow?(rim,?_RimPower); ?//pow(x,y)x的y次方 ????????}?? ?? ???????? ????????ENDCG?? ????}??? ?? ???? ????Fallback?"Diffuse"?? }?? 由于這是第一篇Shader系列文章,已經涉及到很多內容了,所以淺墨不可能展開講解這段代碼的具體思路和寫法,不過已經詳細注釋,大家應該會多少有點明白。隨著稍后文章的深入,這段代碼就顯得很簡單易懂了。
拷貝完成,保存一下這段代碼,unity會自動檢測和編譯被保存的代碼,我只需返回Unity窗口,等待編譯完成即可。若沒有錯誤,在“0.TheFirstShader”的inspector面板中得到的結果應該是有紅色的錯誤提示的。
?
需要注意的是,Shader想要使用到游戲物體上,一般得有個媒介,這個媒介就是我們的老朋友——材質(Material)。我們把Shader作用于材質,接著再把材質對應地作用于給游戲物體,這樣寫的Shader就間接地給物體表面使用了。
?
?
?
而這一層關系,在Unity中完全可以通過點點鼠標,拖動來完成。下面我們就來講一講如何將一個著色程序的結果顯示到物體表面上。
?
知道以上原理了就很簡單了,在“0.TheFirstShader.shader”的同一目錄下創建一個Material。同樣是可以通過Create下拉菜單->Material或者空白處右鍵->create->Material來完成。
?
為了到時候方便對應,我們將這個材質也取名為0.TheFirstShader。
?
?
接著,將0.TheFirstShader.shader拖動到0.TheFirstShader材質身上然后釋放。
?
?
拖動完成后,我們單擊0.TheFirstShader材質,打開他的面板,發現他已經和一開始不一樣了,泛著藍光:
?
?
還沒完,接下來我們還得給這個材質添加兩張紋理圖片。圖片淺墨也已經提前準備好了,在名為Textures01 by QianMo.unitypackage的Unity包中,同樣雙擊這個包然后打開導入到項目中。
?
【Textures01 by QianMo.unitypackage單獨下載請點我】
?
我們在Textures文件夾下找到這兩張紋理,接下來做的就是將他們拖動到0.TheFirstShader材質對應的紋理區域中,如下:
?
?
?
或者點擊這里的Select分別選擇,操作如下:
?
?
兩張紋理選擇完畢后,我們的材質就準備好了,最后的結果,有點黑科技,如各種科幻游戲和電影中發光的礦石,非常炫酷:
?
?
?
?
OK,那么就只剩下最后一步了,就是在場景中創建一個物體,然后將我們做好的材質拖拽到物體身上賦給這個物體就行了。
?
菜單欄【GameObject】->【Create Other】->【Capsule】或者【Create】下拉菜單->【Capsule】來在場景中創建一個膠囊裝的物體。把他拖動到和我們的第一人稱攝像機【First Person Controller】很近的地方,這樣方便觀察,接著就可以把我們的“0.TheFirstShader”材質直接拖拽給場景中的這個膠囊,或者Hierachy面板中【Capsule】名字上就行了,操作如下圖中的箭頭所示:
?
?
?
?
?
經過拖拽,Capsule加上Material后的效果如下:
?
?
?
?
?
?
?
?
4.1?給使用Shader的物體加上文字說明 ?
?
?
為了以后介紹多個Shader寫法時能更清晰更方便,淺墨專門在QianMo’s Toolkit中做了一個可以在場景中和游戲窗口中分別顯示附加給任意物體文字標簽信息的工具腳本,叫做ShowObjectInfo,其詳細注釋的代碼如下:
?
?
?
[csharp] ?view plaincopy print?
?? ?? ?? ?? #if?UNITY_EDITOR?????? ?? ?? using?UnityEngine;?? using?UnityEditor;?? using?System.Collections;?? ?? [AddComponentMenu("淺墨's?Toolkit?v1.0/ShowObjectInfo")]?? ?? ?? public?class?ShowObjectInfo?:?MonoBehaviour?? {?? ?? ???? ???? ???? ????public?string?text="鍵入你自己的內容?by淺墨"; ????public?Camera?TargetCamera; ????public?bool?ShowInfoInGamePlay?=?true; ????public?bool?ShowInfoInSceneEditor?=?false; ????private?static?GUIStyle?style; ?? ?? ?? ???? ???? ???? ????private?static?GUIStyle?Style?? ????{?? ????????get?? ????????{?? ????????????if?(style?==?null)?? ????????????{?? ???????????????? ????????????????style?=?new?GUIStyle(EditorStyles.largeLabel);?? ???????????????? ????????????????style.alignment?=?TextAnchor.MiddleCenter;?? ???????????????? ????????????????style.normal.textColor?=?new?Color(0.9f,?0.9f,?0.9f);?? ???????????????? ????????????????style.fontSize?=?26;?? ????????????}?? ????????????return?style;?? ????????}?? ?? ????}?? ?? ?? ?? ?? ???? ???? ???? ????void?OnGUI(?)?? ????{?? ???????? ????????if?(ShowInfoInGamePlay)?? ????????{?? ???????????? ???????????? ????????????Ray?ray?=?new?Ray(transform.position?+?TargetCamera.transform.up?*?6f,?-TargetCamera.transform.up);?? ???????????? ????????????RaycastHit?raycastHit;?? ???????????? ????????????collider.Raycast(ray,?out?raycastHit,?Mathf.Infinity);?? ?????????????? ???????????? ????????????float?distance?=?(TargetCamera.transform.position?-?raycastHit.point).magnitude;?? ???????????? ????????????float?fontSize?=?Mathf.Lerp(26,?12,?distance?/?10f);?? ???????????? ????????????Style.fontSize?=?(int)fontSize;?? ???????????? ????????????Vector3?worldPositon?=?raycastHit.point?+?TargetCamera.transform.up?*?distance?*?0.03f;?? ???????????? ????????????Vector3?screenPosition?=?TargetCamera.WorldToScreenPoint(worldPositon);?? ???????????? ????????????if?(screenPosition.z?<=?0){return;}?? ???????????? ????????????screenPosition.y?=?Screen.height?-?screenPosition.y;?? ?????????????? ???????????? ????????????Vector2?stringSize?=?Style.CalcSize(new?GUIContent(text));?? ???????????? ????????????Rect?rect?=?new?Rect(0f,?0f,?stringSize.x?+?6,?stringSize.y?+?4);?? ???????????? ????????????rect.center?=?screenPosition?-?Vector3.up?*?rect.height?*?0.5f;?? ?? ?? ???????????? ???????????? ????????????Handles.BeginGUI();?? ???????????? ????????????GUI.color?=?new?Color(0f,?0f,?0f,?0.8f);?? ????????????GUI.DrawTexture(rect,?EditorGUIUtility.whiteTexture);?? ???????????? ????????????GUI.color?=?new?Color(1,?1,?1,?0.8f);?? ????????????GUI.Label(rect,?text,?Style);?? ???????????? ????????????Handles.EndGUI();?? ????????}?? ????}?? ?? ???? ???? ???? ????void?OnDrawGizmos()?? ????{?? ???????? ????????if?(ShowInfoInSceneEditor)?? ????????{?? ???????????? ???????????? ????????????Ray?ray?=?new?Ray(transform.position?+?Camera.current.transform.up?*?6f,?-Camera.current.transform.up);?? ???????????? ????????????RaycastHit?raycastHit;?? ???????????? ????????????collider.Raycast(ray,?out?raycastHit,?Mathf.Infinity);?? ?????????????? ???????????? ????????????float?distance?=?(Camera.current.transform.position?-?raycastHit.point).magnitude;?? ???????????? ????????????float?fontSize?=?Mathf.Lerp(26,?12,?distance?/?10f);?? ???????????? ????????????Style.fontSize?=?(int)fontSize;?? ???????????? ????????????Vector3?worldPositon?=?raycastHit.point?+?Camera.current.transform.up?*?distance?*?0.03f;?? ???????????? ????????????Vector3?screenPosition?=?Camera.current.WorldToScreenPoint(worldPositon);?? ???????????? ????????????if?(screenPosition.z?<=?0)?{?return;?}?? ???????????? ????????????screenPosition.y?=?Screen.height?-?screenPosition.y;?? ?????????????? ???????????? ????????????Vector2?stringSize?=?Style.CalcSize(new?GUIContent(text));?? ???????????? ????????????Rect?rect?=?new?Rect(0f,?0f,?stringSize.x?+?6,?stringSize.y?+?4);?? ???????????? ????????????rect.center?=?screenPosition?-?Vector3.up?*?rect.height?*?0.5f;?? ?? ?? ?? ???????????? ???????????? ????????????Handles.BeginGUI();?? ???????????? ????????????GUI.color?=?new?Color(0f,?0f,?0f,?0.8f);?? ????????????GUI.DrawTexture(rect,?EditorGUIUtility.whiteTexture);?? ???????????? ????????????GUI.color?=?new?Color(1,?1,?1,?0.8f);?? ????????????GUI.Label(rect,?text,?Style);?? ???????????? ????????????Handles.EndGUI();?? ?? ????????}?? ?? ????}?? ?? }?? ?? #endif?? ?
?
這個腳本的用法倒是很簡單,在代碼的說明部分已經詳細寫出,在這里我們再列出一遍:
?
第一步:在Unity中拖拽此腳本到某物體之上,或在Inspector中[Add Component]->[淺墨's Toolkit v1.0]->[ShowObjectInfo]
第二步:在Inspector里,ShowObject Info 欄中的TargetCamera參數中選擇需面向的攝像機,如Main Camera,FirstPerson Controller等
第三步:在text參數里填需要顯示輸出的文字。
第四步:完成。運行游戲或在場景編輯器Scene中查看顯示效果。
?
?
也就是拖拽ShowObjectInfo腳本或者直接添加組件給需要附加文字的物體,然后在Inspector中輸入需要顯示的文字,然后選擇其面對的攝像機就可以了。
?
?
?
我們將ShowObjectInfo腳本拖拽給上文中剛剛變得炫酷外形黑科技的Capsule:
?
那么他在Inspector就多了一個“ShowObject Info(Script)”組件,將該組件的Text項中填上“凹凸紋理+邊緣發光效果”,TargetCamera中填上First Person Controller的子物體Main Camera:
?
?
?
最后,得到的效果就是這樣:
?
?
?
?
?
?
?
?
?
?
?
?
五、總結、配套資源&最終工程下載 ?
?
?
?
好了,本篇的文章到這里就大概結束了。
?
今天講的內容還是非常多的,對于新接觸Unity的朋友們來說或許還得好好消化消化,而熟悉Unity的朋友應該很快就可以看懂,或者覺得淺墨講了一堆廢話,orz。
?
這篇文章的內容說白了就非常簡單,也就是新建工程,然后導入三個淺墨提前準備好的unitypackage游戲資源,點一點鼠標拖動拖動腳本,新建一個Shader,寫點代碼,再創建一個Material,Shader賦給這個Material,最后創建一個膠囊狀Capsule,Material賦給這個Capsule,點運行查看最終效果。一切,就是這么簡單。:)
?
?
本文配套的三個unitypackage打包請點擊此處下載:
?
【淺墨Unity3D Shader編程】之一 配套的三個unitypackage打包下載
?
?
?
本文最終的Unity工程請點擊此處下載:
?
【淺墨Unity3D Shader編程】之一 配套Unity工程
?
?
?
最后放幾張最終的場景美圖吧。
?
站在亭子上看世界:
?
?
?
逼真的光暈:
?
?
?
漂亮的天空:
?
?
?
?
亂真的水面:
?
?
?
藍天和草地樹木交相輝映:
?
?
?
?
OK,全文到此結束。
新的游戲編程之旅已經開啟,下周一,我們不見不散。
?
轉載于:https://www.cnblogs.com/lifesteven/p/5613101.html
總結
以上是生活随笔 為你收集整理的shader 编程入门(一) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。