Texture Painting - Channels

In the texture paint panel there is the “Channels” boxes. They do not seem to do anything.
I am trying to paint into each channel separately for a splat map. No matter what channel is toggled on or off it always paints in all 3 channels. This makes painting 3-color masks in engine really unwieldy.

https://docs.unrealengine.com/latest/images/Engine/UI/LevelEditor/Modes/MeshPaintMode/VertexColor/PaintingColors/button_Channels.jpg

These check boxes set which color/alpha channels should be affected by the paint brush. I submitted a question about this before for vertex color, but the response didn't really address the issue of the described function not working.

It looks like the code for that tool was actually not hooking up to whatever pixel shader this is supposed to feed into. One of our engineers has a fix.

I’m not very familiar with this feature, but I think I have a fix. It requires modifying MeshPaintPixelShader.usf. There could be bugs in this code - use at your own risk.

I took a look in the MeshPaintRendering.cpp code, and it looks like the values from the channel masks end up in FVector4 ChannelFlags, which is then sent down to MeshPaintPixelShader, in the ChannelFlagsParameter:

FVector4 ChannelFlags;
ChannelFlags.X = InShaderParams.RedChannelFlag;
ChannelFlags.Y = InShaderParams.GreenChannelFlag;
ChannelFlags.Z = InShaderParams.BlueChannelFlag;
ChannelFlags.W = InShaderParams.AlphaChannelFlag;
SetShaderValue(RHICmdList, ShaderRHI, ChannelFlagsParameter, ChannelFlags );

ChannelFlagsParameter is bound to the shader parameter c_ChannelFlags …
ChannelFlagsParameter.Bind( Initializer.ParameterMap, TEXT( “c_ChannelFlags”) );

but MeshPaintPixelShader.usf doesn’t actually have a c_ChannelFlags parameter! (in fact, it has neither c_ChannelFlags nor c_GenerateMaskFlag. Not sure what c_GenerateMaskFlag is supposed to do.)

I added a channel flags variable to MeshPaintPixelShader.usf:

float4 c_ChannelFlags;

and modified the way NewColor is assigned to use it:

		float4 BrushColor = c_BrushColor;

		NewColor.a = lerp(OldColor.a, BrushColor.a, PaintAmount * c_ChannelFlags.a);
		NewColor.r = lerp(OldColor.r * OldColor.a, BrushColor.r * BrushColor.a, PaintAmount * c_ChannelFlags.r);
		NewColor.g = lerp(OldColor.g * OldColor.a, BrushColor.g * BrushColor.a, PaintAmount * c_ChannelFlags.g);
		NewColor.b = lerp(OldColor.b * OldColor.a, BrushColor.b * BrushColor.a, PaintAmount * c_ChannelFlags.b);
		if (NewColor.a > 0.0f)
		{
			NewColor.rgb /= NewColor.a;
		}

That seems to do the trick. I’ll work up a pull request containing this fix soon.

Hello Spectronaut,

Yes this fix does seem to work for now. However have you see the painting on layers through the use of Material Blend Layers?

Here is the documentation for it.

I personally recommend this method. It allows for much more control and customization. It will also allow, through the use of shared texture sampling, to add many different layers.

Hi - the material we’re working with is not applied to a landscape, and so this feature isn’t really appropriate here.

I’ve created a pull request that contains my fix. Thanks!

https://github.com/EpicGames/UnrealEngine/pull/1556

Are you saying you can use the Lanscape Material Layer System anywhere you would want to paint a mask in engine? Because we’re painting on a static mesh building, not Landscape terrain.

Hello Spectronaut,

Unfortunately no. It is a landscape specific function that requires layer info to be allocated with the landscape layer in order to work.

With that network it only affects landscapes.