Unity – URP学習
- Baked GI ライティング
- 静的なオブジェクトに対するライトエフェクトをライトマップに書き込む = ベイクするということ。
- エディタで static オブジェクトに変更が加えられると裏でベイクの計算が走る。
- フォワードレンダリング
- ライトごとにモデルを描画する ⇒ ピクセルシェーダが起動した際にライト数分の処理があるということ。
- MSAA をかけれる
- ライト数が多いとコストが増える
- ディファードレンダリング
- G-Bufferパス
ディフューズ色、スペキュラー色、サーフェスのスムースネス 、ワールド空間法線と、エミッション + アンビエント + リフレクション + ライトマップは、G バッファテクスチャにレンダリングされます。 - ライティングパス
- G-Bufferパス
- SRP バッチャー
- SRP のカスタム
https://docs.unity3d.com/ja/current/Manual/srp-creating-simple-render-loop.html
ここも↑と一緒に読むといい
https://catlikecoding.com/unity/tutorials/custom-srp/custom-render-pipeline/
詳細は後述 - unlit シェーダー
「ライトの影響を受けないシェーダー」です。 設定されたColorやTextureがそのまま描画されるので、ゲームではライトの影響を受ける必要のないUIやフラットな絵作りをする際に使われます。
カスタムSRPチュートリアル
レンダーパイプラインアセットの追加
- C#: RenderPipelineAsset を記述
Editor の UI から RenderPipeline をインスタンス化できるようにするためのコード。作った RenderPipeline を Editor から選択できるようになる。 - C#: RenderPipelineInstance を記述
ユーザー定義のレンダーパイプライン(描画コマンド)を記述する。RenderPipelineAsset からインスタンス化される。 - RenderPipeline アセットをプロジェクトに追加
Create > Rendering > RenderPipelineAsset.cs で記述した名前をクリックする。この例では Example Custom Render Pipeline
- 追加した RenderPipeline アセットを使用する
Project Settings > Graphics で SRP Setting をクリックし RenderPipelineAsset を設定する
シェーダーアセットの追加
- シェーダーセットとは .shader 拡張子を持つファイル。
- シェーダーアセットの作成
メインメニューまたは Project ウィンドウ のコンテキストメニューから Assets > Create > Shader の順に選択します。 - コンパイルされたシェーダーの確認
シェーダーアセットを選択し、Inspector > Compiled code で確認できる。 - LightMode パスタグを設定する
123456789// Material の Inspector からシェーダーをアサインする際に Examples のディレクトリが掘られる。Shader "Examples/SimpleUnlitColor"{SubShader{Pass{// LightMode パスタグの値は、ScriptableRenderContext.DrawRenderers の ShaderTagId と一致する必要があります。Tags { "LightMode" = "ExampleLightModeTag"} - a
Material にシェーダーを追加する
Material の詳細は後述の Material の項を参照。
- シェーダーのアサイン
Shader のプルダウンを開いてアサインしたいシェーダーを選択する。
あ
- Create 3D Project – 1 から作るので URP プロジェクトを指定したらダメ。
ShaderTagId
分からん
- 作ったシェーダーが属するパスをどこで設定するのか?eg. SRPDefaultUnlit にどうやってシェーダーを含めるのか?
RenderQueue
分からん
Matrial
Material が持つ参照
- シェーダーオブジェクト
- シェーダーオブジェクトのマテリアルプロパティ
- TODO: マテリアルプロパティの定義をしてみる。
URP
サンプル(デバググループ)を仕込む方法
- BeginSample(name) の直後で ExecuteCommandBuffer() を呼ばないとデバググループが開始されない。下記のお作法に従うこと。
12345678910111213buffer.BeginSample(bufferName);context.ExecuteCommandBuffer(buffer);buffer.Clear();/* そのパスの各種処理 */buffer.EndSample(bufferName);context.ExecuteCommandBuffer(buffer);buffer.Clear();context.Submit();}
マテリアルのオーバーライド
SRP ではマテリアルをオーバーライドできる。ここでは、未サポートのレガシーシェーダーを Unity が内部的に持っているエラーシェーダー “Hidden/InternalErrorShader” に書き換える例を示す。このシェーダーはマゼンダを書きだす。エラーシェーダーに差し替える動機は SRP 非対応のシェーダーを使った場合の挙動が未定義であること、FrameDebugger で見た時にそれが何か分かり難いなどが挙げられる。レガシーシェーダーを FrameDebugger で見たら↓のようになる。
これをエラーシェーダーに書き換えると下記のようになり分かりやすくなる。(まぁ、Used Shader をダブルクリックしたらシェーダに飛べるので分かるけども)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void DrawUnsupportedShaders() { if (errorMaterial == null) { // エラーシェーダを持つマテリアルを new する errorMaterial = new Material(Shader.Find("Hidden/InternalErrorShader")); } var drawingSettings = new DrawingSettings(legacyShaderTagIds[0], new SortingSettings(camera)) { // 描画設定でマテリアルを上書きする overrideMaterial = errorMaterial }; var filteringSettings = FilteringSettings.defaultValue; for (int i = 1; i < legacyShaderTagIds.Length; ++i) { drawingSettings.SetShaderPassName(i, legacyShaderTagIds[i]); } context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings); } |
マテリアルのオーバーライドを Editor だけで行う
partial クラスを実装して partial クラスのメソッドを #if UNITY_EDITOR で分岐してやればよい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
partial class CameraRenderer { // TODO: これを呼び出せるらしい。 partial void DrawUnsupportedShaders(); #if UNITY_EDITOR static ShaderTagId[] legacyShaderTagIds = { new ShaderTagId("Always"), new ShaderTagId("ForwardBase"), new ShaderTagId("PrepassBase"), new ShaderTagId("Vertex"), new ShaderTagId("VertexLMRGBM"), new ShaderTagId("VertexLM") }; static Material errorMaterial; partial void DrawUnsupportedShaders() { if (errorMaterial == null) { errorMaterial = new Material(Shader.Find("Hidden/InternalErrorShader")); } var drawingSettings = new DrawingSettings(legacyShaderTagIds[0], new SortingSettings(camera)) { overrideMaterial = errorMaterial }; ... } #endif } |
描画基本事項の学習
半透明オブジェクトはBack to Frontで描画する
- 半透明描画はデプスを更新しないのでFront to Backにする意味がない
- Back to Frontにしないとブレンド結果がおかしくなる
半透明オブジェクトの描画順序による差異 1
Cube: 不透明オブジェクト
Sphere: 半透明オブジェクト
- 半透明オブジェクト > 不透明オブジェクトの順番で描画
半透明オブジェクトはデプスを書かない設定になっているため、手前にある半透明オブジェクトが次の描画の不透明オブジェクトで上書きされてしまう。
- 不透明オブジェクト ⇒ 半透明オブジェクトの順番で描画
手前にある半透明オブジェクトが正しく描画※される。
※正確にはSkyBoxで半透明オブジェクトの一部が潰されている。「不透明->SkyBox->半透明」の順番で描画するのが正しい。
- 不透明(SkyBox含む)-> 半透明の描画順にした場合
半透明オブジェクトの描画順序による差異 2
半透明オブジェクトを back to front で描画しないといけない理由を調べる。
その前に半透明のブレンドについておさらい。一般的なブレンドは「透明度が高いと背景の色が強く出る」これを式に表すと下記のようになる。
dstColor = srcAlpha * srcColor + (1 – srcAlpha) * dstColor
上記ブレンド式の時、front to back で描画するとカメラから見て後方にあるオブジェクトのアルファ値でブレンドするので絵がおかしくなる。一番手前がほぼ不透明のアルファ = 0.9 だとしても、その後ろのオブジェクトで透けてしまうと言うと分かりやすいだろうか。
TODO: 実験
- front to back で描画した場合
- ⇒ 半透明描画のパスを書いていないのでペンディング。
UV sphere map
コメントを残す