unityShader流程對比及其總譜

1.Unity的3種Shader流程圖


上面三種Shader在unity中都能夠使用一種ShaderLab 的語法來進行編寫Shader。基本的ShaderLab的基本結構如下


Shader  “ name” =
 {
[Properties]
[SubShader]
[FallBack]
}
Properties :  屬性,他定義了一些引用變量,可以在 Unity簡視面板上進行查看,設置。
SubShader :一個shader可以有多個Subshader,在執行的時候,只會執行一個圖形硬件支持的SubShader,判斷順序從第一種以此往後邊進行怕斷,判斷到哪一個subshader當前能夠執行,就執行那一個。
FallBack:當上述所有的SubShader圖形硬件都不能夠執行的話就會執行FallBack。
2.Unity官方自帶的Shader類型流程圖


3.FiexdFunction shader 片段,主要的命令及其規則

4,來奉上FixedFunction Shader 的代碼片段


Shader "ShaderDemo/FixedFunctionShader" {
Properties{
_Color("Main Color",color) = (1,1,1,1)  //漫反射的顏色
_Ambient("Ambient Color",color) = (0.3,0.3,0.3,0.3)
_Specuar("Specular Color",color) = (1,1,1,1) //高光的強度
_Shininess("Shininess",Range(0,8)) = 4 //高光的強度
_Emission("Emission",color) = (1,0,0,1) // 自發光的顏色


_MainTexture("Main Texture",2D) = "white"{}
_SecondTexture("Main Texture",2D) = "white"{}
_Constant("ConstantColor",color) = (1,1,1,1)
}


Subshader{


Tags { "Queue" = "Transparent" }
pass{


//進行混合渲染
Blend SrcAlpha OneMinusDstColor


material
{
diffuse[_Color]
ambient[_Ambient]
specular[_Specuar]
shininess[_Shininess]
emission[_Emission]
}


lighting on
separatespecular on




settexture[_MainTexture]
{
combine texture * primary double //混合之前的顏色
}


// primary  總是當前紋理 和頂點光照後的顏色進行混合
// previous 當前的紋路 和之前所以的紋理 和定點顏色進行混合
settexture[_SecondTexture]
{
constantcolor [_Constant]
combine texture * previous double ,texture * constant //混合之前的顏色  後面加 texture  只是通過貼圖的alpha 來作爲 透明通道
}
}
}
}

關鍵點的函數


基於alpha測試階段的流程


4,SurfaceShader,他實際上是對VertexShader 和fragment Shader的一種包裝,他其實目的是不讓我們更多的來關注實現的細節,但是我就是喜歡知道各種實現的細節,知道其原理。Surface Shader 沒有Pass通道,他能夠幫我自動生成底層能夠執行的代碼,也包括他能夠幫我們生成底層的pass通道。他的基本的結果如下

Shader “menu/name”
{
Propertyes{ }
Subshader{
Tags {}
LOD  xx
CGPROGRAM
#pragma xx


//主內容
ENDCG
}
FallBack "Diffuse"
}
Pragma:編譯指令,例如如下代碼
#pragma surface surf Standard fullforwardshadows
surface 是指定義了一個方法叫做surf,surf這個方法是你在下邊自己定義的,用來進行fragment各種計算的Standrad爲光照模型,起具體的請參考,UnityPBSLighting.cginc文件裏面的如下函數


inline half4 LightingStandard (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
{
s.Normal = normalize(s.Normal);




half oneMinusReflectivity;
half3 specColor;
s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);




// shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
// this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
half outputAlpha;
s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);




half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
c.a = outputAlpha;
return c;
}
fullforwardshadows 描述的是一些其它的選項 這裏指的是陰影選項,具體的請去參考unity官方文檔。具體的surfaceShader代碼如下
Shader "ShaderDemo/SurfaceShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)//主顏色
_MainTex ("Albedo (RGB)", 2D) = "white" {}   //主紋理
_Glossiness ("Smoothness", Range(0,1)) = 0.5  //高光的強度
_Metallic ("Metallic", Range(0,1)) = 0.0  //金屬質感
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200

CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard removeshadow


// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0 


sampler2D _MainTex;


struct Input {
float2 uv_MainTex;
};


half _Glossiness;
half _Metallic;
fixed4 _Color;


void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG




}
}




需要注意的是紋理採樣的時候必須要以uv小寫開頭的名稱,如 uv_MainTex,否則紋理採樣將不成功。我們來看surf函數,這個函數是無返回的,說明他並不是以返回值的形勢來輸出的,Input 目前最重要是他能夠包裝我們的紋理值。第二個參數爲 inout,  他代表這個參數即是輸入又是輸入,默認的是輸入類型,SurfaceOutputStandard請參考unity3D文檔,例如早起的版本SurfaceOutput
struct SurfaceOutput


{
    fixed3 Albedo;  // diffuse color
    fixed3 Normal;  // tangent space normal, if written
    fixed3 Emission;
    half Specular;  // specular power in 0..1 range
    fixed Gloss;    // specular intensity
    fixed Alpha;    // alpha for transparencies
};
早起版本沒有基於Standard物理光照只有基於Lambert光照模型,他的原型如下
inline fixed4 LightingLambert (SurfaceOutput s, UnityGI gi)
{
    fixed4 c;
    c = UnityLambertLight (s, gi.light);


    #if defined(DIRLIGHTMAP_SEPARATE)
        #ifdef LIGHTMAP_ON
            c += UnityLambertLight (s, gi.light2);
        #endif
        #ifdef DYNAMICLIGHTMAP_ON
            c += UnityLambertLight (s, gi.light3);
        #endif
    #endif


    #ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
        c.rgb += s.Albedo * gi.indirect.diffuse;
    #endif


    return c;
}

基於Lambert的渲染模型Shader如下

   Properties {
        _MainTex ("Albedo (RGB)"2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" "Queue" = "Transparent"}
        LOD 200
        
        CGPROGRAM

        #pragma surface surf Lambert addshadow  

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;

        void surf (Input IN, inout SurfaceOutput o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.g;
        }
        ENDCG
    }
//    FallBack "Diffuse"
}

需要注意的是,設置物體透明的時候不能給用Blend,因爲他沒有pass通道,我們直接可以在pragma 編譯指令後面來設置alpha通道,具體的參數可以參考unity3d文檔如下


基於fragment vertex shader的基本結構如下

Shader "ShaderDemo/VertexFragmentShader" {

    SubShader{

        pass
        {
            CGPROGRAM
            #pragma vertex vertexMain
            #pragma fragment  fragMain


            void vertexMain(in float2 objects : POSITION,out float4 pos:POSITION,out fixed4 col:COLOR)
            {
                pos = float4(objects,0,1);
                col = pos;
            }

            void fragMain( inout float4  col:COLOR)
            {
            }

            ENDCG

        }

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章