UE4でマテリアル出力にピンを追加（UE4.14.0）

もんしょ先生が記事に書かれていましたが、4.14.0で見るとちょこちょこ変わってるっぽいのでメモがてら纏めました。<br>
こんな感じでマテリアルの出力ピンにパラメーターを追加して、シェーダー内で取得する方法です。
![MaterialEditor.png](https://qiita-image-store.s3.amazonaws.com/0/58518/d2a28677-28ee-791d-7883-d7e308ca61d9.png)


# 参考
- [UE4] GBufferを拡張せずに異方性スペキュラをやってみる - もんしょの巣穴blog<br>
http://monsho.blog63.fc2.com/blog-entry-193.html

# 変更

## ソースコード側の追加、修正
- Engine/Source/Runtime/Engine/Public/SceneTypes.h<br>
158行目あたり<br>
//^^^ New material properties go above here ^^^^<br>
の上に追加するパラメーターを書く

```cpp:SceneTypes.h
// -- add -- //
MP_ShadowColor,
// -- -- //
//^^^ New material properties go above here ^^^^
```

- Engine/Source/Runtime/Engine/Classes/Materials/Material.h<br>
414行目あたり<br>
float3ならFVectorMaterialInput、floatならFScalarMaterialInput型とする。

```cpp:Material.h
UPROPERTY()
FScalarMaterialInput PixelDepthOffset;

// -- add -- //
UPROPERTY()
FVectorMaterialInput ShadowColor;
// -- -- //
```

- Engine/Source/Runtime/Engine/Classes/Materials/MaterialExpressionMakeMaterialAttributes.h<br>
66行目あたり

```cpp:MaterialExpressionMakeMaterialAttributes.h
UPROPERTY()
FExpressionInput PixelDepthOffset;

// -- add -- //
UPROPERTY()
FExpressionInput ShadowColor;
// -- -- //
```

- Engine/Source/Editor/UnrealEd/Private/MaterialGraph.cpp<br>
58行目あたり

```cpp:MaterialGraph.cpp
MaterialInputs.Add(FMaterialInputInfo(LOCTEXT("PixelDepthOffset", "Pixel Depth Offset"), MP_PixelDepthOffset, LOCTEXT( "PixelDepthOffsetToolTip", "Pixel Depth Offset" ) ));

// -- add -- //
MaterialInputs.Add(FMaterialInputInfo(LOCTEXT("ShadowColor", "ShadowColor"), MP_ShadowColor, LOCTEXT("ShadowColorToolTip", "ShadowColor")));
// -- -- //
//^^^ New material properties go above here. ^^^^
```

- Engine/Source/Runtime/Engine/Private/Materials/HLSLMaterialTranslator.h<br>
282行目あたり

```cpp:HLSLMaterialTranslator.h
SharedPixelProperties[MP_Refraction] = true;
SharedPixelProperties[MP_PixelDepthOffset] = true;
// -- add -- //
SharedPixelProperties[MP_ShadowColor] = true;
// -- -- //
```

413行目あたり

```cpp:HLSLMaterialTranslator.h
Chunk[MP_PixelDepthOffset] = Material->CompilePropertyAndSetMaterialProperty(MP_PixelDepthOffset,this);
// -- add -- //
Chunk[MP_ShadowColor] = Material->CompilePropertyAndSetMaterialProperty(MP_ShadowColor, this);
// -- -- //
```

- Engine/Source/Runtime/Engine/Private/Materials/Material.cpp<br>
2348行目あたり

```cpp:Material.cpp
static_assert(MP_MAX == 29, "New material properties must have DoMaterialAttributesReorder called on them to ensure that any future reordering of property pins is correctly applied.");
```
の29を、追加した数だけ増やす

```cpp:Material.cpp
// -- modifi -- //
static_assert(MP_MAX == 29, "New material properties must have DoMaterialAttributesReorder called on them to ensure that any future reordering of property pins is correctly applied.");
// -- -- //
```

2554行目あたり

```cpp:Material.cpp
DoMaterialAttributeReorder(&PixelDepthOffset, UE4Ver);
// -- add -- //
DoMaterialAttributeReorder(&ShadowColor, UE4Ver);
// -- -- //
```

3774行目あたり

```cpp:Material.cpp
case MP_PixelDepthOffset:		return &PixelDepthOffset;
// -- add -- //
case MP_ShadowColor:		return &ShadowColor;
// -- -- //
```

4437行目あたり

```cpp:Material.cpp
case MP_PixelDepthOffset:
	Active = !bIsTranslucentBlendMode;
	break;
// -- add -- //
case MP_ShadowColor:
	Active = true;
break;
// -- -- //
```

- Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp<br>
3523行目あたり

```cpp:MaterialExpressions.cpp
	static_assert(MP_MAX == 29, 
```

の29を、追加した数だけ増やす

```cpp:MaterialExpressions.cpp
// -- modifi -- //
	static_assert(MP_MAX == 30, 
// -- -- //
```

3548行目あたり

```cpp:MaterialExpressions.cpp
case MP_Refraction: Ret = Refraction.Compile(Compiler); Expression = Refraction.Expression; break;
case MP_PixelDepthOffset: Ret = PixelDepthOffset.Compile(Compiler); Expression = PixelDepthOffset.Expression; break;
// -- add -- //
case MP_ShadowColor: Ret = ShadowColor.Compile(Compiler); Expression = ShadowColor.Expression; break;
// -- -- //
```

3593行目あたり

```cpp:MaterialExpressions.cpp
	static_assert(MP_MAX == 29, 
```

の29を、追加した数だけ増やす

```cpp:MaterialExpressions.cpp
// -- modifi -- //
	static_assert(MP_MAX == 30, 
// -- -- //
```

3621行目あたり

```cpp:MaterialExpressions.cpp
Outputs.Add(FExpressionOutput(TEXT("PixelDepthOffset"), 1, 1, 1, 1, 0));
// -- add -- //
Outputs.Add(FExpressionOutput(TEXT("ShadowColor"), 1, 1, 1, 1, 0));
// -- -- //
```


- Engine/Source/Runtime/Engine/Private/Materials/MaterialShared.cpp<br>
2797行目あたり<br>
FGuidのIDは被らない数値を指定する。<br>
MCT_Float3は変数の方に合わせた列挙体で。<br>
SF_Pixelはどのシェーダーで使用するかで合わせる。

```cpp:MaterialShared.cpp
Add(FGuid(0x0AC97EC3, 0xE3D047BA, 0xB610167D, 0xC4D919FF), TEXT("PixelDepthOffset"),		MP_PixelDepthOffset,		MCT_Float1,	FVector4(0,0,0,0), SF_Pixel);
// -- add -- //
Add(FGuid(0x0AC97EC4, 0xE3D047BB, 0xB610167C, 0xC4D91A00), TEXT("ShadowColor"), MP_ShadowColor, MCT_Float3, FVector4(0, 0, 0, 0), SF_Pixel);
// -- -- //
Add(FGuid(0xA0119D44, 0xC456450D, 0x9C39C933, 0x1F72D8D1), TEXT("TessellationMultiplier"),	MP_TessellationMultiplier,	MCT_Float1,	FVector4(1,0,0,0), SF_Hull);
```

- 最後にエディタを一度落としてエンジンをビルドし直す。
リビルドした方がいいかも。


 

## シェーダー側の追加、変更
- Engine\Shaders\MaterialTemplate.usf<br>
取得関数を追加する

```cpp:MaterialTemplate.usf
 // -- add -- //
half3 GetMaterialShadowColorRaw(FPixelMaterialInputs PixelMaterialInputs)
{
	return PixelMaterialInputs.ShadowColor;
}
half3 GetMaterialShadowColor(FPixelMaterialInputs PixelMaterialInputs)
{
	return saturate(GetMaterialShadowColorRaw(PixelMaterialInputs));
}
 // -- -- //
```





##シェーダー内で値の取得
シェーダー内でMaterialTemplate.usfに追加した関数、GetMaterialShadowColor(PixelMaterialInputs);
で値が取れるようになる。
Engine\Shaders\BasePassPixelShader.usf
　FPixelShaderInOut_MainPS辺りで取るといいかも。

シェーダーを弄ったあとは、UE4エディター上で「Ctrl」+「Shift」＋「.」でシェーダービルドを行うこと。