CrowPSXDocumentationv1.1.0Get CrowPSX ↗
Docs/Vertex painting

MATERIAL WORKFLOWS

Vertex painting

Four-layer painting, layer maps, Polybrush integration, and painted PBR.

PACKAGE VERSION 1.1.0
On this pageLayer weightsPolybrush setupMesh requirementsVertex lighting and local lightsDefault and Lite layersPBR layersSampler-state limitationAlpha, shadows, and bakingCommon problems

The painted shaders are dedicated layered materials; they do not use the regular Base Texture workflow. Vertex RGBA stores Base/Red/Green/Blue layer weights.

CrowPSX/Surface/Vertex Painting/Default#

Four Albedo layers, each with a Tint and independent UV transform, plus compatible Default lighting, retro, rendering, grunge, and emission controls.

CrowPSX/Surface/Vertex Painting/Lite#

Four Albedo layers with Tint and UV controls, using the reduced Lite feature set.

CrowPSX/Surface/Vertex Painting/PBR#

Four PBR layers. Every Base, Red, Green, and Blue layer independently chooses Separate Maps or Packed Map and Smoothness or Roughness. Each layer contains:

  • Albedo texture, Tint, and UV transform
  • Normal texture, signed Normal Strength (-4 to 4), and UV transform
  • Metallic texture, Metallic Strength, and UV transform
  • Ambient Occlusion texture and strength
  • Height texture, Parallax Height, and per-layer Height Floor
  • Smoothness/Roughness texture, Red/Alpha channel selection, response value, and UV transform
  • Optional linked PBR UVs driven by that layer's Albedo transform

Packed painted maps use R Metallic, G Ambient Occlusion, B Height, and A Smoothness or Roughness. The inspector can generate a packed texture from the active layer's separate maps. The same normalized layer weights blend Albedo, Normal, Metallic, Ambient Occlusion, Height, surface response, and texture alpha. Parallax Height is per layer and the integer Parallax Steps setting is shared across all layers.

All maps in one painted layer share that layer's Albedo sampler state to stay inside D3D11 sampler limits. They can use separate UV transforms, but their texture filtering and wrap behavior should be compatible. Separate Maps can be expensive when several painted layers contribute at once; packed maps are recommended for runtime-heavy materials.

See Vertex Painting.

CrowPSX includes three dedicated four-layer vertex-painting shaders:

CrowPSX/Surface/Vertex Painting/Default
CrowPSX/Surface/Vertex Painting/Lite
CrowPSX/Surface/Vertex Painting/PBR

Layer weights#

The mesh vertex-color channels are interpreted as:

R = Red layer
G = Green layer
B = Blue layer
A = Base layer

CrowPSX normalizes the four weights. If all channels are zero, the shader falls back to the Base layer. Layer Blend Strength fades the painted result toward Base. Layer Blend Sharpness increases or softens dominance at transitions.

Polybrush setup#

Polybrush is optional. For predictable four-layer splat painting, use Texture Paint rather than ordinary unrestricted Color Paint.

CrowPSX writes recommended texture-paint metadata automatically. If Polybrush displays a texture-blending warning, run:

Tools > CrowPSX > Polybrush > Configure Texture Painting

Then reselect the object or leave and re-enter Texture Paint mode. The generated layout maps Base to alpha, then Red, Green, and Blue to their matching vertex channels.

Mesh requirements#

Painting resolution is limited by mesh vertex density. A quad with four vertices can only store values at its corners. Subdivide the mesh or author sufficient topology for the desired brush detail.

The mesh and any optimization/combination pipeline must preserve vertex colors. Paint a duplicate before applying destructive mesh operations.

Vertex lighting and local lights#

CrowPSX Vertex mode follows Unity's native Gouraud path. The ForwardBase main light and the Built-in VERTEXLIGHT_ON list are evaluated at mesh vertices and interpolated across the surface.

In the Built-in pipeline, set local point and spot lights to Not Important to place them in that native vertex-light list. Unity represents those lights as unshadowed point lights there. Auto and Important lights arrive as ForwardAdd pixel lights and are still vertex evaluated in pure Vertex mode; point and spot lights there get a narrow per-fragment envelope so Unity's rectangular ForwardAdd bounds never show.

Prefer Not Important when you want the classic look. Unity scissors a ForwardAdd pass to the light's bounds, so an Auto or Important light cannot spill past its range volume no matter how large the triangles are, the envelope hides the hard box edge but cannot render outside it. A Not Important light is evaluated in ForwardBase alongside the rest of the mesh, so its interpolated falloff carries across the whole triangle. Use Vertex Hybrid when those lights need their normal falloff, cookies, or realtime shadows.

Vertex density controls the result: a local light only affects a triangle when it reaches one or more of that triangle's vertices.

Main Light Shadows optionally samples the Built-in ForwardBase main light's shadow per fragment. It does not add shadows to native vertex point or spot lights.

Default and Lite layers#

Each Base/Red/Green/Blue layer contains:

  • Albedo texture
  • Tint
  • Independent Albedo tiling, offset, rotation, and scrolling

These shaders do not use regular _MainTex or _Tint properties.

PBR layers#

Each Base/Red/Green/Blue layer independently selects its PBR Map Workflow, Surface Response Workflow, and Link PBR UVs option. A material can mix packed and separate layers as needed.

Albedo#

Texture, Tint, and UV transform. When Link PBR UVs is enabled, this transform controls all core PBR maps in the layer.

Normal#

Normal texture, signed Normal Strength, and independent UV transform. Import the asset as a Unity Normal Map. Strength accepts -4 to 4: negative values invert the map's tangent-space relief, 0 disables its influence, and the recommended range is -2 to 2. The CrowPSX inspector shows a Fix action for an incorrect import type.

Metallic#

Metallic texture, Metallic Strength, and independent UV transform. The texture uses its red channel. The scalar is used directly when no map is assigned and multiplies the map when present.

Surface response#

Choose Smoothness or Roughness independently for each layer. The response texture supports Red or Alpha channel selection and an independent UV transform. The scalar is used directly when no map is assigned and multiplies the selected channel when present.

Ambient occlusion#

The separate AO map uses its red channel. Ambient Occlusion Strength blends between no occlusion and the texture and affects indirect diffuse light and reflections.

Height and parallax#

The separate Height map uses its red channel. Parallax Height controls view-dependent UV relief for that layer; it does not displace vertices or alter the silhouette. Every layer supports 0–1, with 0.1 marked as the recommended maximum for normal use. Height Floor is also independent per layer: 0 uses the complete map, while higher values raise that layer's minimum height and lift recessed areas toward the peaks. A floor of 1 produces a flat height field at the highest level. Parallax Steps is an integer from 1 to 64 and is shared by all four layers; values above 32 receive an amber performance warning, while values below 4 trade visible stepping for lower sampling cost.

Packed maps#

Packed Map uses R Metallic, G Ambient Occlusion, B Height, and A Smoothness or Roughness. Normal remains separate. The channel guide in the material inspector follows the selected response workflow.

In Separate Maps mode, each layer shows a themed Pack Base/Red/Green/Blue Layer card directly below its workflow control. Press Review Packed Map Creation →, review the channel and save summary, then choose Create & Switch to Packed. CrowPSX creates a linear PNG beside that layer's Albedo texture when possible, otherwise beside the material. It assigns the map and switches only that layer to Packed Map; the separate-map references are retained. Choose Not Now to leave the material unchanged.

Linked PBR UVs#

Enable Link PBR UVs to make the layer's Albedo tiling, offset, rotation, and scrolling control its Normal, Metallic, response, AO, Height, and Packed maps. Disable it when individual transforms are required.

Sampler-state limitation#

The PBR painted shader can sample several texture families across four layers. To remain below D3D11 pixel-shader sampler limits, all maps in one layer share that layer's Albedo sampler state. They can still have separate textures and UV transforms, but should use compatible filtering and wrap settings within a layer.

Separate Maps is the heaviest painted-PBR workflow because an active layer can independently sample Albedo, Normal, Metallic, surface response, AO, and Height. Prefer Packed Map on runtime-heavy materials. Higher Parallax Steps also increase the number of height samples.

CrowPSX skips map reads for painted layers whose normalized weight is zero. Solid single-layer areas therefore evaluate only that layer, while blended transitions evaluate each layer that visibly contributes. Setting a layer's Normal Strength, Ambient Occlusion Strength, or Parallax Height to 0 also skips the corresponding optional map work. Packed/separate selection remains independent per layer and is resolved at runtime rather than creating every possible four-layer shader combination.

Alpha, shadows, and baking#

Layer texture alpha is blended with the same vertex weights. It can feed Cutout or Transparent rendering and is used by compatible shadow and meta passes. A painted fence, leaf, or damaged surface can therefore produce a layer-dependent cutout silhouette.

Common problems#

Brush strokes follow large triangles#

The mesh needs more vertices.

The material stays on Base#

Confirm that the painted shader is assigned, the mesh has vertex colors, Polybrush is editing the rendered mesh, and Layer Blend Strength is above zero.

Unexpected colors or base leakage#

Inspect the RGBA weights. Texture Paint is recommended because it maintains a clearer normalized layer workflow than arbitrary Color Paint values.

Polybrush says vertex colors or texture blending are unsupported#

Reimport the painted shader, run the CrowPSX Polybrush configuration command, and reselect the object so Polybrush refreshes its compatibility check.

CrowPSX 1.1.0 · CrowBite
Shader reference and setup guides.