一個示例性的Unity Shader例子
阿新 • • 發佈:2019-02-09
Shader "Custom/NormSpecular" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _Bump ("Bump", 2D) = "bump" {} _Specular ("Specular", Range(1.0, 500.0)) = 250.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Pass { Tags { "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" #include "Lighting.cginc" #include "AutoLight.cginc" uniform float4x4 _LightMatrix0; // 引入光矩陣 sampler2D _MainTex; sampler2D _Bump; float _Specular; float _Gloss; float4 _MainTex_ST; struct a2v { float4 vertex : POSITION; // 輸入的模型頂點資訊 fixed3 normal : NORMAL; // 輸入的法線資訊 fixed4 texcoord : TEXCOORD0; // 輸入的座標紋理集 fixed4 tangent : TANGENT; // 切線資訊 }; struct v2f { float4 pos : POSITION; // 輸出的頂點資訊 fixed2 uv : TEXCOORD0; // 輸出的UV資訊 fixed3 lightDir: TEXCOORD1; // 輸出的光照方向 fixed3 viewDir : TEXCOORD2; // 輸出的攝像機方向 fixed3 _LightCoord : TEXCOORD3; // 光照座標 fixed4 _ShadowCoord : TEXCOORD4; // 陰影座標 fixed3 vertexLighting:TEXCOORDS5;//頂點光照強度 }; v2f vert(a2v v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX (v.texcoord, _MainTex); // 建立一個正切空間的旋轉矩陣,TANGENT_SPACE_ROTATION由下面兩行組成 //TANGENT_SPACE_ROTATION; float3 binormal = cross( v.normal, v.tangent.xyz ) * v.tangent.w; float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal ); // 將頂點的光方向,轉到切線空間 // 該頂點在物件座標中的光方向向量,乘以切線空間旋轉矩陣 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); // 該頂點在攝像機座標中的方向向量,乘以切線空間旋轉矩陣 o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)); // 將照明資訊給畫素著色器,應該是用於下面片段中光衰弱atten的計算 // TRANSFER_VERTEX_TO_FRAGMENT(o); // 由下面兩行組成 // 頂點轉到世界座標,再轉到光座標 o._LightCoord = mul(_LightMatrix0, mul(_Object2World, v.vertex)).xyz; o._ShadowCoord = mul(unity_World2Shadow[0], mul(_Object2World, v.vertex)); o.vertexLighting = fixed3(0.0,0.0,0.0); o.vertexLighting = Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0, unity_LightColor[0].rgb,unity_LightColor[1].rgb,unity_LightColor[2].rgb,unity_LightColor[3].rgb, unity_4LightAtten0,mul(_Object2World,v.vertex),normalize(mul(float4(v.normal,0.0),_World2Object).xyz)); return o; } fixed4 frag(v2f i) : COLOR { // 對主紋理進行取樣 fixed4 texColor = tex2D(_MainTex, i.uv); // 對法線圖進行取樣 fixed3 norm = UnpackNormal(tex2D(_Bump, i.uv)); // 光衰弱,臥槽,裡面封裝了比較深,暫時看不進去,就不拆開了 fixed atten = LIGHT_ATTENUATION(i); // 求漫反射 // 公式:漫反射色 = 光顏色*N,L的餘弦值(取大於0的),所以夾角越小亮度越小 fixed3 Diff = dot (normalize(norm), normalize(i.lightDir));//半形向量 fixed3 HalfVector = normalize(i.lightDir + i.viewDir); fixed NdotH = max(0,dot(norm,HalfVector)); fixed specularpower = pow(NdotH,_Specular)*sign(Diff); Diff = saturate(Diff); // 計算反射高光 // 公式:反射高光 = 光顏色 * 【(反射光向量,攝像機方向向量)的餘弦值】的【高光指數_Specular】次方 * 光澤度 fixed4 fragColor; fragColor.rgb = texColor.rgb*(((Diff+specularpower)*_LightColor0.rgb)*(atten*Diff*2)+i.vertexLighting); fragColor.a = texColor.a; return fragColor; } ENDCG } } FallBack "Diffuse" }
Unity5.2.3下編譯通過