日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

shader 编程入门(一)

發布時間:2025/4/16 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 shader 编程入门(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?

?

?

?

本系列文章由@淺墨_毛星云?出品,轉載請注明出處。 ?

文章鏈接:?http://blog.csdn.net/poem_qianmo/article/details/40723789

?

作者:毛星云(淺墨)?? ?微博:http://weibo.com/u/1723155442

郵箱:?happylifemxy@163.com

?

?

[cpp]?view plaincopy print?
  • //-----------------------------------------------【Shader說明】----------------------------------------------??
  • //??????Shader功能:???凹凸紋理顯示+自選邊緣顏色和強度??
  • //?????使用語言:???Shaderlab??
  • //?????開發所用IDE版本:Unity4.5?06f?、Monodevelop?????
  • //?????2014年11月2日??Created?by?淺墨??????
  • //?????更多內容或交流請訪問淺墨的博客:http://blog.csdn.net/poem_qianmo??
  • //---------------------------------------------------------------------------------------------------------------------??
  • ??
  • ??
  • 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???
  • ????{??
  • ????????//渲染類型為Opaque,不透明??
  • ????????Tags?{?"RenderType"?=?"Opaque"?}??
  • ??
  • ????????//-------------------開始CG著色器編程語言段-----------------??
  • ????????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次方
  • ????????}??
  • ??
  • ????????//-------------------結束CG著色器編程語言段------------------??
  • ????????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?
  • //-----------------------------------------------【腳本說明】-------------------------------------------------------??
  • //??????腳本功能:????在場景中和游戲窗口中分別顯示給任意物體附加的文字標簽信息??
  • //??????使用語言:???C#??
  • //??????開發所用IDE版本:Unity4.5?06f?、Visual?Studio?2010??????
  • //??????2014年10月?Created?by?淺墨??????
  • //??????更多內容或交流,請訪問淺墨的博客:http://blog.csdn.net/poem_qianmo??
  • //---------------------------------------------------------------------------------------------------------------------??
  • ??
  • //-----------------------------------------------【使用方法】-------------------------------------------------------??
  • //??????第一步:在Unity中拖拽此腳本到某物體之上,或在Inspector中[Add?Component]->[淺墨's?Toolkit?v1.0]->[ShowObjectInfo]??
  • //??????第二步:在Inspector里,Show?Object?Info?欄中的TargetCamera參數中選擇需面向的攝像機,如MainCamera??
  • //??????第三步:在text參數里填需要顯示輸出的文字。??
  • //??????第四步:完成。運行游戲或在場景編輯器Scene中查看顯示效果。??
  • ??
  • //??????PS:默認情況下文本信息僅在游戲運行時顯示。??
  • //??????若需要在場景編輯時在Scene中顯示,請勾選Show?Object?Info?欄中的[Show?Info?In?Scene?Editor]參數。??
  • //??????同理,勾選[Show?Info?In?Game?Play]參數也可以控制是否在游戲運行時顯示文本信息??
  • //---------------------------------------------------------------------------------------------------------------------??
  • ??
  • ??
  • //預編譯指令,檢測到UNITY_EDITOR的定義,則編譯后續代碼??
  • #if?UNITY_EDITOR??????
  • ??
  • ??
  • //------------------------------------------【命名空間包含部分】----------------------------------------------------??
  • //??說明:命名空間包含??
  • //----------------------------------------------------------------------------------------------------------------------??
  • using?UnityEngine;??
  • using?UnityEditor;??
  • using?System.Collections;??
  • ??
  • //添加組件菜單??
  • [AddComponentMenu("淺墨's?Toolkit?v1.0/ShowObjectInfo")]??
  • ??
  • ??
  • //開始ShowObjectInfo類??
  • public?class?ShowObjectInfo?:?MonoBehaviour??
  • {??
  • ??
  • ????//------------------------------------------【變量聲明部分】----------------------------------------------------??
  • ????//??說明:變量聲明部分??
  • ????//------------------------------------------------------------------------------------------------------------------??
  • ????public?string?text="鍵入你自己的內容?by淺墨";//文本內容??
  • ????public?Camera?TargetCamera;//面對的攝像機??
  • ????public?bool?ShowInfoInGamePlay?=?true;//是否在游戲運行時顯示此信息框的標識符??
  • ????public?bool?ShowInfoInSceneEditor?=?false;//是否在場景編輯時顯示此信息框的標識符??
  • ????private?static?GUIStyle?style;//GUI風格??
  • ??
  • ??
  • ??
  • ????//------------------------------------------【GUI?風格的設置】--------------------------------------------------??
  • ????//??說明:設定GUI風格??
  • ????//------------------------------------------------------------------------------------------------------------------??
  • ????private?static?GUIStyle?Style??
  • ????{??
  • ????????get??
  • ????????{??
  • ????????????if?(style?==?null)??
  • ????????????{??
  • ????????????????//新建一個largeLabel的GUI風格??
  • ????????????????style?=?new?GUIStyle(EditorStyles.largeLabel);??
  • ????????????????//設置文本居中對齊??
  • ????????????????style.alignment?=?TextAnchor.MiddleCenter;??
  • ????????????????//設置GUI的文本顏色??
  • ????????????????style.normal.textColor?=?new?Color(0.9f,?0.9f,?0.9f);??
  • ????????????????//設置GUI的文本字體大小??
  • ????????????????style.fontSize?=?26;??
  • ????????????}??
  • ????????????return?style;??
  • ????????}??
  • ??
  • ????}??
  • ??
  • ??
  • ??
  • ??
  • ????//-----------------------------------------【OnGUI()函數】-----------------------------------------------------??
  • ????//?說明:游戲運行時GUI的顯示??
  • ????//------------------------------------------------------------------------------------------------------------------??
  • ????void?OnGUI(?)??
  • ????{??
  • ????????//ShowInfoInGamePlay為真時,才進行繪制??
  • ????????if?(ShowInfoInGamePlay)??
  • ????????{??
  • ????????????//---------------------------------【1.光線投射判斷&計算位置坐標】-------------------------------??
  • ????????????//定義一條射線??
  • ????????????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;??
  • ????????????//設置字體大小,在26到12之間插值??
  • ????????????float?fontSize?=?Mathf.Lerp(26,?12,?distance?/?10f);??
  • ????????????//將得到的字體大小賦給Style.fontSize??
  • ????????????Style.fontSize?=?(int)fontSize;??
  • ????????????//將文字位置取為得到的光線碰撞位置上方一點??
  • ????????????Vector3?worldPositon?=?raycastHit.point?+?TargetCamera.transform.up?*?distance?*?0.03f;??
  • ????????????//世界坐標轉屏幕坐標??
  • ????????????Vector3?screenPosition?=?TargetCamera.WorldToScreenPoint(worldPositon);??
  • ????????????//z坐標值的判斷,z值小于零就返回??
  • ????????????if?(screenPosition.z?<=?0){return;}??
  • ????????????//翻轉Y坐標值??
  • ????????????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;??
  • ??
  • ??
  • ????????????//----------------------------------【2.GUI繪制】---------------------------------------------??
  • ????????????//開始繪制一個簡單的文本框??
  • ????????????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();??
  • ????????}??
  • ????}??
  • ??
  • ????//-------------------------------------【OnDrawGizmos()函數】---------------------------------------------??
  • ????//?說明:場景編輯器中GUI的顯示??
  • ????//------------------------------------------------------------------------------------------------------------------??
  • ????void?OnDrawGizmos()??
  • ????{??
  • ????????//ShowInfoInSeneEditor為真時,才進行繪制??
  • ????????if?(ShowInfoInSceneEditor)??
  • ????????{??
  • ????????????//----------------------------------------【1.光線投射判斷&計算位置坐標】----------------------------------??
  • ????????????//定義一條射線??
  • ????????????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;??
  • ????????????//設置字體大小,在26到12之間插值??
  • ????????????float?fontSize?=?Mathf.Lerp(26,?12,?distance?/?10f);??
  • ????????????//將得到的字體大小賦給Style.fontSize??
  • ????????????Style.fontSize?=?(int)fontSize;??
  • ????????????//將文字位置取為得到的光線碰撞位置上方一點??
  • ????????????Vector3?worldPositon?=?raycastHit.point?+?Camera.current.transform.up?*?distance?*?0.03f;??
  • ????????????//世界坐標轉屏幕坐標??
  • ????????????Vector3?screenPosition?=?Camera.current.WorldToScreenPoint(worldPositon);??
  • ????????????//z坐標值的判斷,z值小于零就返回??
  • ????????????if?(screenPosition.z?<=?0)?{?return;?}??
  • ????????????//翻轉Y坐標值??
  • ????????????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;??
  • ??
  • ??
  • ??
  • ????????????//----------------------------------【2.GUI繪制】---------------------------------------------??
  • ????????????//開始繪制一個簡單的文本框??
  • ????????????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 编程入门(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。