2017年9月6日

Unity 画質設定に応じてシェーダーの処理を切り替える


シェーダーのLODを利用して処理内容を変える方法をメモメモ…


※このページの内容の動作確認にはUnity5.6を使用しています。
組み込みのシェーダーを眺めていると「LOD 200」とか「LOD 300」などと記述されている行があります。シェーダーでのLOD(Level of Detail)というのは「設定された値がこの数値以上の場合のみこの方法で描画する」という、処理を実行するかしないかの基準となる値のことですね。

使い方はこちらのページに非常にわかりやすくまとめられています。
UnityのシェーダーLODを調べてみた

では、実際どういう場面で使えばいいかというと、たとえばハードウェアのスペックに応じて処理を変える場合や、オブジェクトがカメラから離れたときにもっと単純なエフェクトに切り替える場合などです。計算量の多い処理をもっと軽い処理に置きかえたい!というときに、いちいちマテリアルやシェーダーを丸ごととっかえなくてもLODの値さえ変更すればいいので手軽で便利だと思います。

具体例を見てみましょう。

  1. Shader "Custom/Cutout Double-sided With LOD"
  2. {
  3. Properties
  4. {
  5.   _Cutoff ("Cutoff", Range(0,1)) = 0.5
  6.   _Color ("Color", Color) = (1,1,1,1)
  7.   _MainTex ("Albedo (RGB)", 2D) = "white" {}
  8.   _Glossiness ("Smoothness", Range(0,1)) = 0.5
  9.   _Metallic ("Metallic", Range(0,1)) = 0.0
  10. }
  11.  
  12. // 高画質設定用(LOD300)
  13. SubShader
  14. {
  15.   LOD 300
  16.   Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" }
  17.   Cull Off
  18.   
  19.   CGPROGRAM
  20.   // (中略)
  21.   ENDCG
  22. }
  23.  
  24. // 中画質設定用(LOD200)
  25. SubShader
  26. {
  27.   LOD 200
  28.   Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" } 
  29.   Cull Off
  30.   
  31.   CGPROGRAM
  32.   // (中略)
  33.   ENDCG
  34. }
  35. // 低画質設定用(LOD100)
  36. SubShader
  37. {
  38.   LOD 100
  39.   Tags { "Queue"="Transparent" "RenderType"="Transparent" "ForceNoShadowCasting" = "True" }
  40.   Cull Off
  41.   Lighting Off
  42.   ZWrite Off
  43.   Fog { Mode Off }
  44.   Blend One OneMinusSrcAlpha
  45.  
  46.   Pass
  47.   {
  48.    CGPROGRAM
  49.    // (中略)
  50.    ENDCG
  51.   }
  52. }
  53.  
  54. FallBack "Sprites/Default"
  55. }

このシェーダーでは、SubShaderごとに高画質用(LOD300)、中画質用(LOD200)、低画質用(LOD100)を用意しています。LODの値は適当なので勝手に変更しても構いません。公式のマニュアルページでは組み込みシェーダーで設定されているLODの値がまとめられているので、それを目安にしてもいいかも。

あとはスクリプト側からこのシェーダーを参照しておいて…

switch(graphicQuality)
{case GraphicQuality.High: targetShader.maximumLOD = 300; break;case GraphicQuality.Medium: targetShader.maximumLOD = 200; break;case GraphicQuality.Low: targetShader.maximumLOD = 100; break;default: targetShader.maximumLOD = 50; break;
}

…というようにゲーム内の画質設定に応じて対象のLODを変更すればOK。個別のシェーダーを指定するのがめんどくさい場合は、Shader.globalMaximumLODですべてのシェーダーのLODを一気に設定することも可能です。

ちなみに、もし仮にLODですべてのSubShaderがはじかれた場合はFallBackに指定されたシェーダーが実行されます。上の例の場合、LODに50を設定するとFallBackに指定されているSprites/Defaultシェーダーで描画されることになります。

スプライトの描画方法を切り替え(なんかキモい…)

処理速度も変化

こんな感じで、ゲームの実行中にボタンひとつでシェーダーの処理内容を切り替えることができるようになりました。上の画像では影をなくし単純なUnlit系の描画にしたことで処理速度が向上しています。実際にオプションメニューなどで画質設定項目を用意する場合はQualitySettings(BeautifulとかFantasticとかのアレ)と組み合わせることになると思います。

ただ、このままだとシェーダー自体のLODの値を直接書き換えることになるのでもしかしたら何か対策したほうがいいのかも…

0 件のコメント:

コメントを投稿