Unity シェーダーメモ
最終更新日:2024年09月12日記事作成日:2022年01月31日
Unityのシェーダー周りについてのメモです。書きはじめたばかりなのでまだ内容は薄いです。
更新履歴
(2024年9月12日)Built in shadersのダウンロード場所が変更されているのを反映
(2022年5月13日)「シェーダーのコンパイル時間を短くしたい」を拡充
(2022年1月31日)とりあえずページ作成
PBRマテリアルの検証
Standardシェーダーのマテリアルについて、Unity公式のマテリアルチャートにAlbedo、Metallic、Smoothnessの設定値のガイドがあります。
AlbedoのRGBについて非金属は50~243、金属は186~255にすることとなっています。Metallicについて、純粋な非金属は0.0、純粋な金属は1.0にしますが、錆びた金属等では中間の値に設定することもあるようです。
Sceneウィンドウの表示モードをValidate AlbedoまたはValidate Metal Specularに変更すると、シーン内のPBRマテリアルの検証ができます。Luminance Validationを変更するとWorn AsphaltやFresh Snow等、マテリアルが典型的な輝度の範囲に入っているかチェックできます。
シェーダーについて
最初に重要なことなのですが、RiderがUnityのシェーダーにデフォルトで対応していて非常に強力です。C#コードと同じくらいの快適さでシェーダーコードを書いたり定義に飛べるので、使用できるならぜひ使用したほうがいいです(Rider派)。
組み込みのシェーダーを改造する
シェーダーをゼロから書くよりも、既存のシェーダーの動作をちょっと変えたいケースのほうがおそらく多いと思います。
UnityのダウンロードアーカイブからUnityと同じバージョンのページを開き、Other installsを開いて「Shaders」でビルドインシェーダーのコード一式がダウンロードできます。アーカイブを展開して、Visual Studio Codeか何かでシェーダーの名前で全文検索すると該当のシェーダーファイルが見つかりますので、これをプロジェクトのフォルダーにコピーします。関連する.cginc等も必要な場合があります。
ShaderLab
UnityにはまずShaderLabという宣言型のシェーダー言語があり、拡張子.shaderのファイルでシェーダーを定義します。頂点・フラグメントシェーダをHLSLでインラインで記述します。
HLSL
HLSLはマイクロソフトが開発したC言語ライクなシェーダー言語で、以下のページに仕様解説があります。
High-level shader language (HLSL) - Win32 apps | Microsoft Docs
ShaderLabの中でHLSLPROGRAM … ENDHLSLのコードブロックで記述します。
Universal Render Pipeline対応について
SubShaderのTagsで"RenderPipeline" = “UniversalPipeline"を指定します。
その他、詳しくは凹みTipsを見てください。
シェーダーの演算量を確認したい
シェーダーの実行速度の目安を知りたい場合があります。Windowsプラットフォームでシェーダーをコンパイルすると頂点シェーダー・フラグメントシェーダーの平均演算数や平均テクスチャ参照数がコンパイル後のコメントに出力されます。
Standardシェーダーを軽くしたい
Project Settings > GraphicsでStandardシェーダーのクオリティが設定でき、品質を下げると上記のフラグメントシェーダーの演算数が大幅に減ります。
Standard Shader Quality: High
// Stats for Vertex shader:
// d3d11: 32 avg math (22..55)
// Stats for Fragment shader:
// d3d11: 156 avg math (137..176), 5 avg texture (3..7), 7 avg branch (6..8)
Standard Shader Quality: Medium
// Stats for Vertex shader:
// d3d11: 32 avg math (22..55)
// Stats for Fragment shader:
// d3d11: 123 avg math (103..143), 5 avg texture (3..7), 7 avg branch (6..8)
Standard Shader Quality: Low
// Stats for Vertex shader:
// d3d11: 32 avg math (22..55)
// Stats for Fragment shader:
// d3d11: 109 avg math (89..129), 6 avg texture (4..8), 7 avg branch (6..8)
チェックを全部はずす
// Stats for Vertex shader:
// d3d11: 31 avg math (22..52)
// Stats for Fragment shader:
// d3d11: 57 avg math (43..72), 3 texture
シェーダーのコンパイル時間を短くしたい
ビルド時に「Compiling shader variants」で大量のシェーダーバリアントのコンパイルが走る場合があります。
シェーダーを選択してインスペクタでCompiled codeをドロップダウンすると「XX variants included」でシェーダーバリアントの数が表示されています。Showを押すとビルド時に常に含まれるバリアントのキーワードの組み合わせが全部出てきますので、以下に紹介する方法でどうにかして減らすことを考えます。
機能を無効にする
たとえばビルトインレンダリングパイプラインのStandardシェーダーの場合、フォグを使用しない場合はProject Settings > GraphicsのFog ModesをCustomにして全部オフにするとバリアントの数が半減します。
なお、URPでRender Pipeline Assetsの不要な機能を無効にするというプラクティスがありましたが、Unity 2021.2からは効果がないようです(有効のときは有効のバリアントのみ、無効のときは無効のバリアントのみコンパイルされて数が変わらないようです)。
multi_compile等のキーワードを削減する
たとえばシェーダー中に
#pragma multi_compile KEYWORD_A1 KEYWORD_A2 KEYWORD_A3 KEYWORD_A4
#pragma multi_compile KEYWORD_B1 KEYWORD B2
等があると、組み合わせ爆発でコンパイル時間も爆発します。キーワードをできるだけ減らすようにします。
IPreprocessShadersを使用する
Unityはシェーダーバリアントをある程度自動的に減らそうとしますが、使用しないシェーダーバリアントをビルド時に完全に特定することはできません。たとえば実行時にライトのモードを変更すると別のシェーダーバリアントが必要になります。
このキーワードの機能は実行時に使用しないと分かっている場合は、IPreprocessShadersを実装したクラスを作成してバリアントをフィルタできます。
シェーダーを直接編集できる場合は、#pragma skip_variantsでスキップする方法もあります。
Graphics APIを減らす
Graphics APIの設定でたとえばOpenGL ES3とVulkanが両方有効になっているとそれぞれのシェーダーバリアントをコンパイルする必要があり、コンパイル時間が2倍になります。必要なAPIに絞ります。
トゥーンシェーダー
Unity Toon Shader
ユニティちゃんトゥーンシェーダーがUnityのパッケージcom.unity.toonshaderに昇格しつつあるようです。ビルトインに加え、URP、HDRPにも対応しています。
(2021年9月現在)インストールするにはPackage Managerでcom.unity.toonshaderを入力、さらにSamplesを開いて各レンダーパイプラインのサンプルをインポート。
Unity 2021.2.0b11ではUniversal Render Pipeline/Toonシェーダーのビルドに失敗する模様。Unity 2021.1、2020.3なら動作した。サンプルシーンのシェーダーがビルトイン版のToon (Built-in)になっているので、Universal Render Pipeline/Toonに変更。