编写Shader时的一些性能考虑

编写shader时的一些建议:
1、只计算需要计算的东西;
2、通常,需要渲染的像素比顶点数多,而顶点数又比物体数多很多。所以如果可以,尽量将运算从PS移到VS,或直接通过script来设置某些固定值;
3、在使用Surface Shader时,可以通过一些指令让shader优化很多。
  通常情况下,Surface shader的很多默认选项都是开启的,以适应大多数情况,但是很多时候,你可以关闭其中的一些选项,从而让你的shader运行的更快:
  (1) approxview 对于使用了view direction的shader,该选项会让view dir的normalize操作per-vertex进行,而不是per-pixel。这个优化通常效果明显。
  (2) halfasview 可以让Specular shader变得快一些,使用一个介于光照方向和观察方向之间的half vector来代替真正的观察方向viewDir来计算光照函数。
  (3) noforwardadd Forward Render时,完全只支持一盏方向光的per-pixel渲染,其余的光照全部按照per-vertex或SH渲染。这样可以确保shader在一个pass里渲染完成。
  (4) noambient 禁掉ambient lighting和SH lighting,可以让shader快一点儿。
4、浮点数精度相关:
  float:最高精度,通常32位
  half:中等精度,通常16位,-60000到60000,
  fixed:最低精度,通常11位,-2.0到2.0,1/256的精度。
  尽量使用低精度。对于color和unit length vectors,使用fixed,其他情况,根据取值范围尽量使用half,实在不够则使用float。
  在移动平台,关键是在fragment shader中尽可能多的使用低精度数据。另外,对于多数移动GPU,在低精度和高精度之间转换是非常耗的,在fixed上做swizzle操作也是很费事的。
5、Alpha Test
  Alpha test和clip()函数,在不同平台有不同的性能开销。
  通常使用它来cull那些完全透明的像素。
  但是,在ios和一些android上使用的PowerVR GPUs上面,alpha test非常的昂贵。
 6、Color Mask
  在移动设备上,Color Mask也是非常昂贵的,所以尽量别使用它,除非真的是需要。

 

shader多版本编译:
shader variants(shader 变种)使用方式:
(1)#pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON
(2)#pragma shader_feature FANCY_STUFF_OFF FANCY_STUFF_ON
  #pragma shader_feature FANCY_STUFF是#pragma shader_feature _ FANCY_STUFF的快捷方式,同样会生成两个变种

shader_feature和multi_compile的区别:
  shader_feature:未使用的变种不会build进游戏;
  multi_compile:会编译生成所有变种。
  用法:shader_feature更适用于材质的关键字,而multi_compile更适用于代码设置的全局关键字。

关键字个数限制:
  unity最多支持256个关键字,并且unity内部已经使用了60个左右。另外,可以在unity的工程设置中定义一些全局有效的关键字,这样也会消耗一些数量,所以在编写shader时要注意数量不要超过上限。

内置的multi_compile快捷组合:
  #pragma multi_compile_fwdbase 编译ForwardBase需要的所有关键字变种,包括不同的lightmap类型,主要的方向光是否开启阴影等。
  #pragma multi_compile_fwdadd 编译ForwardAdd Pass包含的关键字变种。
  #pragma multi_compile_fwdadd_fullshadows 和上一个类似,另外还包含了光照实施阴影的能力。
  #pragma ulti_compile_fog 雾效。
  上面内置的快捷方式包含了很多的变种,但可以通过skip_variants来屏蔽某些关键字:
  #pragma skip_variants POINT POINT_COOKIE

硬件级别shader变种:
  提供针对不同硬件(比如gles和gles 3.0)的shader变种。(针对硬件能力级别的优化)
  #pragma hardware_tier_variants renderer
    d3d11 - Direct3D 11/12
    glcore - OpenGL 3.x/4.x
    gles - OpenGL ES 2.0
    gles3 - OpenGL ES 3.x
    metal - iOS
    /Mac Metal
    vulkan - Vulkan
    d3d11_9x - Direct3D 11 9.x feature level, as commonly used on WSA platforms
    xboxone - Xbox One
    ps4
    - PlayStation 4
    psp2 - PlayStation Vita
    n3ds - Nintendo 3DS
    wiiu - Nintendo Wii U
  添加了上述#pragma的shader会自动生成三个关键字变种:
    UNITY_HARDWARE_TIER1
    UNITY_HARDWARE_TIER2
    UNITY_HARDWARE_TIER3
  编辑器模式下,可以在Graphics Emulation中来手动设置使用哪个变体。
  上述三中变体,同时只会加载其中一种,
  指定方式:
    (1)自动检测:在加载时,Unity检测GPU并进行设置;如果检测不到,默认选择最高级。
    (2)手动设置来制定使用哪一个tier,代码如下:(一定是在shader加载之前制定,在某个shader加载之后再指定是不会影响该shader的)
    Graphics.activeTier = UnityEngine.Rendering.GraphicsTier.Tier1;

  平台shader设置:
    可以通过代码手动设置[平台, tier, 设置]
    UnityEditor.Rendering.EditorGraphicsSettings.SetTierSettings(BuildTargetGroup target, GraphicsTier tier, TierSettings settings);
    

 



posted @ 2015-08-10 00:29  斯芬克斯  阅读(11153)  评论(0编辑  收藏  举报