Custom Paint Mods

From Automation Game Wiki

Beginning with LCv4.2, Automation supports the creation of custom paint materials which can be applied to cars, fixtures, and engine parts. These materials also support the Exporter, including exporting to BeamNG.

Overview

A Custom Paint mod is a collection of files, of which a Custom Paint file is the parent.

The Custom Paint file contains the settings and applicable options for the Custom Paint, as well as a reference to the paint material.

The custom paint material itself is a Material in UE4, which is set up in a specific way. Material variables can have an editable_ prefix in the name if you want the player to have access to it in the custom paint settings in-game. Variables and parameters also need to be input into the export user data, contained within the material, for them to export correctly. Materials will not export correctly at all without this export user data.

Workflow

  1. In UE4:
    1. Set up a mod.
    2. Create and fill out a Custom Paint file.
    3. Create your Custom Paint material.
    4. Assign variables to the export user data.
  2. In the Automation Workshop Publishing Tool:
    1. Set up a workshop item.
    2. Share your mod.

Create your Custom Paint mod

Create A New Mod

After setting up the modding SDK from Here, create a new blank mod:

Create A Custom Paint File

In your mod content folder, right-click and add a new Custom Paint file. This is the file the game uses to load the paint into the UI.

CreateCustomPaintFile1.jpg

Open the Custom Paint file. It has a few parameters:

  • Name - This will be the name of the paint as it will appear in-game.
  • Material Instance - This is the actual paint itself. The material instance defines how the paint looks, what parameters are available, and how it looks when exported.
  • GUID - This is an unique identifier for this custom paint. It is a random value. This is how the paint is stored and saved by the game.
  • Family GUID - As above, this is an unique identifier. This one is currently un-used, but could in the future be used for storing what paints are part of the same family, if you decide to make several.

Create A Material

Right-click the content browser again, and create a new Material. This is the actual shader: it defines how the paint looks.

CreateCustomPaintMaterial.jpg

Open the material. UE4 uses standard PBR Metallic-Roughness workflows. What this means is you define a material by giving it:

  • a colour (0,0,0 - 1,1,1)
  • telling it how rough it is (0 - 1, 0 being shiny)
  • how metallic it is (0 - 1, 0 being plastic)

as well as a few additional things that help optimise parts of the rendering process, such as:

  • a Normal map (this defines surface detail that would be too fine or complicated to be geometry)
  • an Ambient Occlusion map (this helps darken and reduce reflections and specular highlighting on parts of the geometry that should be darker than usual, and which the lighting model cannot properly calculate)
  • Opacity/Opacity Mask
  • etc..

Material Requirements

Opacity

All Custom Paint materials must be set to Masked, unless it is a transparent material.

Two nodes should be a part of the Opacity or Opacity Mask input. If your material does not have any transparent or masked info, these two nodes are still required.

SetMaterialToMasked.png

If your material does have opacity information, simply add these two nodes at the end with a multiply:

SetMaterialToMasked1.png

Two-Sided Material

If at all possible, your material should be set to two-sided. This ensures the interior of the car doesn't have any transparency holes in it from fixtures or paints. To enable Two-Sided, click on the main material node in the material editor, and in the details panel, under the Material category, Tick Two Sided.

CustomPaintSetTwoSided.jpg

Parameter Names

For parameters to appear in-game in the UI for the player to customize, it must have the editable_ prefix. Only Vector and Scalar parameters will appear in the UI. Vector parameters will always appear as a Colour Picker, and Scalar parameters will mostly always appear as a Slider. If a Scalar parameter also has the _Bool suffix, it will instead appear as an Enable/Disable switch. A Vector parameter cannot have the _Bool suffix.

Example parameters:

CustomPaintParameterNameExamples.jpg

CustomPaintParameterNameExamplesInGame.jpg

Note how in-game the Burn Colour parameter isn't visible, and the Burned parameter is an Enable/Disable toggle. This is because the Burn Colour parameter did not have the editable_ prefix, and the Burned parameter had the _Bool suffix. Also note how the Scalar parameter appears as a slider, and the Vector parameter appears as a colour picker.

Export Material User Data

Export Material User Data main page

From the details panel of the material, expand the Material category, and from the Asset User Data array, add an Export Material User Data. This is where the values and parameters for the material are stored for the exporter. The exporter can only see the parameter names in the export user data. The exporter cannot know the layout of the parameters in the material, and cannot, therefore, know how to use those parameters. The export user data exists to simplify the parameters down to a known layout, such that the exporter can then line those values up with what the BeamNG material system uses, as well as other potential exporter plugins.

Note that the export user data only has access to a limited subset of behaviors for materials, and cannot do a lot of the fancy things that the UE4 material editor is capable of. It should, however, still be sufficient for most basic and intermediate-level materials.

Once you have fed your parameters into the export user data, your material should now export correctly.

Helper Functions For Materials

Inside materials and from the palette menu, or the right-click menu, you can access custom material functions that have been made and exposed to the material system. These nodes are designed to help you with designing your materials. Camso has designed a few material functions that help with designing custom paint materials. These materials can be accessed from the Camso or Custom Paint sub-categories within the palette or right-click menu inside materials.

The following nodes and material functions will help you to make materials easier:

GetStampAlpha
MatFunction GetStampAlpha.jpg

This is one of the most important nodes, as it deals with all the functions, variables, and textures, that are used by the game to put the stamp holes on cars and fixtures. Without this node, fixture stamping does not work. Your material must be set to masked, and this node must be plugged into the opacity mask section.

It has one input, and you should not do anything with it.

MF_AASmoothStep
MatFunction AASmoothStep.jpg

This is useful for turning a range of values into a 0 or a 1, or turning a range of values into a step where black suddenly turns to white.

It has three inputs;

  • In - this is the value you want to turn into a 1 or a 0
  • CompValue - If the In value is above this, the out value will be 1. if In is less than this value, the output will be 0.
  • Range - This is how large of a transition period the value should change in, in screen-space pixels. A small value will change over the course of a single pixel or less, and a large value will change over many pixels.
MF_BlendAngleCorrectedNormals
MatFunction BlendAngleCorrectedNormals.jpg

This blends multiple normal maps together, with correctly normalized results. Other methods of blending normal maps do not correctly account for the blue vector, or do not accurately derive the blue vector. This method is more compute-intensive, but results in perfectly-blended normals.

It has four inputs;

  • In - this is the base normal, which you want to blend another normal with
  • Blend - this is the second normal that you want to add to the first
  • Strength - This is how much of the Blend normal you want to add to the base normal
  • Clamp - this ensures that none of the normal
MF_BlendFade
MatFunction BlendFade.jpg

This is a mandatory node as part of the material for custom paints or fixture materials. Multiply it with any other part of your opacity mask network, or if you dont have any, plug it right in.

it has one input;

  • Opacity - This lets you pass in any other opacity value, and it will be blended with this node. this is mostly used to plug in the GetStampAlpha material function.
MF_CarpaintBackfaceBlend
MatFunction CarpaintBackfaceBlend.jpg

This node will take two material attributes, and let one pass through for the front faces, and the other through for the backfaces.

It has three inputs;

  • Backface- This takes a Material Attributes in, and will pass it through to the output only if the current pixel is of the backface of a polygon.
  • Front face- This takes a Material Attributes in, and will pass it through to the output only if the current pixel is of the front face of a polygon.
  • Alpha - This is an optional input, and will override the default mask used to detect whether a face is the front or back of a polygon.
MF_DynamicGrungeAndWear_Mask
MatFunction DynamicGrungeAndWear.jpg

This node will create a mask ( a 0-1 value) where 1 will appear on corners and sharp curves, and 0 will appear on flat surfaces.

it has six inputs;

  • Curvature Cutoff - This will adjust how small/thick the corners will be, where a larger value will make the grunge mask thicker on corners.
  • Dirtiness - This is the only mandatory input. It takes a scalar value between 0 and 1, where 0 will be no grunge output, and 1 will be the most grunge.
  • Adjust A Power - this node will adjust some of the grunge mask generation.
  • Adjust A Divide - this node will adjust some of the grunge mask generation.
  • Adjust B Power - this node will adjust some of the grunge mask generation.
  • Adjust B Divide - this node will adjust some of the grunge mask generation.
MF_FakeDarkenedMattePaint
MatFunction FakeDarkenedMattePaint.jpg

This node is useful when making paint, as it forces the specular channel darker as the paint colour becomes darker.

Because UE4 uses a fast PBR workflow, even a pure black non-metallic surface will appear somewhat bright, so this node is useful for darkening the paint further by dynamically adjusting the specular channel of the material.

This material is used by plugging the Base Colour, Metallic, (optional) Specular, and Roughness inputs from your material into this node, and plugging the output into the Specular channel of the material.

It has four inputs;

  • Base Colour - Plug the material's base colour input into here.
  • Metallic - Plug the material's Metallic input into here.
  • Specular - Plug the material's Specular input into here, if it is used. If not, leave empty.
  • Roughness - Plug the material's Roughness input into here.
MF_HeightLerp
MatFunction HeightLerp.jpg

This node creates a more useful blend between two heightmaps than a simple Lerp or SmoothStep function. It takes two heightmaps, one for each of the materials or textures that you wish to blend, as well as a Transition Phase (or Alpha), and outputs a new heightmap and mask for use in a Lerp or other material blend function.

The result of this node is a mask for blending between two textures or materials, modulated by the heightmaps of those textures or materials. This is useful for blending, say, bricks into grass, as it will account for the height of each brick, and blend the grass first into the cracks and mortar.

It has three inputs;

  • Height 1 - This is the heightmap of the first texture/material you wish to blend.
  • Height 2 - This is the heightmap of the second texture/material you wish to blend.
  • Transition Phase - This is the phase of the transition, otherwise known as an alpha, for blending between Height 1 and Height 2. A transition phase of 0 means the mask will let all of Height 1 through, and a value of 1 will let as much of Height 2 through as it can, given the height values of each input. a Value of 0.5 will blend the two heights equally.
MF_MipOverride_Mask
MatFunction MipOverrideMask.jpg

This is a fun one. It acts a bit like a Camera Depth Fade, where it defines a transition mask based on depth or distance, but instead of using distance from pixel to camera, which is prone to inconsistencies with different FOVs, it instead uses the distance between the UVs of the adjacent pixels to define its mask. What this means is, regardless of the distance from the camera, or the FOV, the mask output from this node will always occur at the same texel density.

This node was developed for the Fixture Taillight Glass material, where if the glass was small enough on screen, the pixels between the textures was creating enough noise that a transition to a simplified version of the material was needed. Since the material can change scale based on the fixture's size, the camera can move farther or closer away from the car depending on the camera's position, and the FOV can change depending on the user's game or photoscene settings, this was the only way to consistently define a mask for the simplified version of the material.

It will output a 1 if the current pixel's texel size is less than the input threshold.

It has five inputs;

  • DDX - This is the DDX of the UVs for the texture.
  • DDY - This is the DDY of the UVs for the texture.
  • Texture - This is the texture object of the texture you wish to override at a certain texel size.
  • Transition Contrast - This is how much of a range you wish the mask to blend between. A lower value means a sharper, more immediate blend.
  • Max Texel Size - This is the minimum size of a texel, in horizontal or vertical screen pixels, that you wish the texture to be visible. If the texture is smaller than this value, the mask output is 1.
MF_StepScaleable
MatFunction StepScalable.jpg

This is a more performant version of MF_AAStep, where at lower shader settings, it falls back to a standard Step function.

It has two inputs;

  • In - This is the value you want to apply the Step function to.
  • Comp Value - This is the value at which you want the input to return 1. If the input value is less than the comp value, the result will be 0.
MF_CustomPaint_Lerp_Scalar
MatFunction CustomPaint Lerp Scalar.jpg

This node follows the logic of the export parameters, where the values A and B can be LERP-ed together by an Alpha, and an optional Power. The power node forces the Alpha downward, such that the LERP becomes more exponential. A higher value of Power results in the Alpha applying a smoother blend between A and B. The Power is blended into the Alpha such that the higher the alpha, the less the power is applied. the end result is more control over the lower values of Alpha, while the higher values remain closer to a linear blend.

This node is useful for a Scale input for textures, as the Alpha can be driven by a player-editable parameter (with the editable_ prefix) and the player has more control over the scale of the texture at lower scales.

The formula for the output is as such:

lerp (A, B, Lerp(Power, Alpha, Power))

It has five inputs;

  • A - Just like a lerp, this is the A input. If the Alpha is 0, the result is 100% A.
  • B - Just like a lerp, this is the B input. If that Alpha is 1, the result is 100% B.
  • Alpha - Just like a lerp, this is the Alpha input. If the Alpha is 0, the result is 100% A, if Alpha is 0.5, the result is equally half of A and B (unless the Power input is anything other than 1, and the Has Lerp Power is True.)
  • Power - This is the modifier for Alpha. A value above 1 will slowly force the lower values of Alpha further down towards 0, much like a power node would, but higher values of Alpha will remain higher. This is done by applying a second Lerp between the Power and Alpha inputs.
  • Has Lerp Power - This a bool input. If the input bool is True, the Power input is evaluated. If False, the Power input is ignored and this node acts exactly like a standard lerp.
MF_CustomPaint_Lerp_Vec2

Exactly like the scalar version of this node, except it works on Vec2 values instead of scalars.

MF_CustomPaint_Lerp_Vec3

Exactly like the scalar version of this node, except it works on Vec3 values instead of scalars.

MF_CustomPaint_Lerp_Vec4

Exactly like the scalar version of this node, except it works on Vec4 values instead of scalars.

MF_CustomPaint_TexList_002
MF_CustomPaint_TexList_003
MF_CustomPaint_TexList_004
MF_CustomPaint_TexList_005
MF_CustomPaint_TexList_006
MF_CustomPaint_TexList_007
MF_CustomPaint_TexList_008
MF_CustomPaint_TexList_009
MF_CustomPaint_TexList_010
MF_CustomPaint_TexList_011
MF_CustomPaint_TexList_012
MF_CustomPaint_TexList_013
MF_CustomPaint_TexList_014
MF_CustomPaint_TexList_015
MF_CustomPaint_TexList_NthDegree
MF_CustomPaint_Texture
MF_CustomPaint_TextureMaskChannel
MF_CustomPaintScale
MF_ExportParameterSwitch_Scalar
MF_ExportParameterSwitch_Vec3
MF_FakeDarkenedMattePaint
MF_FixtureUVs
MF_NormalStrength