Derivative Normal Map Material Function

Made a fast test(far from production ready) to check derivative maps in unreal engine by material editor.

Number of instructions against the same shader with tangent space normal mapping is a bit highter actually.
I’m completely unaware of what is happening under the hood (es if engine is animating tangents and passing them as interpolator if shader compiler optimizes out the z calculation of the normal and so on).
Character also mixes both normal map for the head and derivative for the body(i didn’t have head derivative map at the moment).It might be or not be relevant as far as optimization is concerned.
It will require more investigation, but probably to have an optimized implementation some engine tweakings are required.

Actually I’m testing it with normal texture exported from xnormal and compressing with TC_Normalmap(default compression doesn’t seem to give good quality results even on derivative maps).
TC_Normalmap also gives just scaled and biased result to just plug in the function so, If you use different compression, you have to scale and bias manually.

Pic is a little test mixing tangent and derivative normal maps on characters bodies (mostly right side char are derivative), heads are all tanget space.

The difference is almost unrecognizable but overally tangent space achieve clean uv seams while on derivative map they are slightly visible, but less than what you can normally see in thousand of shipped games and possibly due to my eyeballed parameters.Neck Seam between tangent and derivative mapped body part is negligible too.

Normal map issues here and there are due to sculpting and normal map calculation errors on my character that is still in early wip.
Character sculpting is not final, nor topology and textures.

p.s. This character will be modular with different body shapes, clothing and themed equipment and I hope to finish and to release it soon to the community.

6a5b59792fbbef3af9e66ed18e34481540023ff5.jpeg

in case you want to test it here is the material function. The scale factor for my texture is x256 and y -256 for the default xnormal derivative map settings,
but i just eyeballed it to match tangent space one.different scale gives more or less bumpiness(for free).



Begin Object Class=MaterialFunction Name="DerivativeNormalPerturb"
   Begin Object Class=MaterialExpressionAdd Name="MaterialExpressionAdd_16"
   End Object
   Begin Object Class=MaterialExpressionAdd Name="MaterialExpressionAdd_17"
   End Object
   Begin Object Class=MaterialExpressionAdd Name="MaterialExpressionAdd_18"
   End Object
   Begin Object Class=MaterialExpressionComponentMask Name="MaterialExpressionComponentMask_20"
   End Object
   Begin Object Class=MaterialExpressionComponentMask Name="MaterialExpressionComponentMask_21"
   End Object
   Begin Object Class=MaterialExpressionCrossProduct Name="MaterialExpressionCrossProduct_16"
   End Object
   Begin Object Class=MaterialExpressionCrossProduct Name="MaterialExpressionCrossProduct_17"
   End Object
   Begin Object Class=MaterialExpressionDDX Name="MaterialExpressionDDX_18"
   End Object
   Begin Object Class=MaterialExpressionDDX Name="MaterialExpressionDDX_19"
   End Object
   Begin Object Class=MaterialExpressionDDX Name="MaterialExpressionDDX_20"
   End Object
   Begin Object Class=MaterialExpressionDDY Name="MaterialExpressionDDY_18"
   End Object
   Begin Object Class=MaterialExpressionDDY Name="MaterialExpressionDDY_19"
   End Object
   Begin Object Class=MaterialExpressionDDY Name="MaterialExpressionDDY_20"
   End Object
   Begin Object Class=MaterialExpressionDotProduct Name="MaterialExpressionDotProduct_8"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_1"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_2"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_3"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_5"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_6"
   End Object
   Begin Object Class=MaterialExpressionFunctionOutput Name="MaterialExpressionFunctionOutput_1"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_60"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_61"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_62"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_63"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_64"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_65"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_68"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_69"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_70"
   End Object
   Begin Object Class=MaterialExpressionNormalize Name="MaterialExpressionNormalize_8"
   End Object
   Begin Object Class=MaterialExpressionSubtract Name="MaterialExpressionSubtract_21"
   End Object
   Begin Object Class=MaterialExpressionVertexNormalWS Name="MaterialExpressionVertexNormalWS_5"
   End Object
   Begin Object Class=MaterialExpressionWorldPosition Name="MaterialExpressionWorldPosition_3"
   End Object
   Begin Object Class=SceneThumbnailInfoWithPrimitive Name="SceneThumbnailInfoWithPrimitive_2"
   End Object
   Begin Object Class=MaterialExpressionComponentMask Name="MaterialExpressionComponentMask_2"
   End Object
   Begin Object Class=MaterialExpressionComponentMask Name="MaterialExpressionComponentMask_3"
   End Object
   Begin Object Class=MaterialExpressionDDX Name="MaterialExpressionDDX_3"
   End Object
   Begin Object Class=MaterialExpressionDDX Name="MaterialExpressionDDX_4"
   End Object
   Begin Object Class=MaterialExpressionDDY Name="MaterialExpressionDDY_3"
   End Object
   Begin Object Class=MaterialExpressionDDY Name="MaterialExpressionDDY_4"
   End Object
   Begin Object Class=MaterialExpressionVertexNormalWS Name="MaterialExpressionVertexNormalWS_1"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_9"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_10"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_11"
   End Object
   Begin Object Class=MaterialExpressionAdd Name="MaterialExpressionAdd_3"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_12"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_13"
   End Object
   Begin Object Class=MaterialExpressionAdd Name="MaterialExpressionAdd_4"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_14"
   End Object
   Begin Object Class=MaterialExpressionWorldPosition Name="MaterialExpressionWorldPosition_1"
   End Object
   Begin Object Class=MaterialExpressionDDX Name="MaterialExpressionDDX_5"
   End Object
   Begin Object Class=MaterialExpressionDDY Name="MaterialExpressionDDY_5"
   End Object
   Begin Object Class=MaterialExpressionCrossProduct Name="MaterialExpressionCrossProduct_2"
   End Object
   Begin Object Class=MaterialExpressionCrossProduct Name="MaterialExpressionCrossProduct_3"
   End Object
   Begin Object Class=MaterialExpressionDotProduct Name="MaterialExpressionDotProduct_1"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_15"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_16"
   End Object
   Begin Object Class=MaterialExpressionAdd Name="MaterialExpressionAdd_5"
   End Object
   Begin Object Class=MaterialExpressionMultiply Name="MaterialExpressionMultiply_17"
   End Object
   Begin Object Class=MaterialExpressionSubtract Name="MaterialExpressionSubtract_1"
   End Object
   Begin Object Class=MaterialExpressionNormalize Name="MaterialExpressionNormalize_1"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_7"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_8"
   End Object
   Begin Object Class=MaterialExpressionFunctionInput Name="MaterialExpressionFunctionInput_9"
   End Object
   Begin Object Name="MaterialExpressionAdd_16"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_62')
      B=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_63')
      MaterialExpressionEditorX=-352
      MaterialExpressionEditorY=-48
      MaterialExpressionGuid=88C59A3A48509C1C4F52459D70B36925
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionAdd_17"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_64')
      B=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_65')
      MaterialExpressionEditorX=-336
      MaterialExpressionEditorY=176
      MaterialExpressionGuid=88C59A3A48509C1C4F52459D70B36925
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionAdd_18"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_68')
      B=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_69')
      MaterialExpressionEditorX=272
      MaterialExpressionEditorY=80
      MaterialExpressionGuid=F9B248D046DDC217DD8AF78B6A206CFC
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionComponentMask_20"
      Input=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_1')
      R=True
      MaterialExpressionEditorX=-1104
      MaterialExpressionEditorY=-144
      MaterialExpressionGuid=1A35D3394300FE9224BFD787964005FB
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionComponentMask_21"
      Input=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_1')
      G=True
      MaterialExpressionEditorX=-1104
      MaterialExpressionEditorY=-64
      MaterialExpressionGuid=1A35D3394300FE9224BFD787964005FB
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionCrossProduct_16"
      A=(Expression=MaterialExpressionDDY'MaterialExpressionDDY_20')
      B=(Expression=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_5')
      MaterialExpressionEditorX=-288
      MaterialExpressionEditorY=-592
      MaterialExpressionGuid=018AF00C4D107BF859D63F956085BA96
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      Desc="tR1"
   End Object
   Begin Object Name="MaterialExpressionCrossProduct_17"
      A=(Expression=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_5')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_20')
      MaterialExpressionEditorX=-256
      MaterialExpressionEditorY=-368
      MaterialExpressionGuid=D48E9C7E4D19C0B026F99FACFC421CE1
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      Desc="tR2"
   End Object
   Begin Object Name="MaterialExpressionDDX_18"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_20')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-208
      MaterialExpressionGuid=ED584B9F4B47A1E5656A19B4C770EADC
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDX_19"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_21')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-144
      MaterialExpressionGuid=C568B7644B5C281FE8D3B793F7834F06
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDX_20"
      Value=(Expression=MaterialExpressionWorldPosition'MaterialExpressionWorldPosition_3')
      MaterialExpressionEditorX=-576
      MaterialExpressionEditorY=-512
      MaterialExpressionGuid=1F4D3B4742862472D2749A864B086DDA
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      Desc="sigmaS"
   End Object
   Begin Object Name="MaterialExpressionDDY_18"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_20')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-80
      MaterialExpressionGuid=A6A6DBB04F08DD58303AA6841F61B399
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDY_19"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_21')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-16
      MaterialExpressionGuid=46229F15468E493F347C2F8A5E036AD9
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDY_20"
      Value=(Expression=MaterialExpressionWorldPosition'MaterialExpressionWorldPosition_3')
      MaterialExpressionEditorX=-576
      MaterialExpressionEditorY=-592
      MaterialExpressionGuid=0D669F2449487B366EBB859FA5B41773
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      Desc="sigmaT"
   End Object
   Begin Object Name="MaterialExpressionDotProduct_8"
      A=(Expression=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_16')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_20')
      MaterialExpressionEditorX=-48
      MaterialExpressionEditorY=-560
      MaterialExpressionGuid=F3B744FB49C889C2E6DF068ABA9F4DFE
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      Desc="fDet"
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_1"
      InputName="Uv"
      Id=8AD637A74080AC1550617A8C6CEEF77B
      InputType=FunctionInput_Vector2
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=-112
      MaterialExpressionGuid=59842F404960EE46F6E8F6BBBF25D7B9
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_2"
      InputName="DerivativeMap_R"
      Id=D10566AA4E9F7BE4C51834AD625FC242
      InputType=FunctionInput_Scalar
      SortPriority=1
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=80
      MaterialExpressionGuid=18EE169546DE45117B4932B2A03906B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_3"
      InputName="DerivativeMap_G"
      Id=D87C1DC8498CFC78E0BBA2A9177D457A
      InputType=FunctionInput_Scalar
      SortPriority=2
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=240
      MaterialExpressionGuid=18EE169546DE45117B4932B2A03906B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_5"
      InputName="TextureUv"
      Description="Coordinates you sampled texture with"
      Id=8AD637A74080AC1550617A8C6CEEF77B
      InputType=FunctionInput_Vector2
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=-112
      MaterialExpressionGuid=59842F404960EE46F6E8F6BBBF25D7B9
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_6"
      InputName="DerivativeMap_R"
      Description="Require Scale and Biased Value"
      Id=D10566AA4E9F7BE4C51834AD625FC242
      InputType=FunctionInput_Scalar
      SortPriority=1
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=64
      MaterialExpressionGuid=18EE169546DE45117B4932B2A03906B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionOutput_1"
      OutputName="PerturbedNormalWS"
      A=(Expression=MaterialExpressionNormalize'MaterialExpressionNormalize_1')
      bLastPreviewed=True
      Id=34C8B89E49B7D3491382EDAD34A897E9
      MaterialExpressionEditorX=1264
      MaterialExpressionEditorY=-192
      MaterialExpressionGuid=8D6FC9D746165B1D044FEBAA224D3712
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_60"
      A=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_3')
      B=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_6')
      MaterialExpressionEditorX=-960
      MaterialExpressionEditorY=256
      MaterialExpressionGuid=5FEE08CF42489434768866911B7DF8C8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_61"
      A=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_2')
      B=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_5')
      MaterialExpressionEditorX=-960
      MaterialExpressionEditorY=96
      MaterialExpressionGuid=5FEE08CF42489434768866911B7DF8C8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_62"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_61')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_18')
      MaterialExpressionEditorX=-512
      MaterialExpressionEditorY=-128
      MaterialExpressionGuid=6EB2E5174D1E288AA70DCFB3124709B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_63"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_60')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_19')
      MaterialExpressionEditorX=-512
      MaterialExpressionGuid=3B85D5A14B98427B13B824B97775D6D8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_64"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_61')
      B=(Expression=MaterialExpressionDDY'MaterialExpressionDDY_18')
      MaterialExpressionEditorX=-512
      MaterialExpressionEditorY=128
      MaterialExpressionGuid=6EB2E5174D1E288AA70DCFB3124709B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_65"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_60')
      B=(Expression=MaterialExpressionDDY'MaterialExpressionDDY_19')
      MaterialExpressionEditorX=-512
      MaterialExpressionEditorY=256
      MaterialExpressionGuid=3B85D5A14B98427B13B824B97775D6D8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_68"
      A=(Expression=MaterialExpressionAdd'MaterialExpressionAdd_16')
      B=(Expression=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_16')
      MaterialExpressionEditorX=64
      MaterialExpressionEditorY=-48
      MaterialExpressionGuid=E1B7D125420D9BA7EBCD62AAB9A56356
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_69"
      A=(Expression=MaterialExpressionAdd'MaterialExpressionAdd_17')
      B=(Expression=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_17')
      MaterialExpressionEditorX=-16
      MaterialExpressionEditorY=176
      MaterialExpressionGuid=F159D068460256FAEC51A58842AE03D4
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_70"
      A=(Expression=MaterialExpressionDotProduct'MaterialExpressionDotProduct_8')
      B=(Expression=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_5')
      MaterialExpressionEditorX=480
      MaterialExpressionEditorY=-128
      MaterialExpressionGuid=6160EEC743BD58C1153852BEE753E433
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionNormalize_8"
      VectorInput=(Expression=MaterialExpressionSubtract'MaterialExpressionSubtract_21')
      MaterialExpressionEditorX=1008
      MaterialExpressionEditorY=-160
      MaterialExpressionGuid=4E6CADDF4905FBE1502E428464302FBA
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionSubtract_21"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_70')
      B=(Expression=MaterialExpressionAdd'MaterialExpressionAdd_18')
      MaterialExpressionEditorX=720
      MaterialExpressionEditorY=-96
      MaterialExpressionGuid=247E5B6641A86F7D30D81CA87733B98A
      bRealtimePreview=True
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      bCollapsed=False
   End Object
   Begin Object Name="MaterialExpressionVertexNormalWS_5"
      MaterialExpressionEditorX=-560
      MaterialExpressionEditorY=-256
      MaterialExpressionGuid=8AB5AF804EFCD0096D50CE81660FD1D2
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionWorldPosition_3"
      MaterialExpressionEditorX=-912
      MaterialExpressionEditorY=-592
      MaterialExpressionGuid=FFA447E946B6945D4F454FA34C28D38B
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="SceneThumbnailInfoWithPrimitive_2"
   End Object
   Begin Object Name="MaterialExpressionComponentMask_2"
      Input=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_5')
      R=True
      MaterialExpressionEditorX=-1104
      MaterialExpressionEditorY=-144
      MaterialExpressionGuid=1A35D3394300FE9224BFD787964005FB
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionComponentMask_3"
      Input=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_5')
      G=True
      MaterialExpressionEditorX=-1104
      MaterialExpressionEditorY=-64
      MaterialExpressionGuid=1A35D3394300FE9224BFD787964005FB
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDX_3"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_2')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-208
      MaterialExpressionGuid=ED584B9F4B47A1E5656A19B4C770EADC
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDX_4"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_3')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-144
      MaterialExpressionGuid=C568B7644B5C281FE8D3B793F7834F06
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDY_3"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_2')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-80
      MaterialExpressionGuid=A6A6DBB04F08DD58303AA6841F61B399
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDY_4"
      Value=(Expression=MaterialExpressionComponentMask'MaterialExpressionComponentMask_3')
      MaterialExpressionEditorX=-832
      MaterialExpressionEditorY=-16
      MaterialExpressionGuid=46229F15468E493F347C2F8A5E036AD9
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionVertexNormalWS_1"
      MaterialExpressionEditorX=-624
      MaterialExpressionEditorY=-432
      MaterialExpressionGuid=8AB5AF804EFCD0096D50CE81660FD1D2
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_9"
      A=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_8')
      B=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_9')
      MaterialExpressionEditorX=-960
      MaterialExpressionEditorY=256
      MaterialExpressionGuid=5FEE08CF42489434768866911B7DF8C8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_10"
      A=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_6')
      B=(Expression=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_7')
      MaterialExpressionEditorX=-960
      MaterialExpressionEditorY=96
      MaterialExpressionGuid=5FEE08CF42489434768866911B7DF8C8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_11"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_10')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_3')
      MaterialExpressionEditorX=-512
      MaterialExpressionEditorY=-128
      MaterialExpressionGuid=6EB2E5174D1E288AA70DCFB3124709B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionAdd_3"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_11')
      B=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_12')
      MaterialExpressionEditorX=-352
      MaterialExpressionEditorY=-48
      MaterialExpressionGuid=88C59A3A48509C1C4F52459D70B36925
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_12"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_9')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_4')
      MaterialExpressionEditorX=-512
      MaterialExpressionGuid=3B85D5A14B98427B13B824B97775D6D8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_13"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_10')
      B=(Expression=MaterialExpressionDDY'MaterialExpressionDDY_3')
      MaterialExpressionEditorX=-512
      MaterialExpressionEditorY=128
      MaterialExpressionGuid=6EB2E5174D1E288AA70DCFB3124709B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionAdd_4"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_13')
      B=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_14')
      MaterialExpressionEditorX=-336
      MaterialExpressionEditorY=176
      MaterialExpressionGuid=88C59A3A48509C1C4F52459D70B36925
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_14"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_9')
      B=(Expression=MaterialExpressionDDY'MaterialExpressionDDY_4')
      MaterialExpressionEditorX=-512
      MaterialExpressionEditorY=256
      MaterialExpressionGuid=3B85D5A14B98427B13B824B97775D6D8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionWorldPosition_1"
      MaterialExpressionEditorX=-912
      MaterialExpressionEditorY=-592
      MaterialExpressionGuid=FFA447E946B6945D4F454FA34C28D38B
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDX_5"
      Value=(Expression=MaterialExpressionWorldPosition'MaterialExpressionWorldPosition_1')
      MaterialExpressionEditorX=-576
      MaterialExpressionEditorY=-512
      MaterialExpressionGuid=1F4D3B4742862472D2749A864B086DDA
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDDY_5"
      Value=(Expression=MaterialExpressionWorldPosition'MaterialExpressionWorldPosition_1')
      MaterialExpressionEditorX=-576
      MaterialExpressionEditorY=-592
      MaterialExpressionGuid=0D669F2449487B366EBB859FA5B41773
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionCrossProduct_2"
      A=(Expression=MaterialExpressionDDY'MaterialExpressionDDY_5')
      B=(Expression=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_1')
      MaterialExpressionEditorX=-288
      MaterialExpressionEditorY=-592
      MaterialExpressionGuid=018AF00C4D107BF859D63F956085BA96
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionCrossProduct_3"
      A=(Expression=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_1')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_5')
      MaterialExpressionEditorX=-288
      MaterialExpressionEditorY=-464
      MaterialExpressionGuid=D48E9C7E4D19C0B026F99FACFC421CE1
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionDotProduct_1"
      A=(Expression=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_2')
      B=(Expression=MaterialExpressionDDX'MaterialExpressionDDX_5')
      MaterialExpressionEditorX=-48
      MaterialExpressionEditorY=-560
      MaterialExpressionGuid=F3B744FB49C889C2E6DF068ABA9F4DFE
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_15"
      A=(Expression=MaterialExpressionAdd'MaterialExpressionAdd_3')
      B=(Expression=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_2')
      MaterialExpressionEditorX=96
      MaterialExpressionEditorY=-48
      MaterialExpressionGuid=E1B7D125420D9BA7EBCD62AAB9A56356
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_16"
      A=(Expression=MaterialExpressionAdd'MaterialExpressionAdd_4')
      B=(Expression=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_3')
      MaterialExpressionEditorX=96
      MaterialExpressionEditorY=176
      MaterialExpressionGuid=F159D068460256FAEC51A58842AE03D4
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionAdd_5"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_15')
      B=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_16')
      MaterialExpressionEditorX=384
      MaterialExpressionEditorY=80
      MaterialExpressionGuid=F9B248D046DDC217DD8AF78B6A206CFC
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionMultiply_17"
      A=(Expression=MaterialExpressionDotProduct'MaterialExpressionDotProduct_1')
      B=(Expression=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_1')
      MaterialExpressionEditorX=384
      MaterialExpressionEditorY=-224
      MaterialExpressionGuid=6160EEC743BD58C1153852BEE753E433
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionSubtract_1"
      A=(Expression=MaterialExpressionMultiply'MaterialExpressionMultiply_17')
      B=(Expression=MaterialExpressionAdd'MaterialExpressionAdd_5')
      MaterialExpressionEditorX=720
      MaterialExpressionEditorY=-160
      MaterialExpressionGuid=247E5B6641A86F7D30D81CA87733B98A
      bRealtimePreview=True
      Function=MaterialFunction'"DerivativeNormalPerturb"'
      Desc="Perturbation"
      bCollapsed=False
   End Object
   Begin Object Name="MaterialExpressionNormalize_1"
      VectorInput=(Expression=MaterialExpressionSubtract'MaterialExpressionSubtract_1')
      MaterialExpressionEditorX=1008
      MaterialExpressionEditorY=-160
      MaterialExpressionGuid=4E6CADDF4905FBE1502E428464302FBA
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_7"
      InputName="TextureScaleFactorX"
      Description="eyeballing this :("
      Id=7006A09246E00F3390A9718BB46AFB14
      InputType=FunctionInput_Scalar
      PreviewValue=(X=256.000000,Y=0.000000,Z=0.000000,W=1.000000)
      SortPriority=3
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=416
      MaterialExpressionGuid=A4507FC047566AB8EABE53916AA63A1F
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_8"
      InputName="DerivativeMap_G"
      Description="Require Scale and Biased Value"
      Id=D87C1DC8498CFC78E0BBA2A9177D457A
      InputType=FunctionInput_Scalar
      SortPriority=2
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=240
      MaterialExpressionGuid=18EE169546DE45117B4932B2A03906B8
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   Begin Object Name="MaterialExpressionFunctionInput_9"
      InputName="TextureScaleFactorY"
      Description="Could be negative (es xNormal)"
      Id=E0D234F84D62B632C6119B99787BF3B0
      InputType=FunctionInput_Scalar
      PreviewValue=(X=-256.000000,Y=0.000000,Z=0.000000,W=1.000000)
      SortPriority=4
      MaterialExpressionEditorX=-1504
      MaterialExpressionEditorY=592
      MaterialExpressionGuid=A4507FC047566AB8EABE53916AA63A1F
      Function=MaterialFunction'"DerivativeNormalPerturb"'
   End Object
   FunctionExpressions(0)=MaterialExpressionFunctionOutput'MaterialExpressionFunctionOutput_1'
   FunctionExpressions(1)=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_5'
   FunctionExpressions(2)=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_6'
   FunctionExpressions(3)=MaterialExpressionComponentMask'MaterialExpressionComponentMask_2'
   FunctionExpressions(4)=MaterialExpressionComponentMask'MaterialExpressionComponentMask_3'
   FunctionExpressions(5)=MaterialExpressionDDX'MaterialExpressionDDX_3'
   FunctionExpressions(6)=MaterialExpressionDDX'MaterialExpressionDDX_4'
   FunctionExpressions(7)=MaterialExpressionDDY'MaterialExpressionDDY_3'
   FunctionExpressions(8)=MaterialExpressionDDY'MaterialExpressionDDY_4'
   FunctionExpressions(9)=MaterialExpressionVertexNormalWS'MaterialExpressionVertexNormalWS_1'
   FunctionExpressions(10)=MaterialExpressionMultiply'MaterialExpressionMultiply_9'
   FunctionExpressions(11)=MaterialExpressionMultiply'MaterialExpressionMultiply_10'
   FunctionExpressions(12)=MaterialExpressionMultiply'MaterialExpressionMultiply_11'
   FunctionExpressions(13)=MaterialExpressionAdd'MaterialExpressionAdd_3'
   FunctionExpressions(14)=MaterialExpressionMultiply'MaterialExpressionMultiply_12'
   FunctionExpressions(15)=MaterialExpressionMultiply'MaterialExpressionMultiply_13'
   FunctionExpressions(16)=MaterialExpressionAdd'MaterialExpressionAdd_4'
   FunctionExpressions(17)=MaterialExpressionMultiply'MaterialExpressionMultiply_14'
   FunctionExpressions(18)=MaterialExpressionWorldPosition'MaterialExpressionWorldPosition_1'
   FunctionExpressions(19)=MaterialExpressionDDX'MaterialExpressionDDX_5'
   FunctionExpressions(20)=MaterialExpressionDDY'MaterialExpressionDDY_5'
   FunctionExpressions(21)=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_2'
   FunctionExpressions(22)=MaterialExpressionCrossProduct'MaterialExpressionCrossProduct_3'
   FunctionExpressions(23)=MaterialExpressionDotProduct'MaterialExpressionDotProduct_1'
   FunctionExpressions(24)=MaterialExpressionMultiply'MaterialExpressionMultiply_15'
   FunctionExpressions(25)=MaterialExpressionMultiply'MaterialExpressionMultiply_16'
   FunctionExpressions(26)=MaterialExpressionAdd'MaterialExpressionAdd_5'
   FunctionExpressions(27)=MaterialExpressionMultiply'MaterialExpressionMultiply_17'
   FunctionExpressions(28)=MaterialExpressionSubtract'MaterialExpressionSubtract_1'
   FunctionExpressions(29)=MaterialExpressionNormalize'MaterialExpressionNormalize_1'
   FunctionExpressions(30)=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_7'
   FunctionExpressions(31)=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_8'
   FunctionExpressions(32)=MaterialExpressionFunctionInput'MaterialExpressionFunctionInput_9'
   CombinedInputTypes=15
   CombinedOutputTypes=15
   ThumbnailInfo=SceneThumbnailInfoWithPrimitive'SceneThumbnailInfoWithPrimitive_2'
End Object


For some reason I found that posted image hilarious… this is the only industry where such an image would be accepted as ‘normal’ (no pun intended).

Interesting results… I don’t see much use in DeriveNormalZ if you’re using TC_NormalMap compression unless I’m missing something. Perhaps it is useful if you’re combining lots of normal maps in the material, but just using the R and G channels and getting the overall B channel.

Random tests + wip things usually come with even more hilarious results.
animation is from engine and with no gun just looks quite weird expecially on this naked big gim there.
It has been used as i was testing the new skin shader too and put many of them to try out performance on my pc.

TC_Normalmap is supposed to compress r and g in DXGI_FORMAT_BC5_SNORM ( I have not checked but it is quite reasonable) so possibly the blue is just calculated to be displayed on screen as engine expects a tangent space normal, This doesn’t change it is the most efficient format for derivative too.
I have no idea if it calculates b in my shader but I suppose it will get optimized out in any case during compilation, but I don’t like to just suppose I hoped someone could confirm that.

I think that another use of derivative maps could be with morph targets es I planned to have a base thin body shape and encode a heavy body shape in vertex color without the need to store/calculate tangents/binormals.
However some more or less specific use may require engine to be modified so for now I will put this in pause as long as no proper use emerges.

Same here. First thing that came to my mind was Machinima Skyrim Gamer **** :- https://www.youtube.com/watch?v=ZPllpzxmM5k#t=135

Reminder : Use just clothed models in proof of concepts or at least invite some women to the “party” :slight_smile:
I admit the pic is quite misleading, my fault, but from now on stay on the derivative normal map topic please.