|
1.5 Blinn-Phong光照模型
圖形學(xué)界大牛Jim Blinn對Phong模型進(jìn)行了改進(jìn),提出了Blinn-Phong模型。Blinn-Phong模型與Phong模型的區(qū)別是,把dot(V,R)換成了dot(N,H),其中H為半角向量,位于法線N和光線L的角平分線方向。Blinn-Phong模型可表示為:
Ispecular = Ks*Is* pow(( dot(N,H), n )
其中H = (L + V) / | L+V |,計(jì)算H比計(jì)算反射向量R更快速。
Unity中,Phong實(shí)際上指的就是Blinn-Phong,兩者指的同一種內(nèi)置光照模型。
PS:光照模型部分的內(nèi)容主要參考為:http://cg./
二、關(guān)于自定義光照模式(custom lighting model)
在編寫表面著色器的時候,我們通常要描述一個表面的屬性(反射率顏色,法線,…)、并通過光照模式來計(jì)算燈光的相互作用。 通過上篇文章的學(xué)習(xí),我們已經(jīng)知道,Unity中的內(nèi)置的光照模式有兩種, 分別是Lambert (漫反射光diffuse lighting) 和 Blinn-Phong (也就是鏡面反射光(高光),specular lighting)模式。
然而,內(nèi)置的光照模式自然有其局限性。想要自己做主的話,我們可以自定義光照模式。 也就是使用自定義光照模式( custom lighting model)。 其實(shí)說白了,光照模式(lighting model)無外乎是幾個Cg/HLSL函數(shù)的組合。
內(nèi)置的 Lambert 和 Blinn-Phong定義在 Lighting.cginc文件中。我們不妨先來人肉一下他們的實(shí)現(xiàn)源代碼。
windows系統(tǒng)下位于: …Unity\Editor\Data\CGIncludes\
Mac系統(tǒng)下位于: /Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc)
Unity內(nèi)置的 Lambert 和 Blinn-Phong模型的Shader源代碼在這里貼出來: #ifndef LIGHTING_INCLUDED#define LIGHTING_INCLUDEDstruct SurfaceOutput { fixed3 Albedo; fixed3 Normal; fixed3 Emission; half Specular; fixed Gloss; fixed Alpha;};#ifndef USING_DIRECTIONAL_LIGHT#if defined (DIRECTIONAL_COOKIE) || defined (DIRECTIONAL)#define USING_DIRECTIONAL_LIGHT#endif#endif// NOTE: you would think using half is fine here, but that would make// Cg apply some precision emulation, making the constants in the shader// much different; and do some other stupidity that actually increases ALU// count on d3d9 at least. So we use float.//// Also, the numbers in many components should be the same, but are changed// very slightly in the last digit, to prevent Cg from mis-optimizing// the shader (it tried to be super clever at saving one shader constant// at expense of gazillion extra scalar moves). Saves about 6 ALU instructions// on d3d9 SM2.#define UNITY_DIRBASIS \const float3x3 unity_DirBasis = float3x3( \ float3( 0.81649658, 0.0, 0.57735028), \ float3(-0.40824830, 0.70710679, 0.57735027), \ float3(-0.40824829, -0.70710678, 0.57735026) \);inline half3 DirLightmapDiffuse(in half3x3 dirBasis, fixed4 color, fixed4 scale, half3 normal, bool surfFuncWritesNormal, out half3 scalePerBasisVector){ half3 lm = DecodeLightmap (color); // will be compiled out (and so will the texture sample providing the value) // if it's not used in the lighting function, like in LightingLambert scalePerBasisVector = DecodeLightmap (scale); // will be compiled out when surface function does not write into o.Normal if (surfFuncWritesNormal) { half3 normalInRnmBasis = saturate (mul (dirBasis, normal)); lm *= dot (normalInRnmBasis, scalePerBasisVector); } return lm;}fixed4 _LightColor0;fixed4 _SpecColor;inline fixed4 LightingLambert (SurfaceOutput s, fixed3 lightDir, fixed atten){ fixed diff = max (0, dot (s.Normal, lightDir)); fixed4 c; c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2); c.a = s.Alpha; return c;}inline fixed4 LightingLambert_PrePass (SurfaceOutput s, half4 light){ fixed4 c; c.rgb = s.Albedo * light.rgb; c.a = s.Alpha; return c;}inline half4 LightingLambert_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal){ UNITY_DIRBASIS half3 scalePerBasisVector; half3 lm = DirLightmapDiffuse (unity_DirBasis, color, scale, s.Normal, surfFuncWritesNormal, scalePerBasisVector); return half4(lm, 0);}// NOTE: some intricacy in shader compiler on some GLES2.0 platforms (iOS) needs 'viewDir' & 'h'// to be mediump instead of lowp, otherwise specular highlight becomes too bright.inline fixed4 LightingBlinnPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten){ half3 h = normalize (lightDir + viewDir); fixed diff = max (0, dot (s.Normal, lightDir)); float nh = max (0, dot (s.Normal, h)); float spec = pow (nh, s.Specular*128.0) * s.Gloss; fixed4 c; c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2); c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten; return c;}inline fixed4 LightingBlinnPhong_PrePass (SurfaceOutput s, half4 light){ fixed spec = light.a * s.Gloss; fixed4 c; c.rgb = (s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec); c.a = s.Alpha + spec * _SpecColor.a; return c;}inline half4 LightingBlinnPhong_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, half3 viewDir, bool surfFuncWritesNormal, out half3 specColor){ UNITY_DIRBASIS half3 scalePerBasisVector; half3 lm = DirLightmapDiffuse (unity_DirBasis, color, scale, s.Normal, surfFuncWritesNormal, scalePerBasisVector); half3 lightDir = normalize (scalePerBasisVector.x * unity_DirBasis[0] + scalePerBasisVector.y * unity_DirBasis[1] + scalePerBasisVector.z * unity_DirBasis[2]); half3 h = normalize (lightDir + viewDir); float nh = max (0, dot (s.Normal, h)); float spec = pow (nh, s.Specular * 128.0); // specColor used outside in the forward path, compiled out in prepass specColor = lm * _SpecColor.rgb * s.Gloss * spec; // spec from the alpha component is used to calculate specular // in the Lighting*_Prepass function, it's not used in forward return half4(lm, spec);}#ifdef UNITY_CAN_COMPILE_TESSELLATIONstruct UnityTessellationFactors { float edge[3] : SV_TessFactor; float inside : SV_InsideTessFactor;};#endif // UNITY_CAN_COMPILE_TESSELLATION#endif OK,下面讓我們一起來看看光照模式應(yīng)該怎樣聲明和定義。
三、光照模式的聲明方式
在Unity Shaderlab和CG語言中,光照模式是一個以Lighting開頭+自定義文字組合在一起的函數(shù)。 即,函數(shù)名為: Lighting+ [自定義部分] 比如,一個可行的函數(shù)名為:LightingQianMoLightingMode
我們可以在著色器文件(shader file)或?qū)胛募?included files)中的任何一個地方聲明此函數(shù)。一般情況下,此函數(shù)有五種原型可供選擇,具體如下。 一般情況下,于以下五種函數(shù)原型中選一種,進(jìn)行實(shí)現(xiàn)就行了。
【形式一】 half4 LightingName (SurfaceOutput s, half3 lightDir, half atten); 此種形式的函數(shù)可以表示在正向渲染路徑(forward rendering path)中的光照模式,且此函數(shù)不取決于視圖方向(view direction)。例如:漫反射(diffuse)。
【形式二】 half4 LightingName (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten); 此種形式的函數(shù)可以表示在正向渲染路徑(forward rendering path)中使用的光照模式,且此函數(shù)包含了視圖方向(view direction)。 【形式三】 half4 LightingName_PrePass (SurfaceOutput s, half4 light); 此種形式的函數(shù)可以在延時光照路徑(deferred lighting path)中使用的。
【形式四】 half4 LightingName_DirLightmap(SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal); 這種形式也是不依賴于視圖方向(view direction)的光照模式。例如:漫反射(diffuse)。
【形式五】 half4 LightingName_DirLightmap(SurfaceOutput s, fixed4 color, fixed4 scale, half3 viewDir, bool surfFuncWritesNormal,out half3 specColor); 這是使用的依賴于視圖方向(view direction)的光照模式(light model)。
比如,一個光照模式(lighting model)要么使用視圖方向(view direction)要么不使用。同樣的,如果光照模式(lightingmodel)在延時光照(deferred lighting)中不工作,只要不聲明成 _PrePass(第三種形式),就是行的。 另外,對于形式四和形式五的選擇,主要取決于我們的光照模式(light model)是否依賴視圖方向(view direction)。需要注意的是,這兩個函數(shù)將自動處理正向和延時光照路徑(forwardand deferred lighting rendering paths)。 PS: Unity在移動平臺中暫時不支持延遲光照渲染。
做個總結(jié),在自定義自己的光照模型函數(shù)時,根據(jù)需要在五種函數(shù)原型中選擇一種,且: 光照模式的函數(shù)名為:Lighting+ [自定義函數(shù)名] pragma聲明為: #pragmasurface surf [自定義函數(shù)名]
然后就是需要,仿照著其他的光照模式來填充函數(shù)體了。
我們舉個例子: #pragma surface surf QianMoLigtingModehalf4 LightingQianMoLigtingMode (SurfaceOutputs, half3 lightDir, half3 viewDir, half atten);
OK,光照模式的聲明就是這樣。光照模式的函數(shù)體是其最核心的部分,需要根據(jù)具體的光照模式數(shù)學(xué)公式進(jìn)行書寫,我們將在接下來的寫Shader實(shí)戰(zhàn)中進(jìn)行學(xué)習(xí)。 PS:估計(jì)這節(jié)的概念有些難懂,大家肯定在第一時間不能完全理解,沒事,讓我們依舊在Shader實(shí)戰(zhàn)中把狀態(tài)找回來。
四、寫Shader實(shí)戰(zhàn)
上文已經(jīng)提到過了,: Unity在移動平臺中暫時不支持延遲光照(Deferred lighting)渲染。因?yàn)檠訒r光照不能與一些自定義per-material 光照模式很好的共同運(yùn)行,所以在下面的例子中我們只在著色器正向渲染(ForwardRendering)中進(jìn)行實(shí)現(xiàn)。
0.內(nèi)置的漫反射光照首先,我們根據(jù)上一節(jié)所學(xué),寫一個依靠內(nèi)置的蘭伯特光照模式的漫反射光的Surface Shader: Shader '淺墨Shader編程/Volume7/33.內(nèi)置的漫反射' { //--------------------------------【屬性】---------------------------------- Properties { _MainTex ('【主紋理】Texture', 2D) = 'white' {} } //--------------------------------【子著色器】---------------------------------- SubShader { //-----------子著色器標(biāo)簽---------- Tags { 'RenderType' = 'Opaque' } //-------------------開始CG著色器編程語言段----------------- CGPROGRAM //【1】光照模式聲明:使用蘭伯特光照模式 #pragma surface surf Lambert //【2】輸入結(jié)構(gòu) struct Input { float2 uv_MainTex; }; //變量聲明 sampler2D _MainTex; //【3】表面著色函數(shù)的編寫 void surf (Input IN, inout SurfaceOutput o) { //從主紋理獲取rgb顏色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------結(jié)束CG著色器編程語言段------------------ ENDCG } Fallback 'Diffuse' } 實(shí)現(xiàn)效果:
1.簡單的高光光照模型
下面是一個簡單的高光光照模式(specular lighting model)Shader。實(shí)際上他就是Unity內(nèi)置的Blinn-Phong光照模型,實(shí)際上做起來并不困難。這邊我們將它單獨(dú)拿出來實(shí)現(xiàn)一下:
Shader '淺墨Shader編程/Volume7/34.自定義高光' { //--------------------------------【屬性】---------------------------------- Properties { _MainTex ('【主紋理】Texture', 2D) = 'white' {} } //--------------------------------【子著色器】---------------------------------- SubShader { //-----------子著色器標(biāo)簽---------- Tags { 'RenderType' = 'Opaque' } //-------------------開始CG著色器編程語言段----------------- CGPROGRAM //【1】光照模式聲明:使用自定義的光照模式 #pragma surface surf SimpleSpecular //【2】實(shí)現(xiàn)自定義的光照模式SimpleSpecular half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) { half3 h = normalize (lightDir + viewDir); half diff = max (0, dot (s.Normal, lightDir)); float nh = max (0, dot (s.Normal, h)); float spec = pow (nh, 48.0); half4 c; c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2); c.a = s.Alpha; return c; } //【3】輸入結(jié)構(gòu) struct Input { float2 uv_MainTex; }; //變量聲明 sampler2D _MainTex; //【4】表面著色函數(shù)的編寫 void surf (Input IN, inout SurfaceOutput o) { //從主紋理獲取rgb顏色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------結(jié)束CG著色器編程語言段------------------ ENDCG } //“備胎”為普通漫反射 Fallback 'Diffuse' } 實(shí)現(xiàn)效果:
2.自制簡單的Lambert光照
對應(yīng)于Unity內(nèi)建的Lambert光照,我們可以自定義原理類似的光照模式,實(shí)現(xiàn)自己Lambert光照:
Shader '淺墨Shader編程/Volume7/35.自制簡單的Lambert光照' { //--------------------------------【屬性】---------------------------------------- Properties { _MainTex ('【主紋理】Texture', 2D) = 'white' {} } //--------------------------------【子著色器】---------------------------------- SubShader { //-----------子著色器標(biāo)簽---------- Tags { 'RenderType' = 'Opaque' } //-------------------開始CG著色器編程語言段----------------- CGPROGRAM //【1】光照模式聲明:使用自制的蘭伯特光照模式 #pragma surface surf QianMoLambert //【2】實(shí)現(xiàn)自定義的蘭伯特光照模式 half4 LightingQianMoLambert (SurfaceOutput s, half3 lightDir, half atten) { half NdotL =max(0, dot (s.Normal, lightDir)); half4 color; color.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2); color.a = s.Alpha; return color; } //【3】輸入結(jié)構(gòu) struct Input { float2 uv_MainTex; }; //變量聲明 sampler2D _MainTex; //【4】表面著色函數(shù)的編寫 void surf (Input IN, inout SurfaceOutput o) { //從主紋理獲取rgb顏色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------結(jié)束CG著色器編程語言段------------------ ENDCG } Fallback 'Diffuse' } 實(shí)現(xiàn)效果如下:
3.自定義的半Lambert光照接下來,讓我們自制一個半Lambert光照。 Lambert定律認(rèn)為,在平面某點(diǎn)漫反射光的光強(qiáng)與該反射點(diǎn)的法向量和入射光角度的余弦值成正比(即我們之前使用dot函數(shù)得到的結(jié)果)。Half Lambert最初是由Valve(大V社)提出來的,用于提高物體在一些光線無法照射到的區(qū)域的亮度的。 簡單說來,半Lambert光照提高了漫反射光照的亮度,使得漫反射光線可以看起來照射到一個物體的各個表面。 而半Lambert最初也是被用于《半條命2》的畫面渲染,為了防止某個物體的背光面丟失形狀并且顯得太過平面化。這個技術(shù)是完全沒有基于任何物理原理的,而僅僅是一種感性的視覺增強(qiáng)。 遮蔽的漫反射-漫反射光照的一種改進(jìn)。照明'環(huán)繞(wraps around)'在物體的邊緣。它對于假冒子表面(subsurface)散射效果(scattering effect)非常有用。
半Lambert光照Shader的代碼如下:
Shader '淺墨Shader編程/Volume7/36.自制半Lambert光照' { //--------------------------------【屬性】---------------------------------------- Properties { _MainTex ('【主紋理】Texture', 2D) = 'white' {} } //--------------------------------【子著色器】---------------------------------- SubShader { //-----------子著色器標(biāo)簽---------- Tags { 'RenderType' = 'Opaque' } //-------------------開始CG著色器編程語言段----------------- CGPROGRAM //【1】光照模式聲明:使用自制的半蘭伯特光照模式 #pragma surface surf QianMoHalfLambert //【2】實(shí)現(xiàn)自定義的半蘭伯特光照模式 half4 LightingQianMoHalfLambert (SurfaceOutput s, half3 lightDir, half atten) { half NdotL =max(0, dot (s.Normal, lightDir)); //在蘭伯特光照的基礎(chǔ)上加上這句,增加光強(qiáng) float hLambert = NdotL * 0.5 + 0.5; half4 color; //修改這句中的相關(guān)參數(shù) color.rgb = s.Albedo * _LightColor0.rgb * (hLambert * atten * 2); color.a = s.Alpha; return color; } //【3】輸入結(jié)構(gòu) struct Input { float2 uv_MainTex; }; //變量聲明 sampler2D _MainTex; //【4】表面著色函數(shù)的編寫 void surf (Input IN, inout SurfaceOutput o) { //從主紋理獲取rgb顏色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------結(jié)束CG著色器編程語言段------------------ ENDCG } Fallback 'Diffuse' } 實(shí)現(xiàn)效果如下:
4.自定義卡通漸變光照
下面,我們一起實(shí)現(xiàn)一個自定義卡通漸變光照,通過一個不同的漸變紋理(漸變紋理可由PS制作),實(shí)現(xiàn)各種不同的漸變效果。 自定義卡通漸變光照Shader代碼如下: Shader '淺墨Shader編程/Volume7/37.自定義卡通漸變光照' { //--------------------------------【屬性】---------------------------------------- Properties { _MainTex ('【主紋理】Texture', 2D) = 'white' {} _Ramp ('【漸變紋理】Shading Ramp', 2D) = 'gray' {} } //--------------------------------【子著色器】---------------------------------- SubShader { //-----------子著色器標(biāo)簽---------- Tags { 'RenderType' = 'Opaque' } //-------------------開始CG著色器編程語言段----------------- CGPROGRAM //【1】光照模式聲明:使用自制的卡通漸變光照模式 #pragma surface surf Ramp //變量聲明 sampler2D _Ramp; //【2】實(shí)現(xiàn)自制的卡通漸變光照模式 half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) { //點(diǎn)乘反射光線法線和光線方向 half NdotL = dot (s.Normal, lightDir); //增強(qiáng)光強(qiáng) half diff = NdotL * 0.5 + 0.5; //從紋理中定義漸變效果 half3 ramp = tex2D (_Ramp, float2(diff,diff)).rgb; //計(jì)算出最終結(jié)果 half4 color; color.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2); color.a = s.Alpha; return color; } //【3】輸入結(jié)構(gòu) struct Input { float2 uv_MainTex; }; //變量聲明 sampler2D _MainTex; //【4】表面著色函數(shù)的編寫 void surf (Input IN, inout SurfaceOutput o) { //從主紋理獲取rgb顏色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } //-------------------結(jié)束CG著色器編程語言段------------------ ENDCG } Fallback 'Diffuse' } 我們?nèi)〔煌臐u變紋理,可得到不同的效果。以下是五種不同漸變紋理和對應(yīng)的效果圖。 第一組: 第二組: 第三組: 第四組:
第五組:
5.自定義卡通漸變光照v2讓我們在上面這個Shader的基礎(chǔ)上,加入更多可選的屬性,成為一個功能完備的漸變光照Shader: Shader '淺墨Shader編程/Volume7/38.自定義卡通漸變光照v2' { //--------------------------------【屬性】---------------------------------------- Properties { _MainTex ('【主紋理】Texture', 2D) = 'white' {} _Ramp ('【漸變紋理】Ramp Texture', 2D) = 'white'{} _BumpMap ('【凹凸紋理】Bumpmap', 2D) = 'bump' {} _Detail ('【細(xì)節(jié)紋理】Detail', 2D) = 'gray' {} _RimColor ('【邊緣顏色】Rim Color', Color) = (0.26,0.19,0.16,0.0) _RimPower ('【邊緣顏色強(qiáng)度】Rim Power', Range(0.5,8.0)) = 3.0 } //--------------------------------【子著色器】---------------------------------- SubShader { //-----------子著色器標(biāo)簽---------- Tags { 'RenderType'='Opaque' } LOD 200 //-------------------開始CG著色器編程語言段----------------- CGPROGRAM //【1】光照模式聲明:使用自制的卡通漸變光照模式 #pragma surface surf QianMoCartoonShader //變量聲明 sampler2D _MainTex; sampler2D _Ramp; sampler2D _BumpMap; sampler2D _Detail; float4 _RimColor; float _RimPower; //【2】實(shí)現(xiàn)自制的卡通漸變光照模式 inline float4 LightingQianMoCartoonShader(SurfaceOutput s, fixed3 lightDir, fixed atten) { //點(diǎn)乘反射光線法線和光線方向 half NdotL = dot (s.Normal, lightDir); //增強(qiáng)光強(qiáng) half diff = NdotL * 0.5 + 0.5; //從紋理中定義漸變效果 half3 ramp = tex2D (_Ramp, float2(diff,diff)).rgb; //計(jì)算出最終結(jié)果 half4 color; color.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2); color.a = s.Alpha; return color; } //【3】輸入結(jié)構(gòu) struct Input { //主紋理的uv值 float2 uv_MainTex; //凹凸紋理的uv值 float2 uv_BumpMap; //細(xì)節(jié)紋理的uv值 float2 uv_Detail; //當(dāng)前坐標(biāo)的視角方向 float3 viewDir; }; //【4】表面著色函數(shù)的編寫 void surf (Input IN, inout SurfaceOutput o) { //先從主紋理獲取rgb顏色值 o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; //設(shè)置細(xì)節(jié)紋理 o.Albedo *= tex2D (_Detail, IN.uv_Detail).rgb * 2; //從凹凸紋理獲取法線值 o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); //從_RimColor參數(shù)獲取自發(fā)光顏色 half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); o.Emission = _RimColor.rgb * pow (rim, _RimPower); } //-------------------結(jié)束CG著色器編程語言段------------------ ENDCG } FallBack 'Diffuse' } 我們將此Shader編譯后賦給材質(zhì),得到如下效果:
可供調(diào)節(jié)的屬性非常多,稍微放幾張效果圖,剩下的大家可以下載工程源代碼,或者拷貝Shader代碼,自己回去調(diào)著玩吧~
布料細(xì)節(jié)紋理+灰白漸變紋理+紅色邊緣光:
布料細(xì)節(jié)紋理+灰白漸變紋理+淺綠色邊緣光:
布料細(xì)節(jié)紋理+灰白漸變紋理+白色邊緣光:
布料細(xì)節(jié)紋理+灰白漸變紋理+無邊緣光(黑色):
五、場景搭建
以大師級美工鬼斧神工的場景作品為基礎(chǔ),淺墨調(diào)整了場景布局,加入了音樂,并加入了更多高級特效,于是便得到了如此這次比較唯美的靜謐之秋場景。
運(yùn)行游戲,樹影搖曳,我們來到金黃色的豐收之秋。
最后,放一張本篇文章中實(shí)現(xiàn)的Shader全家福:
OK,美圖就放這么多。游戲場景可運(yùn)行的exe可以在文章開頭中提供的鏈接下載。而以下是源工程的下載鏈接。
本篇文章的示例程序源工程請點(diǎn)擊此處下載:
【淺墨Unity3D Shader編程】之七 靜謐之秋篇配套Unity工程下載
Unity Shader系列文章到目前已經(jīng)更新了7篇,一共實(shí)現(xiàn)了38個詳細(xì)注釋、循序漸進(jìn)、功能各異的Shader,對Unity中的固定功能Shader、Surface Shader都已經(jīng)有了比較詳細(xì)、系統(tǒng)的講解和實(shí)現(xiàn)。而可編程Shader按學(xué)習(xí)計(jì)劃來說是以后的計(jì)劃,目前還是未涉及,有機(jī)會在以后的文章中一起和大家一起探討。 而大家如果仔細(xì)參考和閱讀這七篇文章,會發(fā)現(xiàn)Unity中Shader的書寫其實(shí)是非常容易和有章可循的。這大概就是淺墨寫這個系列文章的初衷吧。 天下沒有不散的宴席。 淺墨接下來的一段時間有一些大的游戲項(xiàng)目要接觸,所以,Unity Shader系列文章每周周一的固定更新只能改為不定期的更新了。以后淺墨有了空余時間,會繼續(xù)寫博文來與大家交流分享。 OK,于未來某天更新的下篇文章中,我們后會有期。:)
|
|
|