simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Unity:UniversalRP de MasterNode (v7.1.2)

目まぐるしく変わる Unity の Universal RP の実装

その実装に合わせてカスタム MasterNode を作り替え続ける備忘録である

手順

Unity 2019.3.0b6 を落して、テンプレートに Universal RP を選ぼう

f:id:simplestar_tech:20191007213216p:plain
UniversalRPテンプレートを選ぶ

起動すると次の画面になりますね

f:id:simplestar_tech:20191007213954p:plain
Scene

Create Shader をチェック

f:id:simplestar_tech:20191007214101p:plain
ま、そうだな

Toon Graph 項目を増やす

Library/PackageCache フォルダを見ます

f:id:simplestar_tech:20191007214407p:plain
RP 関連

この三つのフォルダを Packages フォルダへ移動しておきます。

f:id:simplestar_tech:20191007214457p:plain
こんな風に

で PBR Graph で文字列検索して次の通り Toon Graph を作る項目を追加します。

f:id:simplestar_tech:20191007214601p:plain
Toon の項目を足します

いえー、増えた

f:id:simplestar_tech:20191007214923p:plain
Toon Graph ここにあり

ToonMasterNode クラス作ろう

次のファイルを作成して
"Packages\com.unity.shadergraph@7.1.2\Editor\Data\MasterNodes\IToonSubShader.cs"

このように実装します。

f:id:simplestar_tech:20191007215308p:plain
IToonSubShader

同じフォルダにある PBRMasterNode.cs ファイルを複製して ToonMasterNode.cs とし…
ファイル内の PBR を Toon に全部置換します

次のファイルを同じフォルダにある PBRSettingsView.cs を複製して作ります
Packages\com.unity.shadergraph@7.1.2\Editor\Drawing\Views\ToonSettingsView.cs
ファイル内の PBR を Toon に全部置換します

次のファイルも同様に、同じ階層の PBRMasterGUI.cs を複製して作ります。
Packages\com.unity.shadergraph@7.1.2\Editor\ShaderGUI\ToonMasterGUI.cs
ファイル内の PBR を Toon に全部置換します

これで、最初の UI メニュー項目の変更箇所を次のように ToonMasterNode に置き換え

        [MenuItem("Assets/Create/Shader/Toon Graph", false, 208)]
        public static void CreateToonMasterMaterialGraph()
        {
            GraphUtil.CreateNewGraph(new ToonMasterNode());
        }

これで壊れた Toon Master Node を Shader Graph で作れるようになりました

f:id:simplestar_tech:20191007220710p:plain
こわれた MasterNode が作れるようになった

UniversalPBRSubShader を複製する

次のファイルを複製
Packages\com.unity.render-pipelines.universal@7.1.2\Editor\ShaderGraph\SubShaders\UniversalPBRSubShader.cs
UniversalToonSubShader.csファイルにリネームして
ファイル内の PBR を Toon に全部置換します(小文字の pbr は残す)

次のパスのファイルを同じフォルダのPBRForwardPass.hlslを複製して作ります
Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ToonForwardPass.hlsl
ファイル内の PBR を Toon に全部置換します(一か所だけ)

次のパスのファイルを同じフォルダのPBR2DPass.hlslを複製して作ります
Packages\com.unity.render-pipelines.universal@7.1.2\Editor\ShaderGraph\Includes\Toon2DPass.hlsl
ファイル内に PBR はないので置換は不要

次のファイル内を見ましょう
Packages\com.unity.render-pipelines.universal@7.1.2\ShaderLibrary\Lighting.hlsl

UniversalFragmentPBR 関数をコピーして UniversalFragmentToon 関数を次の通り追加します

half4 UniversalFragmentToon(InputData inputData, half3 albedo, half metallic, half3 specular,
	half smoothness, half occlusion, half3 emission, half alpha)
{
	BRDFData brdfData;
	InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);

	Light mainLight = GetMainLight(inputData.shadowCoord);
	MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));

	half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);
	color += LightingPhysicallyBased(brdfData, mainLight, inputData.normalWS, inputData.viewDirectionWS);

#ifdef _ADDITIONAL_LIGHTS
	uint pixelLightCount = GetAdditionalLightsCount();
	for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
	{
		Light light = GetAdditionalLight(lightIndex, inputData.positionWS);
		color += LightingPhysicallyBased(brdfData, light, inputData.normalWS, inputData.viewDirectionWS);
	}
#endif

#ifdef _ADDITIONAL_LIGHTS_VERTEX
	color += inputData.vertexLighting * brdfData.diffuse;
#endif

	color += emission;
	return half4(color, alpha);
}

Unity にフォーカスを与えると Shader ビルドが走るので、先ほどの壊れた Shader Graph が正常な Shader として扱われるようになります

f:id:simplestar_tech:20191007222827p:plain
いえー!!

おまけ

Lighting.hlsl の UniversalFragmentToon を次の通り emissionを消してみました

half4 UniversalFragmentToon(InputData inputData, half3 albedo, half metallic, half3 specular,
	half smoothness, half occlusion, half3 emission, half alpha)
{
	BRDFData brdfData;
	InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);

	Light mainLight = GetMainLight(inputData.shadowCoord);
	MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));

	half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);
	color += LightingPhysicallyBased(brdfData, mainLight, inputData.normalWS, inputData.viewDirectionWS);

	uint pixelLightCount = GetAdditionalLightsCount();
	for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
	{
		Light light = GetAdditionalLight(lightIndex, inputData.positionWS);
		color += LightingPhysicallyBased(brdfData, light, inputData.normalWS, inputData.viewDirectionWS);
	}

	color += inputData.vertexLighting * brdfData.diffuse;

	return half4(color, alpha);
}

f:id:simplestar_tech:20191007223452p:plain
emissionガン無視

まとめ

PBR シェーダを複製していき Toon MasterNode を作って Shader Graph 経由で作成、編集できることを示しました。
頑張って Shader の実装を書き換えていけば Toon の Master Node が作れるってわけです。

ここまでの知識を次の知見につなげれば、なんとかなりそう…
simplestar-tech.hatenablog.com

v7.1.2 でも動く Toon Shader Graph の完成に期待(未来の自分頑張れ)