To display the node title, you need to override the GetCaption function. Once overridden, the title can be set as follows:
void UMaterialExpression::GetCaption(TArray<FString>& OutCaptions) const
{
OutCaptions.Add(TEXT("NodeTitle"));
}
I assume that’s what you did. You can also add something like additional “headers” under the node title using the same array. I assume the order of the elements is reversed, so the last element of the array will be the main node title (not sure why it’s done that way). So if you want, you can write something like this:
void UMaterialExpression::GetCaption(TArray<FString>& OutCaptions) const
{
OutCaptions.Add(TEXT("UnderTitle2"));
OutCaptions.Add(TEXT("UnderTitle"));
OutCaptions.Add(TEXT("NodeTitle"));
}
Or like this:
void UMaterialExpression::GetCaption(TArray<FString>& OutCaptions) const
{
OutCaptions.Add(TEXT("UnderTitle\nUnderTitle2"));
OutCaptions.Add(TEXT("NodeTitle"));
}
Which should give the same result as in the image below:

Now, to display the output names, it should be enough to set the variable bShowOutputNameOnPin
to true. By default, it is false, because most built-in nodes that perform some calculations have only one output pin and therefore the name is hidden by design.
This property should be set in the constructor as follows:
UWorldAlignedEmissiveMask::UWorldAlignedEmissiveMask(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
...
bShowOutputNameOnPin = true;
...
}
After compiling, you may need to replace the old node with the new one on the node graph to see these changes.
Now about those errors you showed earlier. Obviously, this is related to errors you made somewhere in the code inside the GetMask
function. The error occurs in this line of code:
const int32 WorldAlignedCoord = Compiler->Add(MaskXY, MaskXZ);
This is because MaskXY
is “float2” while MaskXZ
is “float4”.
The problem starts in the following line:
const int32 MaskedXZ = Compiler->ForceCast(
Compiler->ComponentMask(WorldPosCode, 1, 0, 1, 0),
MCT_Float3
);
You are correctly using ComponentMask
which creates a “float2” from “float3”, then for some reason unknown to me you cast to “MCT_Float3” resulting in “float3”. So on this line you will have “float3 MaskXZ”, although I assume based on the variable name you meant to have “float2 MaskXZ”.
Now on the next line you did the following:
const int32 CoordXZ = Compiler->Div(
Compiler->AppendVector(MaskedXZ, Compiler->Constant(0.0f)),
TileSizeCode);
Which returns “float4” because “AppendVector(float3, float) → float4”. I also don’t understand why you are using the AppendVector function. This function concatenates vectors. For example, if you have vectors float2(1, 2) and float2(4, 5), the function will return float4(1, 2, 4, 5). So I don’t see any point in using it here.
The “If” operator is written with errors as well. In my opinion, the way it is written will not give the desired result you wanted. In addition, the last argument of the Compiler->If
function is “Threshold”. I think it should be very small, for example, 0.00001. “1” is a very large uncertainty.
I tried to fix these problems and ended up with the following function:
UWorldAlignedEmissiveMask::FMask UWorldAlignedEmissiveMask::GetMask(FMaterialCompiler* Compiler)
{
FMask Result;
const int32 WorldPosCode = WorldPos.Compile(Compiler);
const int32 AxisCode = ProjectionAxisIndex.Compile(Compiler);
const int32 TileSizeCode = TileSize.Compile(Compiler);
const int32 TexCode = Tex.Compile(Compiler);
const int32 CoordXY = Compiler->Div(Compiler->ComponentMask(WorldPosCode, 1, 1, 0, 0), TileSizeCode);
const int32 CoordXZ = Compiler->Div(Compiler->ComponentMask(WorldPosCode, 1, 0, 1, 0), TileSizeCode);
const int32 CoordYZ = Compiler->Div(Compiler->ComponentMask(WorldPosCode, 0, 1, 1, 0), TileSizeCode);
// This one will be used if "AxisIndex >= 0.5"
const int32 WorldAlignedCoordElse = Compiler->If(
AxisCode,
Compiler->Constant(1.5),
CoordYZ,
CoordYZ,
CoordXZ,
Compiler->Constant(0.00001)
);
const int32 WorldAlignedCoord = Compiler->If(
AxisCode,
Compiler->Constant(0.5),
WorldAlignedCoordElse,
WorldAlignedCoordElse,
CoordXY,
Compiler->Constant(0.00001)
);
const int32 SampleColor = Compiler->TextureSample(TexCode, WorldAlignedCoord, SAMPLERTYPE_Color);
const int32 Intensity = Compiler->Dot(SampleColor, Compiler->Constant3(1.0, 1.0, 1.0));
const int32 WhiteMask = Compiler->SmoothStep(
Compiler->Constant(WhiteThreshold),
Compiler->Constant(WhiteThreshold + WhiteThresholdDelta),
Intensity);
Result.EmissiveOutput = Compiler->Mul(Compiler->Constant3(1.0, 1.0, 1.0), WhiteMask);
Result.OpacityMaskOutput = WhiteMask;
return Result;
}
Let me know if this solution works for you. I may have forgotten to mention something, so if something doesn’t work or you have any questions, feel free to ask.