【Unity】StandardShaderを改造する
StandardShaderはUnityに標準でビルトインされているシェーダーで、オブジェクトに対して光や影の計算を行ってくれます。今回はこのStandardShaderをカスタマイズする方法を解説します。
環境
Unity 2021.3.4f1 Windows 10
1. StandardShaderのダウンロード
StandardShaderはUnityにビルトイン(=組み込まれている)されているシェーダーのため、直接編集することができません。しかしながら、シェーダー自体はUnity社から公開されているので、これをコピーしてカスタマイズしていきます。
ビルトインシェーダーはUnity ダウンロード アーカイブからダウンロードすることができます。
2. StandardShaderと関連ファイルのインポート
StandardShaderはいくつかのファイルで構成されています。ビルトインシェーダーがダウンロードできたら以下の4つのファイルを使用するUnityプロジェクトへインポートします。
DefaultResourcesExtra/Standard.shader
CGIncludes/UnityStandardCore.cginc
CGIncludes/UnityStandardCoreForward.cginc
Editor/StandardShaderGUI.cs
インポートが完了したら区別ができるようにこれらのファイル名を上から順に以下のように変更します。(末尾にCustomを付加)
3. StandardShaderの改造
ここからが実際の改変内容になります。今回はStandardShaderの処理にグレースケールの機能を追加してみたいと思います。それぞれのファイルを以下のように変更します。
-Shader "Standard"
+Shader "StandardCustom"
{
Properties
{
@@ -45,6 +45,8 @@ Shader "Standard"
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
+
+ _Brightness("Brightness", Range(0.0, 1.0)) = 1.0
}
CGINCLUDE
@@ -90,7 +92,7 @@ Shader "Standard"
#pragma vertex vertBase
#pragma fragment fragBase
- #include "UnityStandardCoreForward.cginc"
+ #include "UnityStandardCoreForwardCustom.cginc"
ENDCG
}
@@ -126,7 +128,7 @@ Shader "Standard"
#pragma vertex vertAdd
#pragma fragment fragAdd
- #include "UnityStandardCoreForward.cginc"
+ #include "UnityStandardCoreForwardCustom.cginc"
ENDCG
}
@@ -191,7 +193,7 @@ Shader "Standard"
#pragma vertex vertDeferred
#pragma fragment fragDeferred
- #include "UnityStandardCore.cginc"
+ #include "UnityStandardCoreCustom.cginc"
ENDCG
}
@@ -256,7 +258,7 @@ Shader "Standard"
#pragma vertex vertBase
#pragma fragment fragBase
- #include "UnityStandardCoreForward.cginc"
+ #include "UnityStandardCoreForwardCustom.cginc"
ENDCG
}
@@ -288,7 +290,7 @@ Shader "Standard"
#pragma vertex vertAdd
#pragma fragment fragAdd
- #include "UnityStandardCoreForward.cginc"
+ #include "UnityStandardCoreForwardCustom.cginc"
ENDCG
}
@@ -344,5 +346,5 @@ Shader "Standard"
FallBack "VertexLit"
- CustomEditor "StandardShaderGUI"
+ CustomEditor "StandardShaderGUICustom"
}
@@ -425,6 +425,8 @@ VertexOutputForwardBase vertForwardBase (VertexInput v)
return o;
}
+float _Brightness;
+
half4 fragForwardBaseInternal (VertexOutputForwardBase i)
{
UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy);
@@ -443,6 +445,8 @@ half4 fragForwardBaseInternal (VertexOutputForwardBase i)
half4 c = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect);
c.rgb += Emission(i.tex.xy);
+ c.rgb = Luminance(c.rgb).xxx * _Brightness;// モノクロ化
+
UNITY_EXTRACT_FOG_FROM_EYE_VEC(i);
UNITY_APPLY_FOG(_unity_fogCoord, c.rgb);
return OutputForward (c, s.alpha);
UnityStandardCoreForwardCustom.cginc
@@ -16,7 +16,7 @@
half4 fragBase (VertexOutputBaseSimple i) : SV_Target { return fragForwardBaseSimpleInternal(i); }
half4 fragAdd (VertexOutputForwardAddSimple i) : SV_Target { return fragForwardAddSimpleInternal(i); }
#else
- #include "UnityStandardCore.cginc"
+ #include "UnityStandardCoreCustom.cginc"
VertexOutputForwardBase vertBase (VertexInput v) { return vertForwardBase(v); }
VertexOutputForwardAdd vertAdd (VertexInput v) { return vertForwardAdd(v); }
half4 fragBase (VertexOutputForwardBase i) : SV_Target { return fragForwardBaseInternal(i); }
StandardShaderGUICustom.cs
@@ -55,6 +55,7 @@ namespace UnityEditor
public static string renderingMode = "Rendering Mode";
public static string advancedText = "Advanced Options";
public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
+ public static string brightnessText = "Brightness";
}
MaterialProperty blendMode = null;
@@ -83,6 +84,7 @@ namespace UnityEditor
MaterialProperty detailNormalMapScale = null;
MaterialProperty detailNormalMap = null;
MaterialProperty uvSetSecondary = null;
+ MaterialProperty brightness;
MaterialEditor m_MaterialEditor;
WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
@@ -126,6 +128,7 @@ namespace UnityEditor
detailNormalMapScale = FindProperty("_DetailNormalMapScale", props);
detailNormalMap = FindProperty("_DetailNormalMap", props);
uvSetSecondary = FindProperty("_UVSec", props);
+ brightness = FindProperty("_Brightness", props);
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
@@ -176,6 +179,8 @@ namespace UnityEditor
m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);
if (reflections != null)
m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);
+
+ m_MaterialEditor.ShaderProperty(brightness, Styles.brightnessText);
4. カスタムStandardShaderの適用
修正が完了したらStandardCustom.shaderを右クリックして[Create] > [Material]でマテリアルを新規作成するか、既存のマテリアルにStandardCustom.shaderを割り当てます。
インスペクタでパラメータを確認すると、追加した「Brightness」パラメータが追加されいることがわかります。
SceneビューやGameビューでカスタムシェーダーを割り当てたオブジェクトの色がモノクロになったり、追加したパラメータがを変更して明るさ(色の濃さ)が変わることを確認します。
5. おわりに
StandardShaderをカスタマイズする方法を見てきました。光や影の計算を行ってくれるStandardShaderはお手軽に使えますが、自分でカスタマイズしようとするとやや骨が折れることが分かります。
(インスペクターから独自のパラメータを変更できるようにする必要がない場合はStandardShaderGUICustom.csは不要になります)
恐らくStandardShaderはユーザによるカスタマイズが元々想定されておらず、光や影の処理込みでお手軽に独自の処理を組み込みたい場合は、SurfaceShaderを使うことが想定されているのでしょう。
しかしながらStandardShaderとSurfaceShaderでは内部処理の違いより見た目も若干異なるため、StandardShaderの質感で独自の処理を組み込みたい場合は今回のようなアプローチが必要になってきます。ニッチな記事にはなりましたが参考になれば幸いです。🌱
6. 参考
この記事が気に入ったらサポートをしてみませんか?