Unity3D 實用技巧 - Unity Shader 匯總式學習·初探篇

2021-02-19 Unity官方平臺

最近,剛好在溫故練習Unity Shader相關的內容,所以小編這邊就考慮做一些關鍵知識點的匯總整理。那麼咱們就直接進入主題哈!

三大 Shader 程式語言(CG/HLSL/GLSL)

Shader Language的發展方向是設計出在便攜性方面可以和C++、Java等相比的高級語言,「賦予程式設計師靈活而方便的編程方式」,並「儘可能的控制渲染過程」同時「利用圖形硬體的並行性,提高算法效率」。

Shader Language目前主要有3種語言:基於 OpenGL 的 OpenGL Shading Language,簡稱 GLSL; 基於 DirectX 的 High Level Shading Language, 簡稱 HLSL; 基於 NVIDIA 公司的 C for Graphic,簡稱 Cg 語言。

渲染管線也稱為渲染流水線,是顯示晶片內部處理圖形信號相互獨立的並行處理單元。

Gpu流水線上一些可高度編程的階段,而由著色器編譯出來的最終代碼是會在Gpu上運行的;有一些特定類型的著色器,如頂點著色器,片元著色器等。依靠著色器我們可以控制流水線中的渲染細節,例如用頂點著色器來進行頂點變換及傳遞數據,用片元著色器來進行逐像素渲染。

Unity Shader != 真正的Shader

Unity Shader實際上指的就是一個ShaderLab文件。以.shader作為後綴的一種文件。在Unity shader裡面,我們可以做的事情遠多於一個傳統意義上的Shader。在傳統的shader中,我們僅可以編寫特定類型的Shader,例如頂點著色器,片元著色器等。在Unity Shader中,我們可以在同一個文件裡面同時包含需要的頂點著色器和片元著色器代碼。在傳統shader中,我們無法設置一些渲染設置,例如是否開啟混合,深度測試等,這些是開發者在另外的代碼中自行設置的。而Unity shader中,我們通過一行特定的指令就可以完成這些設置。在傳統shader中,我們需要編寫冗長的代碼設置著色器的輸入和輸出,要小心的處理這些輸入輸出的位置對應關係等。而在Unity shader中,我們只需要在特定語句塊中聲明一些屬性,就可以依靠材質來方便的改變這些屬性。而對於模型自帶的數據(如頂點,紋理坐標,法線等),Unity Shader也提供了直接訪問的方法,不需要開發者自行編碼來傳給著色器。

通常採用動態編譯的方式(Cg也支持靜態編譯方式),即在宿主程序運行時,利用Cg運行庫(Cg Runtimer Library)動態編譯Cg代碼。

Cg數據類型:

01  基礎功能類型函數

03  透明效果:只要一個片元的透明度不滿足條件(通常小於某個閾值),那麼就捨棄對應的片元。被捨棄的片元不會在進行任何的處理,也不會對顏色緩衝產生任何影響;否則,就會按照普通的不透明物體來處理,即進行深度測試,深度寫入等等。雖然簡單,但是很極端,要麼完全透明,要麼完全不透明。透明度混合:可以得到真正的半透明效果,它會使當前片元的透明度作為混合因子,與已經儲存在顏色緩衝中的顏色值進行混合麼,得到新的顏色。但是,透明度混合需要關閉深度寫入,這使得我們要非常小心物體的渲染順序。注意:透明度混合只關閉了深度寫入,但沒有關閉深度測試。這表示當使用透明度混合渲染一個片元時,還是會比較它的深度值與當前深度緩衝中的深度值,如果深度值距離攝像機更遠,那麼就不會在進行混合操作。比如一個不透明物體在透明物體前面,我們先渲染不透明物體,可以正常的擋住不透明物體。

常見混合操作類型應用:

A   //正常(Normal)透明度混合 Blend SrcAlpha OneMinusSrcAlpha //柔和相加 Blend OneMinusDstColor OneC   //正片疊底 Blend DstColor Zero  //兩倍相乘 Blend DstColor SrcColorE   //變暗 BlendOp min Blend One One  //變亮 Blend OneMinusDstColor One Blend One OneMinusSrcColor

 //線性減淡 Blend One One

在Unity中,表面著色器的關鍵代碼用Cg/HLSL語言編寫,然後嵌在ShaderLab的結構代碼中使用。使用表面著色器,用戶僅需要編寫最關鍵的表面函數,其餘周邊代碼將由Unity自動生成,包括適配各種光源類型、渲染實時陰影以及集成到前向/延遲渲染管線中等。

01  編寫表面著色器有幾個規則

 表面著色器的實現代碼需要放在CGPROGRAM..ENDCG代碼塊中,而不是Pass結構中,它會自己編譯到各個Pass。

 使用#pragma surface..命令來指明它是一個表面著色器。

A #pragma surface surfaceFunction lightModel [optionalparams]:Surface Shader和CG其他部分一樣,代碼也是要寫在CGPROGRAM和ENDCG之間。但區別是,它必須寫在SubShader內部,而不能寫在Pass內部。Surface Shader自己會自動生成所需的各個Pass。由上面的編譯格式可以看出,surfaceFunction和lightModel是必須指定的。

surfaceFunction通常就是名為surf的函數(函數名可以任意),它的函數格式是固定的:

void surf (Input IN, inout SurfaceOutput o)

void surf (Input IN, inout SurfaceOutputStandard o)

void surf (Input IN, inout SurfaceOutputStandardSpecular o)

 lightModel也是必須指定的。由於Unity內置了一些光照函數——Lambert(diffuse)和Blinn-Phong(specular),因此這裡在默認情況下會使用內置的Lambert模型。當然我們也可以自定義。

 optionalparams包含了很多可用的指令類型,包括開啟、關閉一些狀態,設置生成的Pass類型,指定可選函數等。除了上述的surfaceFuntion和lightModel,我們還可以自定義兩種函數:vertex:VertexFunction和finalcolor:ColorFunction。也就是說,Surface Shader允許我們自定義四種函數。

02  計算函數匯總

 //最重要的計算函數void surf (Input IN, inout SurfaceOutput o)void surf (Input IN, inout SurfaceOutputStandard o)

void surf (Input IN, inout SurfaceOutputStandardSpecular o)

 //頂點修改void vert (inout appdata_full v)

void vert(inout appdata_full v, out Input o)

 //unity老版本(新版本兼容)不包含GI的half4 Lighting (SurfaceOutput s, half3 lightDir, half atten)

half4 Lighting (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)

 //unity新版本(包含GI,要自定義GI函數)half4 Lighting (SurfaceOutput s, UnityGI gi)

half4 Lighting (SurfaceOutput s, half3 viewDir, UnityGI gi)

 //延遲渲染

half4 Lighting_Deferred (SurfaceOutput s, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal)

 //遺留的延遲渲染

half4 Lighting_PrePass (SurfaceOutput s, half4 light)

 //自定義GI

half4 Lighting_GI (SurfaceOutput s, UnityGIInput data, inout UnityGI gi);

 //最終顏色修改void final(Input IN, SurfaceOutput o, inout fixed4 color)void final(Input IN, SurfaceOutputStandard o, inout fixed4 color)

void final(Input IN, SurfaceOutputStandardSpecular o, inout fixed4 color)

兩個結構體就是指struct Input和SurfaceOutput。其中Input結構體是允許我們自定義的。如下表。這些變量只有在真正使用的時候才會被計算生成。在一個貼圖變量之前加上uv兩個字母,就代表提取它的uv值,例如uv_MainTex 。

另一個結構體是(SurfaceOutput、SurfaceOutputStandard和SurfaceOutputStandardSpecular)。我們也可以自定義這個結構體內的變量,自定義最少需要有4個成員變量:Albedo、Normal、Emission和Alpha,缺少一個都會報錯。關於它最難理解的也就是每個變量的具體含義以及工作機制(對像素顏色的影響)。

struct SurfaceOutput {    fixed3 Albedo;    fixed3 Normal;    fixed3 Emission;    half Specular;    fixed Gloss;    fixed Alpha;};

Albedo:我們通常理解的對光源的反射率。它是通過在Fragment Shader中計算顏色疊加時,和一些變量(如vertex lights)相乘後,疊加到最後的顏色上的。(漫反射顏色)

Normal:即其對應的法線方向。只要是受法線影響的計算都會受到影響。

Emission:自發光。會在Fragment 最後輸出前(調用final函數前,如果定義了的話),使用下面的語句進行簡單的顏色疊加:c.rgb += o.Emission;

Specular:高光反射中的指數部分的係數。影響一些高光反射的計算。按目前的理解,也就是在光照模型裡會使用到(如果你沒有在光照函數等函數——包括Unity內置的光照函數,中使用它,這個變量就算設置了也沒用)。有時候,你只在surf函數裡設置了它,但也會影響最後的結果。這是因為,你可能使用了Unity內置的光照模型,如BlinnPhong,它會使用如下語句計算高光反射的強度(在Lighting.cginc裡):float spec = pow (nh, s.Specular*128.0) * s.Gloss;

Gloss:高光反射中的強度係數。和上面的Specular類似,一般在光照模型裡使用。

Alpha:通常理解的透明通道。在Fragment Shader中會直接使用下列方式賦值(如果開啟了透明通道的話):c.a = o.Alpha;

因為涉及的代碼量比較大,小編這邊直接在GitHub上分享通用效果測試的工程。

部分測試效果展示(雪融&火焰流動效果):

項目地址:

https://github.com/haili1234/BasicShaderDemo_01

AnimeKing是Unity社區的價值博主,如果你喜歡本文的話,歡迎點擊「閱讀原文」關注AnimeKing的問答專區。想要你的創意被更多人看見嗎?快快加入Unity社區,在社區內分享經驗,你也有機會獲得Unity官方推薦哦! 博客發布入口:unity.cn/articles - 「寫文章"

長按關注

第一時間了解Unity引擎動向,學習最新開發技巧

 點擊「閱讀原文」,關注AnimeKing的問答專區 

相關焦點

  • Unity 3d可視化節點材質Shader Forge實用教程 初級篇
    大家好,我們前段時發布了免費的shader forge教程,現在更完整,更強大的Shader Forge實用教程來了!
  • 隨風擺動的草叢 — Unity Shader Graph 2D 初探
    個人感想Add,Multiply,Subtract,Divide 以及 One Minus 這些基本節點用處非常廣泛,在學習時須熟練掌握其性質若要僅更改某 N 維矢量的某一維度,先使用 Split 節點將其分離,再使用 Combine 節點組合在一起Gradient Noise 節點可生成均勻自然的隨機噪聲,在模擬風,水波等自然效果時應用廣泛這個著色器瞎胡調參數能調出來好多神奇的效果
  • 在Unity Shader中自定義材質面板
    雖然Unity提供了Custom Shader GUI的方法,但是對於我們只想單純地寫一個shader來說,還要再去改GUI未免太過麻煩。所以我們還是決定直接在shader代碼裡對材質面板進行設定。僅僅只是為了方面演示,從而把所有情況進行了匯總。
  • 博主營地 | Unity3D 實用技巧 - 理論知識庫(一)
    今天小編會把常用的一些理論問題匯總起來,後面可以做一個快速的記憶和學習。原生GUI:http://unity3d.9ria.com/?p=2587NGUI:http://blog.csdn.net/mfc11/article/details/17681429為什麼dynamic font在unicode環境下優於static font。Unicode是國際組織制定的可以容納世界上所有文字和符號的字符編碼方案。
  • Unity PBR Standard Shader 實現詳解 (三)
    上一篇《Shader框架和數據準備》中,我們寫了一個完整的shader,但這個shader的主要內容並不是PBR計算,而是計算前的數據準備
  • Unity 重Built-in到URP函數對應整理
    本文提供重 Built-in 到 URP 的示例總結,希望可以幫助到大家1.開始之前這裡有一些連結可以幫助你深入了解URPUnity URP 官方文檔 https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal%408.1/manual/index.html
  • 新手如何從零開始學習unity
    接下來給大家分享一點經驗與技巧。(一)  首先unity的腳本可以用很多語言來寫,比如java,js,c#,用C#,很多人說自己沒有C#的基礎,其實自己自學也能夠學會,在unity中學會簡單的遊戲邏輯開發,其實不需要太多的C#知識,unity用的VS編輯器其實是在C#裡面調用unity的API,因為它在創建腳本的時候引入了一個 unityEngine的空間,這個空間就是unity的 C# API,那麼新手只需要去學習
  • Unity3D 推薦的7個項目和案例練習
    過高要求自己可能會浪費學習的時間,而且Unity3D是遊戲開發工具,學習匹配的內容以應對面臨的參賽、畢設、工作才是關鍵。學習的階段:初級則是能快速完成、少量插件運用的案例。中級則涉及遊戲框架,綜合運用。高級則涉及網絡開發,伺服器端。
  • Unity Standard Shader 技術分析
    Metallic和unity_ColorSpaceDielectricSpec.a被用來構造reflectivity,之後reflectivity和Albedo共同構造diffColor.而Metallic,Albedo,unity_ColorSpaceDielectricSpec被共同用來構造
  • 【Unity Shader/源碼】實現《塞爾達傳說》卡通海洋
    half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflectDir, 0);half3 sky = DecodeHDR(rgbm, unity_SpecCube0_HDR);fixed3 halfDir = normalize(lightDir + viewDir);fixed3 specular
  • unity 半透明渲染技巧(3則)
    unity 半透明渲染技巧(1):固定深度法半透明渲染排序問題 長期在各種3d引擎存在,這裡將一些針對性技巧。
  • Unity專家都在用的5種方法,教你加快編輯器作業流程
    快捷鍵管理器(Shortcuts Manager):https://docs.unity3d.com/2020.1/Documentation/Manual/ShortcutsManager.html快捷鍵管理器(Shortcuts Manager)你可以將任意鍵位或鍵位組綁定到 Unity 編輯器的命令。
  • Unity3D Shader 新手教程—更好的卡通Shader
    在shader中學習更多不同參考坐標系(空間space)以及其作用。深入學習一個實用的fragment shader。學習矩陣相乘和Unity內建矩陣的使用。準備工作為了實現一個描邊的toon shader,我們需要做的是:描邊有很多方法進行描邊,現在我們採用使用一個Pass改善已有的描邊效果。
  • 一種Shader變體收集和打包編譯優化的思路
    一、什麼是變體  引用Unity官方文檔的解釋:ShaderVariant  https://docs.unity3d.com/ScriptReference/ShaderVariantCollection.ShaderVariant.html  In Unity, many shaders
  • Unity腳本生命周期
    作為一個unity從業人員,相信許多人有時候都會記不住unity的生命周期,記不住沒關係,有了這張圖,一切都是浮雲。
  • 《卡通湖水渲染思路》與《Unity Shader ScreenPos》詳解
    至於給波浪更換顏色,我們容易發現上面功能實現後,儘管我們可以給shader添加一個_FoamColor屬性來控制,但顏色值會和水面顏色混合,並不能得到我們想要的效果。我們可以在Unity內置shader中找到這個函數的內部定義:
  • Unity在線學習平臺,讓夢想不再遙不可及
    學習Unity有時並沒那麼簡單。為了讓學習過程更加輕鬆,我們推出了專門幫助大家學習2D、3d和VR開發的學習平臺:Unity Learn。近期,我們為各位準備了Unity Learn高級版權益放送。點擊連結,加入學習:learn.unity.com初次學習Unity可能會讓人毫無頭緒,該從哪裡開始學呢?「Getting Started with Unity」課程可以為各位指明方向。
  • TA(技術美術)學習網站總結
    文丨馬甲 騰訊互動娛樂 遊戲美術師 一、T部分(技術相關) 1.shadertoy這個網上的所有shader都是GLSL的pixel shaders
  • Unity Shader 基礎教程
    第二部分:渲染管道為了學習Shader,我們將簡單的了解渲染管道,我們將在本教程中討論下面這張圖片:我更加傾向把Shader看做是由一種信息類型(模型數據、顏色等等)到另外一種信息類型(像素/片元)的變換,對象數據繼承與對象本身,例如模型中的點、法線、三角形、UV坐標等等。我們可以把自定義數據/傳遞到shader中使用,顏色、紋理、數字等等這些。
  • 博主營地 | Unity3D 實用技巧 - 基礎數學庫函數學習
    文章雖有些平常乏味,但還是希望大家能留言共同討論學習。如果你喜歡本文的話,在官網 unity.cn 或 Unity Connect App 搜索關鍵詞「數學庫」 就可以找到這篇文章,還可以收藏起來,慢慢學習哦。想要你的創意被更多人看見嗎?快快加入Unity社區,在社區內分享經驗,你也有機會獲得Unity官方推薦哦!