• 【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只工作在特定的渲染器上,使用近似值代替精确值,以及减少或压缩贴图。








  • 相关阅读:
    codeforces Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) C. Constellation
    codeforces Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) B Guess the Permutation
    codeforces Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) A Slime Combining(栈)
    在服务器IIS中添加新网站后打开网站需要用户名和密码时怎么办?
    简易通讯录
    先列出所有数据库,再删除其中一个数据库。
    数据库创建mysql_query($sql,$link)
    显示所有数据库 mysql_fetch_object()
    读取数据库数据
    PHP警告错误处理办法
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6314679.html
Copyright © 2020-2023  润新知