【Unity Shader】Shader基礎


Chapter3 Unity Shader 基礎

概述

在Unity需要材質(Material)與Unity Shader配合使用來達到滿意的效果。

  1. Unity Shader定義了渲染需要的各種代碼(頂點着色器與片元着色器等),屬性(使用哪些紋理)和指令(渲染和標簽設置),我們通過材質調節這些屬性,再賦給相應的模型。
  2. 材質:配合GameObject的Mesh或者Particle Systems組件來工作。
  3. Unity Shader:
    1. Standard Surface Shader:使用了一個包含了標准光照模型的表面着色器模板
    2. Unlit Shader: 一個不包含光照但是包含霧效的基本頂點/片元着色器
    3. Image Effect Shader: 為實現屏幕后處理提供基本模板
    4. Compute Shader: 借助GPU的並行性來進行一些與渲染流水線無關的計算

ShaderLab

一款專門為Unity Shader服務的語言。

Properties 屬性
  1. 語句格式:Name("display name",PropertyType)=DefaultValue
  2. 支持的屬性類型:
    | 屬性類型 | 定義語法 ||
    |:--------😐:--------:||
    |Int|number||
    |Float|number|
    |Range(min,max)|number|
    |Color|(number,number,number,number)|
    |Vector|(number,number,number,number)|
    |2D|"defaulttexture"{}|
    |Cube|"defaulttexture"{}|
    |3D|"defaulttexture"{}|

Unity允許重載默認的材質編輯面板以提供更多的自定義數據類型。 關鍵詞“Custom Shader GUI”
Properties語義塊的作用僅僅是為了讓這些屬性可以出現在材質面板里

SubShader:表面着色器
  1. 語句格式
SubShader{
	//可選的,標簽
	[Tags]

	//可選的,狀態
	[RenderSetup]

	//一次完整的渲染流程,如果pass的數目過多,會造成渲染性能的下降。
	Pass{
	}
	...
}
  1. RenderSetup 狀態:關於渲染狀態的設置指令
    | 狀態名稱 | 設置指令 |解釋|
    |:--------😐:--------😐:----😐
    | Cull |Cull Back/Front/Off| 剔除模式:剔除背面/正面/關閉剔除|
    |ZTest|ZTest Less Greater/LEqual/GEqual/Equal/NotEqual/Always|設置深度剔除時使用的函數|
    |ZWrite|ZWrite On/Off|關閉/開啟深度寫入|
    |Blend|Blend SrcFactor DstFactor|開啟並設置混合模式|

  2. Tags 標簽:希望怎樣以及何時渲染這個對象Tags{"TagName1"="Value1" "TagName2"="Value2"}
    | 標簽類型 | 說明 |
    |--------|--------|
    | Queue | 控制渲染順序,指定該物體屬於哪一個渲染隊列 |
    |RenderType|對着色器進行分類,可以用於着色器替換功能|
    |DisableBatching|指明是否對該SubShader使用批處理|
    |ForceNoShadowCasting|控制使用該SubShader的物體是否會投射陰影|
    |IgnoreProjector|控制使用該SubShader的物體是否受projector(投影儀?)的影響|
    |CanUseSpriteAtlas|當該SubShader是用於sprite時,將該標簽設為“false”|
    |PreviewType|指明材質面板將如何預覽該材質。默認材質下,材質將顯示為一個球形,我們可以通過將該標簽的值設為“Plane”“SkyBox”來改變預覽類型|
    上述標簽可以在SubShader中聲明,而不可以在Pass塊中聲明,Pass塊有專屬於自己的標簽。

  3. Pass語義塊:

    Pass{
        [Name]
        [Tag]
        [RenderSetup]
        // Other code
    }
    
    1. Name “MyPassName”:定義該Pass的名稱,可以使用UsePass命令來直接使用其他unity shader中的Pass,例如:UsePass "MyShader/MYPASSNAME",由於Unity 內部會將所有Pass 名稱轉換為大寫字母的表示,所以在使用UsePass的時候必須使用大寫形式的名字。

    2. RenderSetup:我們可以對Pass設置渲染狀態,除上述狀態設置以外,我們還可以使用固定管線的着色器。

    3. Tag:
      |標簽類型|說明|例子|
      |---|----|---|
      |LightMode|定義該Pass在Unity渲染流水線中的角色|Tags{"LightMode"="ForwardBase"}|
      |RequireOptions|用於制定當滿足某些條件的時候才渲染該Pass,它的值是一個由空格分割的字符串,目前支持的選項:SoftVegetation|Tags{"RequireOptions"="SoftVegetation"}|

    4. 特殊的Pass:

      • UsePass:使用該指令復用其他UnityShader中的Pass。

      • GrabPass:負責抓取屏幕並將結果存儲在一張紋理之中,以用於后續的Pass 處理。

FallBack

如果上面所有的SubShader在這塊顯卡上都不能運行,那么就用這個最低級的Shader。

FallBack "name"
// 或者
FallBack Off

通過一個字符串通知引擎最低級的Shader是哪個,也可以關閉Fallback功能——如果上述的SubShader無法使用,那就不要管它了。

其他語義
  • 拓展編輯界面:CustomEditor
  • 對命令進行分組:CateGory

UnityShader的形式

ShaderLab語句塊:

Shader "Myshader"{
    Properties{
        // 所需的各種屬性
    }
    SubShader{
        // 真正意義上的SubShdaer代碼會出現在這里
        // 表面着色器(Surface Shader)
        // 頂點/片元着色器(Vertex/Fragment Shader)
        // 固定函數着色器(Fixed Function Shader)
    }
    SubShader{
        // 與上一個Shader類似
    }
}
表面着色器

當給Unity提供一個表面着色器的時候,它在背后依舊將其轉換為對應的頂點/片元着色器。意義在於Unity為我們處理了很多光照細節,使得我們無需再操心這些事情。

Shader "Custom/Simple Surface Shader"{
    SubShader{
        Tags{ "RenderType" = "Opaque" }
        CGPROGRAM
        #pragma surface surf Lambert
        struct Input {
            float4 color:COLOR;
        };
        void surf (Input IN,inout SurfaceOutput o)
        {
            o.Albedo = 1;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

表面着色器被定義在SubShader語義塊中的CGPROGRAM與ENDCG之間。之間的代碼使用Cg/HLSL語言編寫,它嵌套在ShaderLab語言中。

頂點/片元着色器

頂點/片元着色器的代碼需要定義在CGPROGRAM與ENDCG之間,而着色器是寫在Pass語義塊內,而非SubShader內,這樣做來定義每個Pass需要的Shader代碼,靈活性更高,同時控制渲染的實現細節。

Shader "Custom/Simple VertexFragment Shader"{
    SubShader{
        Pass{
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            float4 vert(float4 v:POSITION):SV_POSITION{
                return mul(UNITY_MATRIX_MVP,v);
            }

            fixed4 frag():SV_Target{
                return fixed4(1.0,0.0,0.0,1.0);
            }

            ENDCG
        }
    }
}
固定函數着色器

上面兩種UnityShader形式都使用了可編程管線,而對於一些舊的設備不支持可編程管線着色器,此時需要使用固定函數着色器來完成渲染,這些着色器往往只可以完成一些非常簡單的效果。

Shader "Tutorial/Basic"{
    Properties{
        _Color("Main Color",color)=(1.0,5.0,5.1)
    }
    SubShader{
        Pass{
            Material{
                Diffuse[_Color]
            }
            Lighting On
        }
    }
}
樂樂女神的一些建議:
  • 除非有明確的需求必須要使用固定函數着色器,否則請使用可編程管線的着色器。
  • 如果想和各種光源打交道,你可能更喜歡表面着色器,但需要小心它在移動平台的性能表現。
  • 如果需要使用的光照數目非常少,使用頂點/片元着色器是一個更好的選擇。
  • 如果有很多自定義的渲染效果,請選擇頂點/片元着色器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM