聽說MatCap能在低端機上做出很漂亮的pbr效果,就嘗試了一下。
MatCap全稱MaterailCapture,里面存的是光照信息,通過法線的xy分量去采樣matcap,得到在該方向法線的光照信息,因為不是實時光照,所以性能好,好不好看就看你的Matcap做得好不好了。下面是簡單的matcap嘗試:
Shader "Unlit/SimpleMatCapShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _MatCap("MatCap", 2D) = "white" {} _MatCapFactor("MatCapFactor", Range(0,5)) = 1 _EnvTex("EnvTex (CubeMap)", Cube) = "_SkyBox" {} _EnvFactor("EnvStrength", Range(0,1)) = 0.8 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; }; struct v2f { float4 twoUv : TEXCOORD0;//主紋理uv存xy,matCapUv存在zw,這算一種優化 float4 vertex : SV_POSITION; float3 RefDir : TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _MatCap; half _MatCapFactor; samplerCUBE _EnvTex; half _EnvFactor; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.twoUv.xy = TRANSFORM_TEX(v.uv, _MainTex); //matcap存的其實是:法線中xy分量作為uv,對應的光照顏色信息,即用xy去采樣就好,注:xy必須是歸一化法線中的分量,故z才沒必要 o.twoUv.zw = UnityObjectToWorldNormal(v.normal).xy; o.twoUv.zw = o.twoUv.zw * 0.5 + 0.5;//(-1,1)->(0,1) float3 wolrdN = UnityObjectToWorldNormal(v.normal); o.RefDir = reflect(-WorldSpaceViewDir(v.vertex), wolrdN); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.twoUv.xy); fixed4 mapCapCol = tex2D(_MatCap, i.twoUv.zw); fixed4 reflection = texCUBE(_EnvTex, i.RefDir); col.rgb = col.rgb * mapCapCol.rgb * _MatCapFactor + reflection.rgb * _EnvFactor; return col; } ENDCG } } }
各種效果如下:
matCap貼圖的獲取:
這邊提供幾個可以獲取MatCap貼圖的網址:
[1] https://www.pinterest.com/evayali/matcap/
[3]http://pixologic.com/zbrush/downloadcenter/library/#prettyPhoto
總結,如果matcap做得好,確實能得到非常漂亮的效果,關鍵是,只是多一張tex就能獲得如此效果,不錯不錯。
許多資料都沒有講到,但我個人以為,matcap其實是繽紛多彩的高光效果。普通高光一般是單一的白色,或其他單色,matcap因為用圖片存不同“斜率”的法線的高光顏色,所以可以做得更加漂亮,這個可以看下圖:
一個matcap紋理圖
(因為法線先x,y,z歸一化(一個單位球體),后取其中的x,y采用,所以[x,y]必定束縛在圓中,
所以matcap都是圓,即使不是,也只有圓內紋理有效)
從上面shader可知我們先把法線從[-1,1]映射到[0,1]后再采樣,這個是由於matcap坐標是從0開始的,為了更加直觀的理解,我們反其道行之:
把matcap圖片的坐標從[0,1]映射到[-1,1]。
則,明顯地,圖片中間就是[0,0],即普通笛卡爾坐標系的原點,此時,法線區間是[-1,1],matcap圖的坐標區間也是[-1,1],一一對應,每個像素的法線根據其大小和方向在matcap圖中取值,得到的就是這個像素的高光顏色,這樣,matcap的效果也變得很直觀了。