【Reading Notes】cp7-Mobile Shader Adjustment(移动平台下的shader)

写在前面

在接下来两个章节,将要学习怎样使Shader在不同平台下都有良好的表现。我们不去讨论任何一个特定的平台,而是去分解Shader中我们可以进行调整的各个部分,讨论一般情况下的移动平台优化。这其中包括了,Unity内置变量的介绍,如何减少Shader内存等等。
+ 什么是Cheap shader
+ 分析你的shader
+ 为移动平台修改shader

Introdudction

shader的优化,几乎在每一个游戏项目都会遇到。常常有一个关注的点,例如用更新的纹理实现相同的效果。作为一个技术美术,一个shader程序员,你必须明白shader优化的基本原理,这样才可以实现性能提高的同时保持相对较好的效果。拥有了这些知识,还会对你编写shader有所帮助。例如,你知道你们游戏是运行于移动设备之上的,我们可以把所有的光照函数使用Half vector近似模拟,而不是直接计算反射向量。

什么是廉价(Cheap)的shader

这又点难以回答,对于shader有很方面可以去做优化是的它更有效率。有可能是内存纹理,纹理数量问题,有可能是shader本身很好的工作,但我们可以使用更少的数据,代码去实现相同的效果。我们需要去探索这些相关的技术,和怎么样去组合它们使得你的shader又快有保持一定的高质量效果,无论在PC还是移动设备上。

几个优化方面:
+ ### 数据类型
+ Float: 32位,浮点数, 精度高,但在3中浮点数中最慢。
+ Half: 16位,浮点数,[-60000, 60000], 精确到小数点后3位,适合存储UV值,颜色值,比float要快。
+ Fixed: 通常是11位,定点数?范围在[-2, 2] 精度1/256,这个精度设置非常适合颜色运算。

  • ### noforwardadd: 告诉Unity 使用了改shader的物体仅仅对一个方向向量进行逐像素处理(pre-pixel),任何其光照都将以Spherical Harmonic(SH)一种非常简单效率的光照模型,unity内置。当我们继续在场景中放置一个点光源,可以明显看到,对点光源的计算并没有NormalMap的凹凸信息,因为我们的Shader对于法相贴图的计算是逐像素的。
    image

那么,很多时候我们想要去控制那个作为主光源进行逐像素的计算?这可以同光光源的Inspector面板上的RenderMode进行控制,有3个选项
+ Auto 由Unity决定最佳的行为。
+ Important 尽可能进行逐像素处理
+ Not Important 进行逐顶点处理
通过这些选项你可以告诉Unity那些光源应该更应该被认为是需要逐像素处理的光源,反之,那些不应该进行逐像素处理。

  • ### exclude_pass: 说明这个shader不接受任何源自于deffered renderer(延迟渲染)。

shader code

Shader "CookbookShaders/self/OptimizeShader001" {
    Properties {
        _MainTex ("Base (RBG)", 2D)="white"{}
        _NormalMap("Normal Map", 2D)="bump"{}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        //define light function ourself, noforwardadd?
        //excluce_path:prepass 
        #pragma surface surf SimpleLambert excluce_path:prepass  noforwardadd

        sampler2D _MainTex;
        sampler2D _NormalMap;

        struct Input {
            half2 uv_MainTex; //float2 to half2 ,save data
            //half2 uv_NormalMap; remove uv of normalmap ,because same as uv maintex
        };

        inline float4 LightingSimpleLambert(SurfaceOutput s, float3 lightDir, float atten)
        {
            //float to fixed save data
            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;
        }

        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
            o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Profiling you shader 分析你的Shader

Unity提供的Prefiling可以让我们实时的了解运行过程中,每一个对象对于各种资源的消耗。
更多信息可以参考官方文档:https://docs.unity3d.com/Manual/MobileProfiling.html

为移动设备修改Shader

到现在我们实践过一些Shader的优化技巧,现在让我们来看看怎么为移动平台写一个漂亮,高质量的Shader。

Shader "CookbookShaders/self/mobilespeclar" {
    Properties{
        _Diffuse("Base (RGB) Specular Amount (A)", 2D) = "white" {}
    _SpecIntensity("Specular Width", Range(0.01, 1)) = 0.5
        _NormalMap("Normal Map", 2D) = "bump" {}
    }
        SubShader{
        Tags{ "RenderType" = "Opaque" }
        LOD 200

        CGPROGRAM
        //define light function ourself, noforwardadd only one direct light should per-pixel
        //excluce_path:prepass 
        //halfasview
#pragma surface surf MobileBlinnPhong  nolightmap noforwardadd halfasview

        sampler2D _Diffuse;
        sampler2D _NormalMap;
        fixed _SpecIntensity;

    struct Input {
        half2 uv_Diffuse;
    };

    inline float4 LightingMobileBlinnPhong(SurfaceOutput s, fixed3 lightDir, fixed 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;
    }

    void surf(Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(_Diffuse, IN.uv_Diffuse);
        o.Albedo = c.rgb;
        o.Alpha = 0.0;
        o.Specular = _SpecIntensity;
        o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_Diffuse));
    }
    ENDCG
    }
        FallBack "Diffuse"
}
  • nolightmap: 关闭lightmap check
  • noforwawrdadd: 如前面所说
  • halfasview: 计算高光是使用viewDir与lightDir的中间向量代替反射向量。

最后,需要知道保证只使用你真正所需要的数据,要对游戏在目标平台下的效果做权衡。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值