Shader Learing(ShaderLab syntax篇)

Shader Learing(ShaderLab syntax篇)

回顧:
回顧Unity中,數據的傳遞及Shader的工作原理:



從上圖我們可以看出,在渲染管線中,頂點着色器輸入的數據經過頂點着色器後,頂點着色器會把相關數據傳遞給片段着色器,上圖即表明了在Unity的頂點着色器和片段着色器中數據的傳遞類型和傳遞方向。

/*
齊次座標表示是計算機圖形學的重要手段之一,它既能夠用來明確區分向量和點
同時也更易用於進行仿射(線性)幾何變換。
*/
Shader "Custom/004_RGBCube" {
	SubShader { 
		Pass { 
        CGPROGRAM 
        #pragma vertex vert // vert function is the vertex shader 
        #pragma fragment frag // frag function is the fragment shader
        // for multiple vertex output parameters an output structure 
        // is defined:
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 col : TEXCOORD0;
        };
		//POSITION語意用於頂點着色器,用來指定這些個位置座標值,是在變換前的頂點的object space座標。
		//SV_POSITION語意則用於像素着色器,用來標識經過頂點着色器變換之後的頂點座標。
        vertexOutput vert(float4 vertexPos : POSITION) 
        // vertex shader 
        {
           vertexOutput output; // we don't need to type 'struct' here
           output.pos =  mul(UNITY_MATRIX_MVP, vertexPos);
           output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0);
              // Here the vertex shader writes output data
              // to the output structure. We add 0.5 to the 
              // x, y, and z coordinates, because the 
              // coordinates of the cube are between -0.5 and
              // 0.5 but we need them between 0.0 and 1.0. 
            return output;
        }
        float4 frag(vertexOutput input) : COLOR // fragment shader
        {
            return input.col; 
              // Here the fragment shader returns the "col" input 
              // parameter with semantic TEXCOORD0 as nameless
              // output parameter with semantic COLOR.
        }
        ENDCG  
      }
   }
}

ShaderBuilt-in Vertex Input:
我們知道Unity Shader編程中,可以使用結構體來把頂點輸入數據,如上面的示例,其實在Unity Shader編程中,有很多內建的結構體可以讓我們很方便的使用,下面使用Unity內建的結構體實現上面的示例:

Shader "Custom/005_Build_InShader" {
	SubShader { 
      Pass { 
         CGPROGRAM 
        #pragma vertex vert  
        #pragma fragment frag 
        #include "UnityCG.cginc"
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 col : TEXCOORD0;
        };
        vertexOutput vert(appdata_full input) 
        {
           vertexOutput output;
           output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
           output.col = input.texcoord;

           return output;
        }
        float4 frag(vertexOutput input) : COLOR 
        {
           return input.col; 
        }
        ENDCG  
     }
   }
}

/*
struct vertexInput {
         float4 vertex : POSITION; // position (in object coordinates, 
								 // i.e. local or model coordinates)
         float4 tangent : TANGENT;  
								// vector orthogonal to the surface normal
         float3 normal : NORMAL; // surface normal vector (in object
								// coordinates; usually normalized to unit length)
         float4 texcoord : TEXCOORD0;  // 0th set of texture 
									// coordinates (a.k.a. “UV”; between 0 and 1) 
         float4 texcoord1 : TEXCOORD1; // 1st set of tex. coors. 
         float4 texcoord2 : TEXCOORD2; // 2nd set of tex. coors. 
         float4 texcoord3 : TEXCOORD3; // 3rd set of tex. coors. 
         fixed4 color : COLOR; // color (usually constant)
      };
	預定義結構體:
	pre-defined input structures appdata_base, appdata_tan, appdata_full
	and appdata_img for the most common cases. 
	These are defined in the file UnityCG.cginc 
	(in the directory Unity > Editor > Data > CGIncludes):

	struct appdata_base {
      float4 vertex : POSITION;
      float3 normal : NORMAL;
      float4 texcoord : TEXCOORD0;
	};
	struct appdata_tan {
      float4 vertex : POSITION;
      float4 tangent : TANGENT;
      float3 normal : NORMAL;
      float4 texcoord : TEXCOORD0;
    };
    struct appdata_full {
      float4 vertex : POSITION;
      float4 tangent : TANGENT;
      float3 normal : NORMAL;
      float4 texcoord : TEXCOORD0;
      float4 texcoord1 : TEXCOORD1;
      float4 texcoord2 : TEXCOORD2;
      float4 texcoord3 : TEXCOORD3;
      fixed4 color : COLOR;
      // and additional texture coordinates only on XBOX360
    };
    struct appdata_img {
      float4 vertex : POSITION;
      half2 texcoord : TEXCOORD0;
    };
*/

uniform:
uniform變量一般用來表示:變換矩陣,材質,光照參數和顏色等信息。

Shader "Custom/006_Uniforms" {
	SubShader {
      Pass {
         CGPROGRAM
        #pragma vertex vert  
        #pragma fragment frag 
        // uniform float4x4 _Object2World; 
        // automatic definition of a Unity-specific uniform parameter
        struct vertexInput {
           float4 vertex : POSITION;
        };
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 position_in_world_space : TEXCOORD0;
        };
        vertexOutput vert(vertexInput input) 
        {
            vertexOutput output; 
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.position_in_world_space = 
               mul(_Object2World, input.vertex);
               // transformation of input.vertex from object 
               // coordinates to world coordinates;
            return output;
        }
        float4 frag(vertexOutput input) : COLOR 
        {
            float dist = distance(input.position_in_world_space, 
            float4(0.0, 0.0, 0.0, 1.0));
               // computes the distance between the fragment position 
               // and the origin (the 4th coordinate should always be 
               // 1 for points).
            if (dist < 5.0)
            {
               return float4(0.0, 1.0, 0.0, 1.0); 
                  // color near origin
            }
            else
            {
               return float4(0.1, 0.1, 0.1, 1.0); 
                  // color far from origin
            }
        }
        ENDCG  
      }
   }
}
/*
uniform float4 _Time, _SinTime, _CosTime; // time values
   uniform float4 _ProjectionParams;
							  // x = 1 or -1 (-1 if projection is flipped)
							  // y = near plane; z = far plane; w = 1/far plane
   uniform float4 _ScreenParams; 
					    // x = width; y = height; z = 1 + 1/width; w = 1 + 1/height
   uniform float3 _WorldSpaceCameraPos;
   uniform float4x4 _Object2World;      // model matrix
   uniform float4x4 _World2Object;     // inverse model matrix 
   uniform float4 _WorldSpaceLightPos0; 
   // position or direction of light source for forward rendering

   uniform float4x4 UNITY_MATRIX_MVP;   // model view projection matrix 
   uniform float4x4 UNITY_MATRIX_MV;   // model view matrix
   uniform float4x4 UNITY_MATRIX_V;   // view matrix
   uniform float4x4 UNITY_MATRIX_P;   // projection matrix
   uniform float4x4 UNITY_MATRIX_VP;   // view projection matrix
   uniform float4x4 UNITY_MATRIX_T_MV; 
      // transpose of model view matrix
   uniform float4x4 UNITY_MATRIX_IT_MV; 
      // transpose of the inverse model view matrix
   uniform float4 UNITY_LIGHTMODEL_AMBIENT; // ambient color
   */

Uniform應用的第二個示例:

Shader "Custom/007_UserSpecifiedUniforms" {
	Properties {
    _Point ("a point in world space", Vector) = (0., 0., 0., 1.0)
    _DistanceNear ("threshold distance", Float) = 5.0
    _ColorNear ("color near to point", Color) = (0.0, 1.0, 0.0, 1.0)
    _ColorFar ("color far from point", Color) = (0.3, 0.3, 0.3, 1.0)
   }
   SubShader {
      Pass {
        CGPROGRAM
        #pragma vertex vert  
        #pragma fragment frag 
        #include "UnityCG.cginc" 
            // defines _Object2World and _World2Object
         // uniforms corresponding to properties
        uniform float4 _Point;
        uniform float _DistanceNear;
        uniform float4 _ColorNear;
        uniform float4 _ColorFar;
        struct vertexInput {
           float4 vertex : POSITION;
        };
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 position_in_world_space : TEXCOORD0;
        };
        vertexOutput vert(vertexInput input) 
        {
            vertexOutput output; 
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.position_in_world_space = 
               mul(_Object2World, input.vertex);
            return output;
        }
        float4 frag(vertexOutput input) : COLOR 
        {
            float dist = distance(input.position_in_world_space, 
               _Point);
               // computes the distance between the fragment position 
               // and the position _Point.
            
            if (dist < _DistanceNear)
            {
               return _ColorNear; 
            }
            else
            {
               return _ColorFar; 
            }
        }
        ENDCG  
      }
   }
}

/*
Shader的屬性可以在腳本中被使用:
eg:
GetComponent(Renderer).sharedMaterial.SetVector("_Point", 
      Vector4(1.0, 0.0, 0.0, 1.0));
   GetComponent(Renderer).sharedMaterial.SetFloat("_DistanceNear", 
      10.0);
   GetComponent(Renderer).sharedMaterial.SetColor("_ColorNear", 
      Color(1.0, 0.0, 0.0));
   GetComponent(Renderer).sharedMaterial.SetColor("_ColorFar", 
      Color(1.0, 1.0, 1.0));
*/

這樣,我們可以通過持有屬性來達到修改的目的。
Pass(通道):RenderSetup+固定功能着色器命令
Unity中一個SubShader(渲染方案)是由一個個Pass塊來執行的。每個Pass都會消耗對應的一個DrawCall。在滿足渲染效果的情況下儘可能地減少Pass的數量。
Pass(通道編程)
1個Pass塊可以使一個幾何物體被一次渲染。
Pass { [Name and Tags] [RenderSetup] [TextureSetup] }
最基礎的pass命令包含有1個可選的渲染設置命令列表,及1個可選的可用紋理列表。
一個Pass 可以定義它的名字和任意數量的標籤-name/value 字符串 將Pass的含義告訴給渲染引擎。

Render Setup 渲染設置
Pass設置了一系列的顯卡狀態,比如說alpha混合是否開啓,是否允許霧化等等。 這些命令有:


①Color color

Shader "Custom/NewShader" {
	SubShader {
        Pass { Color (1,0,0,0) }  //將對象設置爲固體顏色
    }
}

②Material {Material Block}  定義一個使用頂點光照管線的材質

Shader "Custom/NewShader" {
	SubShader {
        Pass {
            Material {  //材質塊用於定義對象的材質屬性
                Diffuse (1,1,1,1)
                Ambient (1,1,1,1)
            }
            Lighting On
        }
    }
}

③Lighting On|Off     開啓或關閉頂點光照

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", COLOR) = (1,1,1,1)
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
                Ambient [_Color]
            }
            Lighting On
 //對於在材質塊中定義的設置有任何影響,您必須啓用燈光與燈光的命令。如果燈光是關閉的,顏色是直接從顏色命令。
        }
    }
}

④SeparateSpecular On|Off  此命令使鏡面照明添加到着色通道的末端,所以鏡面照明不受紋理的影響。
⑤ColorMaterial AmbientAndDiffuse|Emission  使用每個頂點顏色代替材質中設置的顏色。

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]//Diffuse color: 漫反射顏色分量。這是一個對象的基本顏色。
                Ambient [_Color]//Ambient color: 環境顏色分量。這是對象的顏色,在照明窗口中被環境光照射
                Shininess [_Shininess]//Shininess number: 突出的清晰度,在1和0之間
                Specular [_SpecColor]//Specular color: 對象的高光的顏色
                Emission [_Emission]//Emission color: 物體不被任何光線擊中時的顏色
            }
            Lighting On
            SeparateSpecular On
            SetTexture [_MainTex] {
                Combine texture * primary DOUBLE, texture * primary
            }
        }
    }
}



⑥Cull Back|Front|Off     設置多邊形剔除模式,控制多邊形應該剔除(不繪製)的面

Shader "Custom/NewShader" {  //對象只渲染對象的背面
  SubShader {
        Pass {
            Material {
                Diffuse (1,1,1,1)
            }
            Lighting On
            Cull Front
        }
    }
}

⑦ZWrite On|Off     設置深度寫模式,控制像素從這個對象是否寫入深度緩衝

Shader "Custom/NewShader" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
}
SubShader {
    Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    LOD 200
    // extra pass that renders to depth buffer only
    Pass {
        ZWrite On     // 開啓深度緩衝寫
        ColorMask 0   //關閉所有渲染染色通道
    }
    // paste in forward rendering passes from Transparent/Diffuse
    UsePass "Transparent/Diffuse/FORWARD"
}
//Fallback "Transparent/VertexLit"
}

⑧ZTest Less|Greater|LEqual|GEqual|Equal|NotEqual|Always     設置深度測試模式
⑨Offset Factor, Units     允許您指定兩個參數的深度偏移量

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }
    SubShader {
        // We use the material in many passes by defining them in the subshader.
        // Anything defined here becomes default values for all contained passes.
        Material {
            Diffuse [_Color]
            Ambient [_Color]
            Shininess [_Shininess]
            Specular [_SpecColor]
            Emission [_Emission]
        }
        Lighting On
        SeparateSpecular On
        // Set up alpha blending
        Blend SrcAlpha OneMinusSrcAlpha
        // Render the back facing parts of the object.
        // If the object is convex, these will always be further away
        // than the front-faces.
        Pass {
            Cull Front
            SetTexture [_MainTex] {
                Combine Primary * Texture
            }
        }
        // Render the parts of the object facing us.
        // If the object is convex, these will be closer than the
        // back-faces.
        Pass {
            Cull Back
            SetTexture [_MainTex] {
                Combine Primary * Texture
            }
        }
    }
}


⑩SetTexture [TextureName] {Texture Block}

Shader "Custom/NewShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }
    SubShader {
        // Render the front-facing parts of the object.
        // We use a simple white material, and apply the main texture.
        Pass {
            Material {
                Diffuse (1,1,1,1)
            }
            Lighting On
            SetTexture [_MainTex] {
                Combine Primary * Texture
            }
        }
        // Now we render the back-facing triangles in the most
        // irritating color in the world: BRIGHT PINK!
        Pass {
            Color (1,0,1,1)
            Cull Front
        }
    }
}
//傳統的紋理合成
//Previous 是之前SetTexture的結果。        
//Primary 是從照明計算或頂點顏色的顏色。    
//Texture 紋理是在SetTexture TextureName指定紋理的顏色(見上圖)。
//Constant 是ConstantColor指定的顏色。

⑪SetTexture [_MainTex] { combine previous * texture, previous + texture }
⑫Fog {Fog Commands}     設置霧參數
⑬Mode Off|Global|Linear|Exp|Exp2
⑭Color ColorValue
⑮Density FloatValue
⑯Range FloatValue, FloatValue


⑰AlphaTest Off     開啓alpha測試
⑱AlphaTest comparison AlphaValue

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (.5, .5, .5, .5)
        _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
        _Cutoff ("Base Alpha cutoff", Range (0,.9)) = .5
    }
    SubShader {
        // Set up basic lighting
        Material {
            Diffuse [_Color]
            Ambient [_Color]
        }
        Lighting On
        // Render both front and back facing polygons.
        Cull Off
        // first pass:
        // render any pixels that are more than [_Cutoff] opaque
        Pass {
            AlphaTest Greater [_Cutoff]
            SetTexture [_MainTex] {
                combine texture * primary, texture
            }
        }
        // Second pass:
        // render in the semitransparent details.
        Pass {
            // Dont write to the depth buffer
            ZWrite off
            // Don't write pixels we have already written.
            ZTest Less
            // Only render pixels less or equal to the value
            AlphaTest LEqual [_Cutoff]
            // Set up alpha blending
            Blend SrcAlpha OneMinusSrcAlpha
            SetTexture [_MainTex] {
                combine texture * primary, texture
            }
        }
    }
}


⑲Blend Off     設置α混合模式

Blend SrcFactor DstFactor
Blend SrcFactor DstFactor, SrcFactorA DstFactorA
BlendOp BlendOp

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB) Transparency (A)", 2D) = "white" {}
        _Reflections ("Base (RGB) Gloss (A)", Cube) = "skybox" { TexGen CubeReflect }
    }
    SubShader {
        Tags { "Queue" = "Transparent" }
        Pass {
            Blend SrcAlpha OneMinusSrcAlpha
            Material {
                Diffuse [_Color]
            }
            Lighting On
            SetTexture [_MainTex] {
                combine texture * primary double, texture * primary
            }
        }
        Pass {
            Blend One One
            Material {
                Diffuse [_Color]
            }
            Lighting On
            SetTexture [_Reflections] {
                combine texture
                Matrix [_Reflection]
            }
        }
    }
}

Per-pixel Lighting 逐像素光照
逐像素光照管道的工作依賴於渲染對象在多個pass中。Unity3D一旦獲得環境光和任何頂點的光照就開始渲染物體。然後,它在一個單獨添加的pass中影響渲染的物體每1個光照的像素。
Per-vertex Lighting 逐頂點光照
逐頂點光照是Direct3d/OpenGl的標準光照模式,它的計算依賴於每一個頂點。打開光照後才能啓動逐頂點光照。光照受Materialblock, ColorMaterial 和 SeparateSpecular命令影響。 
有幾個特殊的pass可以重用公共的功能或實現一些高級效果。
UsePass 包含從另外的Shader中已被命名的pass。
GrabPass 抓取屏幕內容並轉換成紋理,可以給之後的pass使用,用來做特效最好了。

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