TextureSampleGradのCustomNode

UEのマテリアルでTextureからSampleGradでサンプリングするメモ.

これが2021年最後の記事. 良いお年を!

ノードとしてSampleGradが提供されていないようなので、CustomNodeでSampleGrad関数を直接呼ぶこととする.
(提供されているようならこの記事は見なかったことにしてください.)

CustomNodeの内容

TextureとUV, ddx, ddy を引数にとって内部で TextureSampleGrad関数を利用する.

/*
    Input
            InTexture  ( and InTextureSampler)
            InUv
            InDdx
            InDdy
    
    Output
            float4
*/

float4 tex = Texture2DSampleGrad(InTexture, InTextureSampler, InUv, InDdx, InDdy);
return tex;

CustomNodeコピペ用

コピペで利用したい場合は以下のテキストをマテリアルエディタに貼り付ければCustomNodeが生成される.

Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name="MaterialGraphNode_21"
   Begin Object Class=/Script/Engine.MaterialExpressionCustom Name="MaterialExpressionCustom_2"
   End Object
   Begin Object Name="MaterialExpressionCustom_2"
      Code="\r\n/*\r\n    Input\r\n            InTexture  ( and InTextureSampler)\r\n            InUv\r\n            InDdx\r\n            InDdy\r\n    \r\n    Output\r\n            float4\r\n*/\r\n\r\nfloat4 tex = Texture2DSampleGrad(InTexture, InTextureSampler, InUv, InDdx, InDdy);\r\nreturn tex;\r\n\r\n"
      OutputType=CMOT_Float4
      Inputs(0)=(InputName="InTexture",Input=(Expression=MaterialExpressionTextureObjectParameter'"MaterialExpressionTextureObjectParameter_1"'))
      Inputs(1)=(InputName="InUv",Input=(Expression=MaterialExpressionReroute'"MaterialExpressionReroute_0"'))
      Inputs(2)=(InputName="InDdx",Input=(Expression=MaterialExpressionDDX'"MaterialExpressionDDX_0"'))
      Inputs(3)=(InputName="InDdy",Input=(Expression=MaterialExpressionDDY'"MaterialExpressionDDY_0"'))
      MaterialExpressionEditorX=-352
      MaterialExpressionEditorY=240
      MaterialExpressionGuid=A6C202464ABAD8F6E9734E9B54C6742D
      Material=PreviewMaterial'"/Engine/Transient.M_TexturePreview"'
   End Object
   MaterialExpression=MaterialExpressionCustom'"MaterialExpressionCustom_2"'
   NodePosX=-352
   NodePosY=240
   ErrorType=1
   ErrorMsg="Custom material Custom missing input 1 (InTexture)"
   NodeGuid=98660A2E479B2DED7843C29DD7E144AB
   CustomProperties Pin (PinId=3FB004F94791B89E090EB9B99B713C0F,PinName="InTexture",PinType.PinCategory="required",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_83 FF18694A45E6BEAA46EA3F8C083A2CBC,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
   CustomProperties Pin (PinId=3E114E314D9BAB61118B329013A0C05A,PinName="InUv",PinType.PinCategory="required",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_Knot_7 18FE939F4A97C00C67CC16A085BED853,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
   CustomProperties Pin (PinId=B5C056784D5BAD800E83398A08AD56B8,PinName="InDdx",PinType.PinCategory="required",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_85 80EC1CDF4B3A1C9667D72EB37399E8C0,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
   CustomProperties Pin (PinId=905889CC49E11D9C88DB2792EF254574,PinName="InDdy",PinType.PinCategory="required",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_86 BBAD4B0443CF6057D92E17A5A0BB730A,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
   CustomProperties Pin (PinId=8EFEA7514110CC30D32E41B0B1689991,PinName="Output",PinFriendlyName=NSLOCTEXT("MaterialGraphNode", "Space", " "),Direction="EGPD_Output",PinType.PinCategory="",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_Root_0 1653EE4D4D08EED8A95A3CA74981CFA2,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object

利用例

TextureObjectとUV, ddx, ddy をCustomNodeに入力する.

f:id:nagakagachi:20211231190816p:plain
当記事のCustomNodeの利用例

何に使うの

確率的テクスチャブレンディング等ではタイリング境界でUVギャップが大きくなり, 自動的なMipLevel選択ではアーティファクトが発生してしまう.
そのため自前で適切な勾配(Grad)を計算して明示的に指定する必要がある.

左画像は通常のTextureSampleノードを使った場合, 右がTextureSampleGradを利用した場合.
TextureSampleではライン上のアーティファクトが発生しているが, TextureSampleGradでは自前で勾配を指定することで改善している.

f:id:nagakagachi:20211231192444p:plain
TextureSampleとTextureSampleGrad