banner
Matrix

Matrix

Abyss
email
github

Unity Shader 學習筆記 1

本文從 0 開始學習 Unity Shader

先新建一個 Unity Shader (Surface Shader)開始:

Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        _Color ("顏色", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("光滑度", Range(0,1)) = 0.5
        _Metallic ("金屬感", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // 基於物理的標準光照模型,並在所有光源類型上啟用陰影
        #pragma surface surf Standard fullforwardshadows

        // 使用著色器模型3.0目標,以獲得更好看的光照效果
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // 為此著色器添加實例化支持。您需要在使用該著色器的材質上勾選“啟用實例化”。
        // 有關實例化的更多信息,請參見 https://docs.unity3d.com/Manual/GPUInstancing.html。
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // 在這裡放置更多每個實例的屬性
        UNITY_INSTANCING_BUFFER_END(Props)

        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 = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

這段 Unity Shader 代碼定義了一個自定義的 Surface Shader,它用於渲染具有基本物理屬性(如顏色、光澤度、金屬感)的表面。讓我們詳細解釋一下各個部分:

Shader 聲明#

Shader "Custom/NewSurfaceShader"
這行聲明了一個新的 Shader,並給它命名為 "Custom/NewSurfaceShader"。這個名字可以在 Unity 的材質編輯器中找到並應用於遊戲對象。

image

Properties#

這塊代碼定義 Shader 從外部接收的參數,以便在 Inspector 面板修改。

為了看到具體結果,首先要先創建一個新的材質,然後在材質的 Inspector 面板的 Shader 中選擇剛才創建的 Shader,隨後可以看到 Shader 代碼中 Properties 中定義的屬性:

image

再來分析一下 Properties 的語法:

_PropertyName ("顯示名稱", PropertyType) = DefaultValue

對應的可以解釋 Shader 代碼中的聲明:

Properties {
    _Color ("顏色", Color) = (1,1,1,1) // 定義了一個默認為白色的顏色屬性。
    _MainTex ("Albedo (RGB)", 2D) = "white" {} // 定義了一個2D紋理屬性,默認使用白色紋理。
    _Glossiness ("光滑度", Range(0,1)) = 0.5 // 定義了一個在0到1之間的浮點數屬性,表示表面的光滑度。
    _Metallic ("金屬感", Range(0,1)) = 0.0 // 定義了一個在0到1之間的浮點數屬性,表示材料的金屬感。
}

SubShader#

SubShader塊定義了實際的渲染邏輯。如果一個 Shader 包含多個 SubShader,Unity 會根據硬體和性能從中選擇最合適的一個執行。

  • Tags { "RenderType"="Opaque" }:指定了這個 Shader 是用於不透明物體的渲染。
  • LOD 200:設置了 Shader 的細節級別(Level Of Detail),影響渲染性能和質量。

CGPROGRAM#

CGPROGRAMENDCG之間是實際的 Shader 代碼,使用Cg/HLSL語言編寫。

#pragma surface surf Standard fullforwardshadows

聲明該 Shader 的光影

在 Unity 的 Shader 代碼中,#pragma 指令用於向編譯器提供特定的編譯指令。

#pragma surfaceasdasd
這部分是 Surface Shader 特有的,它告訴 Unity 這是一個 Surface Shader,並開始定義這個 Shader 的屬性和行為。

surf是該 Shader 代碼後面自定義的一個函數,Unity 在渲染每個像素時,會調用這個函數來確定各種屬性,例如光澤 顏色等。

standard 表明使用 Unity 中的 PBR(physically based rendering)模型,這是一種常用的渲染模型。

fullforwardshadows是一個選項,它啟用了在前向渲染路徑中的全部陰影投射。這意味著無論是定向光、點光源還是聚光燈,所有類型的光源都會在 Shader 中正確地計算陰影。這對於需要在遊戲或場景中實現複雜光照和陰影效果的應用特別重要。不使用這個選項可能會在某些光源下得到不準確的陰影渲染,或者是陰影質量下降。

#pragma target 3.0:指定了 Shader 模型 3.0,以獲得更好的光照效果。

sampler2D _MainTex; 定義了一個 2D 紋理採樣器,在 Shader 中,紋理採樣用於從紋理中讀取像素數據,通常存儲基礎的漫反射貼圖。

在 CG 中,貼圖一般是 3 通道或者 4 通道(取決於是否有 A,每個通道 8bit)的內存,Sampler 幫助我們自動計算每個像素和坐標的對應關係以及偏移。

input 結構體定義了輸入的數據結構,具體而言,input 定義了輸入的數據結構 uv_MainTex (紋理坐標) 是 float2 類型。

half _Glossiness 定義了一個half變量(佔用內存較少的浮點型),這個變量用於控制材質的光滑度。類似地,定義_Metallic變量控制材質的金屬度。_Colorfixed4類型(低精度四元數),用來存儲材質的基本顏色。

下面兩行關於 GPU 實例化支持的指令,pass。

surf函數是 shader 的核心,這個函數計算材質表面的屬性,即前面定義的一系列變量,還負責對材質進行著色。

surf 函數#

在 Unity 的 Surface Shader 中,surf 函數是一個核心組件,用於定義材質表面的視覺屬性。這個函數處理輸入,並將結果輸出到一個特定的數據結構中,這個結構描述了物體表面如何與光線互動。

執行過程
輸入:surf 函數接收一個 Input 結構體作為參數,這個結構體包含了所有必要的輸入數據,例如 UV 坐標、法線等,具體取決於 Shader 的定義。在你的代碼示例中,Input 結構體包含了 uv_MainTex,即主紋理的 UV 坐標。

多次調用:在渲染過程中,Unity 對每個像素或每個頂點調用 surf 函數。對於每個像素,它使用相應的輸入數據(如紋理坐標和其他可用的頂點數據)計算表面的輸出。

輸出:輸出是通過修改 surf 函數的第二個參數實現的,這是一個可寫的 SurfaceOutputStandard 結構體。這個結構體包含了決定像素最終外觀的各種屬性,如反照率(Albedo)、金屬感(Metallic)、光滑度(Smoothness)和透明度(Alpha)。這些屬性基於物理屬性來模擬真實世界材質的表現。

影響材質效果:surf 函數輸出的數據被 Unity 的渲染引擎使用,結合光照模型和場景的光照條件,來計算最終的像素顏色。這樣,每個像素的顏色都是根據其具體的表面特性和場景中的光照條件動態計算的。


以上就是一個新建 shader 的所有代碼內容。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。