ShaderGraphのTargetを追加する

## はじめに
ShaderGraphに自作Targetの追加が出来たので、方法を残しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555386/7e169c72-432b-83fb-24c1-6d33caa9eaad.png)

### Targetを追加してなにがしたいのか？
Toon調のShaderを作りたかった。
最初はUnlitをベースに進めていたのですが、ノードからだと制御が難しい箇所も多く、
LitShaderを改造した方が早いのでは？と思い試してみました。

### 動作環境
- unity2022.3.33f1

※UnityアップデートでShaderGarphに更新が入ると要修正なのでご留意ください。



## 既存のTargetを複製する
1から作っていくのは大変なので、既存のTargetを複製し、必要な箇所だけ書き換えていきます。
Targetに必要なScriptはここに入ってるので、必要なものだけAssets以下に複製します。
``Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Targets``
````
・UniversalTarget //Target
・UniversalSubTarget //Materialの親
・UniversalLitSubTarget //LitMaterial
````
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555386/20deb046-e0fd-7a44-3978-1db376e7efe0.png)


複製先のフォルダに``Assembly Definition Reference Asset``も作成し、
``Unity.RenderPipelines.Universal.Editor``を設定します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555386/bfde9828-f028-0900-ff67-8932bda248a8.png)

---
ここまで対応すると、Consoleに大量のエラーが発生します。
ほとんどが同名クラスがあるという内容なので、クラス名をひたすらリネームし、
``SubShaderUtils``などstaticクラスやEnumなどは削除します。

リネームでエラーが消えたら
``UniversalTarget``のコンストラクタ内にある``displayName``を好きな名前にします。
※Universalのままだと表示されません。

ShaderGraphを確認すると、Targetから選択できるようになりました。
SubTargetを１つしか複製してないので、MaterialもLitのみになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555386/41233739-cd97-959f-f123-987a4013d4bc.png)

これでTargetの複製までは完了しました！

## Targetの改造
今は初期のLitShaderと同じ状態だと思うので、ここから改造していきます。

ShaderもScript同様に必要なものを複製し、書き換える形にします。
``UniversalTarget``
``UniversalLitSubTarget``
このスクリプトの``#region Includes``のすぐ下に、hlslのPathが書かれています。
改造したいhlslを複製し、pathも書き換えます。

あとは複製したファイルを編集することで、自由に改造できます。





以下テスト
``UniversalLitSubTarget >> kForwardPass   PBRForwardPass.hlsl//Forweadパスのエントリー``
ForwardレンダリングのPassはまずこのファイルを通るので、Fragの最後を編集してみます。
````diff_hlsl
    half4 color = UniversalFragmentPBR(inputData, surface);
    color.rgb = MixFog(color.rgb, inputData.fogCoord);

    color.a = OutputAlpha(color.a, isTransparent);

+   color.rgb = half3(1, 0, 0);

    outColor = color;
````
Base Colorに何を繋いでも強制的に赤くなるのが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555386/dbe07c03-5923-1129-6a01-bf7e5960f883.png)

``PBRForwardPass.hlsl``からだとライト計算には干渉できなそうなので、
``UniversalFragmentPBR``関数の持ち主``lighting.hlsl``も編集してみます。

````diff_hlsl
half3 LightingPhysicallyBased(BRDFData brdfData, BRDFData brdfDataClearCoat,
    half3 lightColor, half3 lightDirectionWS, half lightAttenuation,
    half3 normalWS, half3 viewDirectionWS,
    half clearCoatMask, bool specularHighlightsOff)
{
    half NdotL = saturate(dot(normalWS, lightDirectionWS));
+   NdotL = step(0.5, NdotL);
    half3 radiance = lightColor * (lightAttenuation * NdotL);
    half3 brdf = brdfData.diffuse;
            .
            .
            .
            . 
    return brdf * radiance;
}
````
Diffuseが2極化されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555386/5c77b5f8-51e0-1838-df89-1367e3506dff.png)

## おわりに
アップデート時のメンテコストだけ怖いですが、
Unlitを使って作るよりは、だいぶ楽にCustomLitが作れそうな印象でした。

上記のテストプロジェクトはこちらにアップしてます。

https://github.com/haw2fregel/CustomShaderGraphTarget