Unity HDRPをカスタマイズしてアウトラインパスを追加する
HDRPを弄れる環境はこちらで既に整えました
今回は実際にカスタマイズして周作に最適なアウトラインパスを追加してみます。(Render Graphがリリースされたらここの情報は無になります(多分...))
使用するバージョン
- Unity 2019.2.0f1
- HDRP 6.9.0-preview
今回のプロジェクトはこちらです。 github.com
Lit.shaderをカスタマイズしてアウトラインパスを追加する
大元となるのはHDRPのLit.shaderなので丸々コピーしてきてアウトラインパスを追加しましょう。
今回使うバージョンである6.9.0-previewの Lit.shader
はこちらです。
Lit.shader
にはいくつかのパスが既に記述されているので、それを参考にアウトラインを描画するパスを追加します。
Pass { Name "Outline" Tags { "LightMode" = "Outline" } // アウトライン用のパスのためカリング設定を反対にする Cull Front ZTest On ZWrite On HLSLPROGRAM #define SHADERPASS SHADERPASS_FORWARD #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/ShaderPass/LitSharePass.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitData.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl" PackedVaryingsType Vert(AttributesMesh inputMesh) { VaryingsType varyingsType; // オブジェクトスペースで法線方向に頂点を膨らませる inputMesh.positionOS += inputMesh.normalOS * 0.02; varyingsType.vmesh = VertMesh(inputMesh); return PackVaryingsType(varyingsType); } #ifdef TESSELLATION_ON PackedVaryingsToPS VertTesselation(VaryingsToDS input) { VaryingsToPS output; output.vmesh = VertMeshTesselation(input.vmesh); return PackVaryingsToPS(output); } #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/TessellationShare.hlsl" #endif // TESSELLATION_ON void Frag( PackedVaryingsToPS packedInput, out float4 outColor : SV_Target ) { // アウトラインは黒色 outColor = float4(0.0, 0.0, 0.0, 1.0); } #pragma vertex Vert #pragma fragment Frag ENDHLSL }
HDRPのコードを書き換えてOutlineパスを実行する
最近HDRPのコードを読んでいて描画の大部分は HDRenderPipeline.cs
に記述されていそうな感じがします。
少なくともパスを追加して呼び出すということがしたいだけであれば、ここを起点に読み進めればできそうです!
というわけでOutlineを呼び出す処理を書いていきます。
Outlineパス差し込み
実装は置いておいて HDRenderPipeline.cs
にパスを差し込みます。
今回はアウトラインということなので、DefferdやForwardのライティング処理が終わってから実行したいです。
空描画の次あたりに差し込んでみます。
RenderForwardEmissive(cullingResults, hdCamera, renderContext, cmd);
RenderSky(hdCamera, cmd);
++ RenderOutline(cullingResults, hdCamera, renderContext, cmd);
RenderTransparentDepthPrepass(cullingResults, hdCamera, renderContext, cmd);
RenderOutlineを実装する
差し込みましたが実装がまだないのでその他のRender関数を参考に作ります。
今回は RenderForwardOpaque
を参考にしました。
void RenderOutline(CullingResults cullResults, HDCamera hdCamera, ScriptableRenderContext renderContext, CommandBuffer cmd) { bool debugDisplay = m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled(); using (new ProfilingSample(cmd, "Render Outline", CustomSamplerId.Outline.GetSampler())) { bool msaa = hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA); RenderTargetIdentifier[] renderTarget = null; renderTarget = mMRTSingle; renderTarget[0] = msaa ? m_CameraColorMSAABuffer : m_CameraColorBuffer; HDUtils.SetRenderTarget(cmd, renderTarget, m_SharedRTManager.GetDepthStencilBuffer(msaa)); var rendererList = RendererList.Create(CreateOpaqueRendererListDesc(cullResults, hdCamera.camera, HDShaderPassNames.s_OutlineName)); DrawOpaqueRendererList(renderContext, cmd, hdCamera.frameSettings, rendererList); } }
CustomSamplerIdとHDShaderPassNamesにOutlineを追加
RenderOutlineで使用する変数等を追加します。
HDCustomSamplerId.cs
にプロファイリング用に使用する列挙体を追加します
ForwardPassName,
++ Outline,
ForwardTransparentDepthPrepass,
HDStringConstants.cs
にパス名の文字列とIDを追加します。
public static readonly string s_ForwardStr = "Forward";
++ public static readonly string s_OutlineStr = "Outline";
public static readonly string s_DepthOnlyStr = "DepthOnly";
public static readonly ShaderTagId s_ForwardName = new ShaderTagId(s_ForwardStr);
++ public static readonly ShaderTagId s_OutlineName = new ShaderTagId(s_OutlineStr);
public static readonly ShaderTagId s_DepthOnlyName = new ShaderTagId(s_DepthOnlyStr);
動作確認
これでアウトラインパスが動作するHDRPとシェーダーの準備ができたので、作成したシェーダーをアサインしたマテリアルをメッシュに割り当てて動作確認します。
問題なく動作していそうです!
単純なパスなら意外とさっくりと追加できました、もっと良い方法や考慮すべきことが残っていそうな気がするので何か情報をお持ちの方は是非教えていただきたいです。