【Unity Shaders】Mobile Shader Adjustment —— 为手机定制Shader

本系列主要參考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同一时候会加上一点个人理解或拓展。

这里是本书全部的插图。这里是本书所需的代码和资源(当然你也能够从官网下载)。

========================================== 切割线 ==========================================



写在前面


上一篇里,我们学习了一些技巧来初步优化Shader。这次,我们学习很多其它的技术来实现一个更复杂的Shader:Normal-Mapped Specular Shader。这些技术包含:使用光照函数的两个新变量halfasview或者approxview,降低使用的贴图数量,以及对贴图进行更好的压缩。



准备工作


  1. 创建一个新的场景和一个球体,加入一个平行光。
  2. 创建一个新的Shader和Material,能够命名为MobileShader。
  3. 把Shader赋给Material,把Material赋给球体。

实现


  1. 首先,还是改动Properties块。本节我们须要一张diffuse贴图,它的alpha通道值相应像素的光滑度(Gloss);以及一张法线贴图,和高光指数的滑动条。
    	Properties {
    		_Diffuse ("Base (RGB) Specular Amount (A)", 2D) = "white" {}
    		_NormalMap ("Normal Map", 2D) = "bump"{}
    		_SpecIntensity ("Specular Width", Range(0.01, 1)) = 0.5
    	}

    解释:一直没有彻底搞懂Unity SurfaceOutput里面各变量的计算细节。这里再详解下。SurfaceOutput里面的内置变量能够见这篇,例如以下:
    struct SurfaceOutput {  
        half3 Albedo;      // 该像素的反射率,反应了像素的基色 
        half3 Normal;     // 该像素的法线方向
        half3 Emission;   // 该像素的自发光颜色,使得即便没有光照也能够物体本身也能够发出光
        half Specular;     // 该像素的高光指数  
        half Gloss;         // 该像素的高光光滑度,值越大高光反射越清晰,反之越模糊  
        half Alpha;         // 该像素的不透明度 
    };

  2. 以下是建立#pragma声明。这能够控制Surface Shader各属性的开关,使得Shader更高效或者更低效:
    		CGPROGRAM
    		#pragma surface surf MobileBlinnPhong exclude_path:prepass nolightmap noforwardadd halfasview

    解释忽略延迟光照,不支持光照贴图,仅仅接受一个单一的平行光光源作为逐像素光源。最后,使用halfasview声明告诉Unity,我们使用一个介于光照方向和观察方向之间的half vector来取代真正的观察方向viewDir来计算光照函数。这将加速Shader的处理时间,由于这是基于逐顶点而非逐像素计算而得的。尽管这样得到的结果是近似值,但对于移动平台来说足够了。

  3. 建立和Properties块中各变量的联系。和之前不同,我们这次使用fixed来得到高光指数滑条的值:
    		sampler2D _Diffuse;
    		sampler2D _NormalMap;
    		fixed _SpecIntensity;

  4. 得到贴图的UV坐标。在上一篇就提过,为了节省变量空间,我们仅使用一个UV值:
    		struct Input 
    		{
    			half2 uv_Diffuse;
    		};

  5. 由于我们在声明中加入了新的变量,我们能够在光照函数中使用新的參数:
    		inline fixed4 LightingMobileBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 halfDir, fixed atten)
    		{
    			fixed diff = max (0, dot (s.Normal, lightDir));
    			fixed nh = max (0, dot (s.Normal, halfDir));
    			fixed spec = pow (nh, s.Specular * 128) * s.Gloss;
    			
    			fixed4 c;
    			c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);
    			c.a = 0.0;
    			return c;
    		}

  6. 最后,我们在surf函数中完毕对像素颜色的计算:
    		void surf (Input IN, inout SurfaceOutput o) 
    		{
    			fixed4 diffuseTex = tex2D (_Diffuse, IN.uv_Diffuse);
    			o.Albedo = diffuseTex.rgb;
    			o.Gloss = diffuseTex.a;
    			o.Alpha = 0.0;
    			o.Specular = _SpecIntensity;
    			o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_Diffuse));
    		}


最后,得到的效果例如以下:



解释


我们最后总结一下使用过的全部技术:优化变量类型,共享UV坐标,降低处理的光源个数,让Shader仅仅工作在特定的渲染器上,使用近似值取代精确值,以及降低或压缩贴图。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值