1. 程式人生 > >Unity3d開發(一)ShaderLab 入門 語法格式

Unity3d開發(一)ShaderLab 入門 語法格式

Ahead

好長時間沒更新部落格了,究其原因,是我想嘗試Wiki這種形式來整理知識。總體來說,它還是不錯的,不過不適合我。所以,還是迴歸部落格吧。

Shader Lab

ShaderLab 是Unity3d自己封裝的一個呼叫CG/HLSL/GLSL的介面。相關資訊可以參考:聖典翻譯的新手

基本格式

shaderLab 程式碼一般遵循以下格式:

Shader "MyShader/ShaderName" 
{
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0.5)
        _MainTex ("Texture", 2D) = "white" { }
    }
    SubShader 
    {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            //--snip--
            struct v2f {
                float4 pos :SV_POSITION;
                float3 color : COLOR0;
            };
            
            v2f lv1(appdata_base v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
                o.color = v.normal * 0.5 +0.5;
                return o;
            }
            
            half4 lv2(v2f i) : COLOR
            {
                return half4(i.color,1);
            }
            
            ENDCG
        }
    }
    FallBack "VertexLit"
}

屬性設定

Properties {
    `InnerName` ( `showName`,`type`) = `defaultValue`
}

其中型別與預設值對應如下:

  • Color (r,g,b,a)
  • Range(min,max) 2.4
  • 2D "white" {}
  • Float 2.4

surface shader

以下內容詳細可以參考此處

定義

使用 #pragma surface 這個指令可用編寫表面著色器。

#pragma surface surfaceFunction lightModel [optionalparams]

所需引數:

  • surfaceFunction - 表示Cg函式中有表面著色器(surface shader)程式碼。這個函式的格式應該是這樣:

    void surf (Input IN,inout SurfaceOutput o)

    Input是你自己定義的結構。Input結構中應該包含所有紋理座標(texture coordinates)和和表面函式(surfaceFunction)所需要的額外的必需變數。

  • lightModel -在光照模式中使用。內建的是Lambert (diffuse)和 BlinnPhong (specular)。如果想編寫自己的光照模式,請參考:自定義光照模式。

cginc

對於預定義的巨集和函式,Unity將她們放進了許多包含檔案中。在Mac上,它的目錄為 Contents/CGIncludes/xxx.cginc 例如常用的:UnityCG.cginc, lighting.cginc 等。當然我們也可以自己編寫。將檔案字尾更改成.cginc

然後在shader中使用#include "YourCGInclude.cginc"即可。

INPUT

Input 這個輸入結構通常擁有著色器需要的所有紋理座標(texture coordinates)。紋理座標(Texture coordinates)必須被命名為“uv”後接紋理(texture)名字。(或者uv2開始,使用第二紋理座標集)

例如:

Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _BumpMap ("Bumpmap", 2D) = "bump" {}
}

struct Input {
        float2 uv_MainTex;
        float2 uv_BumpMap;
};

  sampler2D _MainTex;
  sampler2D _BumpMap;

OUTPUT

struct SurfaceOutput {
    half3 Albedo;       //反射率
    half3 Normal;       //法線
    half3 Emission;     //自發光,用於增強物體自身的亮度,使之看起來好像可以自己發光
    half Specular;      //鏡面
    half Gloss;         //光澤
    half Alpha;         //透明
};

subshader Tag

使用Tags可以為subshader指定屬性:

Tags { "TagName1" = "Value1" "TagName2" = "Value2" }

詳細的屬性使用可以參考Unity手冊中 subshader tags章節。

指令碼中呼叫

在指令碼中可以動態設定shader的值,例如:

[ExecuteInEditMode]
public class caller : MonoBehaviour {
    public Color diffColor;

    void Update()
    {
        renderer.sharedMaterial.SetColor("_color",diffColor);
    }
}

其中,shader中有名為_color的uniform變數 例如:

Shader "Learn/ColorShader" {
    Properties {
    }
    SubShader {
        Tags { "Queue"= "Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        
        Pass{
            CGPROGRAM
            #pragma vertex v2f
            #pragma fragment frag
            
            #include "UnityCG.cginc"
             
            uniform fixed4 _color;
            
            struct InputVertex
            {
                float4 pos : POSITION;
            } ;
            
            struct Output
            {
                float4 pos :SV_POSITION;
                float4 col :COLOR0;
            } ;
              
            Output v2f(InputVertex input)
            {
                Output o;
                o.pos = mul(UNITY_MATRIX_MVP,input.pos);
                o.col = _color;
                return o;
            }
            
            half4 frag(Output o): COLOR
            {
//              return half4(1.0,0.4,0.4,1);
                return o.col;
            }
        
            ENDCG
        }
    }  
    FallBack "Diffuse"
}

自定義光照

#pragma surface surf `FuncName`
  • half4 LightingFuncName (SurfaceOutput s, half3 lightDir, half atten) {}
  • half4 LightingFuncName (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {}
  • half4 LightingFuncName (SurfaceOutput s, half4 light) {}

如果你覺得這篇文章對你有幫助,可以順手點個,不但不會喜當爹,還能讓更多人能看到它...