Surface Variants

Surface Variants allow you to specify parameters to recolor a texture, primarily for creating textures like stone, brick, siding, etc. with variations in the color of the blocks that compose the texture. It can also be used to recolor a texture and save it to disk.

A Surface Variant describes one recolorable surface. It holds four things:

  • a texture,
  • the normal map that is paired with that texture,
  • the transform that places both of them on a block,
  • the range of colors that the blocks use.

The recolor works through a gradient map, which replaces the colors of a texture with the colors of a gradient that you author. This page explains the Surface Variant asset, its inspector, and the way in which a texture definition applies it.

Where PolyBash uses surface variants

A texture definition or a Surface Variant Applier applies a surface variant. A texture definition is an asset that lays out blocks from a list of prefabs and captures the result into a texture.

PolyBash provides four texture definitions. Create each one from the Assets → Create → Snowtop → PolyBash menu.

Asset Menu entry Layout
Wall texture definition Wall Texture Definition Rows of wall blocks, with a row count, a total height, and a per-row offset.
Path texture definition Path Texture Definition Rows of path blocks, with a row count, a total height that sets the length of the path, and a per-row offset.
Stair texture definition Stair Texture Definition Steps, with a step count, a height, a depth, and a per-step offset.
Roof tile texture definition Roof Tile Texture Definition Rows of roof tiles, with a row count, a tile shape, and a per-row offset.

Every texture definition shares the same Texture Generation settings, and so the same surface variant list. The section Apply a surface variant to a texture definition describes that list. The page Texture Generation documents every other setting of a texture definition.

The blocks come from prefabs, and each prefab has its own material. During the capture, a surface variant replaces that material, so one prefab set produces every surface that you need. Only the renderer on the prefab root receives the surface variant, and renderers on child objects keep their own materials.

PolyBash includes the block prefabs and the roof tile prefabs in the folder Assets/Snowtop/PolyBash/Texture Generation/Prefabs. The section Included block prefabs of the texture generation page describes each set.

PolyBash includes 15 surface variants in the folder Assets/Snowtop/PolyBash/Surface Variants, such as SurfaceVariant-Stone and SurfaceVariant-Wood. The texture definitions in the folder Assets/Snowtop/PolyBash/Texture Definitions and the sample scene use 12 of them. All 15 are a starting point for your own surfaces. The sample scene uses SurfaceVariant-Wood, SurfaceVariant-Wood Black, SurfaceVariant-Wood Dark and SurfaceVariant-Wood White. Nothing uses SurfaceVariant-PathStone, SurfaceVariant-Stone Green or SurfaceVariant-StoneTrim. To create your own surface variant, duplicate one of these assets with Edit → Duplicate, and then edit the duplicate. The original assets stay unchanged, so the texture definitions and the sample scene keep their colors.

These surface variants use two surface textures as their target textures and target normals. The textures are in the folder Assets/Snowtop/PolyBash/Texture Generation/Surface Textures. The folders Stone-01 and Wood-01 each hold a base color map, a normal map, an ambient occlusion map, a height map and a roughness map.

Concepts

  • Source ramp: the palette of the source texture, sampled as a list of colors ordered from dark to light. The asset stores this ramp for you.
  • Target palette: the colors that you want instead. You author two target palettes, Gradient A and Gradient B.
  • Interpolation: the blend between gradient A and gradient B. A value of 0 selects gradient A, and a value of 1 selects gradient B.
  • Lookup texture: a small texture that PolyBash bakes from the source ramp and the two gradients. The capture shaders read it, and the asset stores and updates it for you.
  • Surface transform: the scale, the translation and the rotation that place the patch of the target texture that one block covers.
  • LAB: a color model that measures color differences the way that human vision does. The blend between gradient A and gradient B, the adjustments and the transfer of the texture detail use LAB.

For each pixel, the shader performs these steps:

  1. It measures the brightness of the pixel.
  2. It reads the source ramp at that brightness, which gives the color that the source palette expects.
  3. It reads gradient A and gradient B at that brightness, and then blends them by the interpolation value.
  4. It writes the blended target color, plus the difference between the actual pixel and the expected source color.

Step 4 preserves the texture detail. Grain, cracks and dirt survive the color replacement, because the shader transfers the deviation of each pixel from the source ramp.

Create a surface variant

  1. In the Project window, select the folder that must contain the asset.
  2. Select Assets → Create → Snowtop → PolyBash → Surface Variant.
  3. Name the asset.

The baked lookup texture becomes a child object of this asset. Do not delete it, and do not create it yourself.

Inspector reference

Source

The source section describes the palette of the texture that you recolor.

Field Description
Source Texture The texture whose palette the source ramp describes. Leave it empty for a plain grayscale ramp.
Ramp Resolution (2^n) The number of brightness steps that the ramp stores, as a power of two. A value of 8 gives 256 steps.
Ramp Color Mode Average takes the LAB mean of every pixel in a brightness step. Dominant takes the largest color cluster instead.
Reverse Ramp Reverses the ramp, so that the dark end swaps with the light end.

A color strip below these fields shows the resulting ramp. The strip appears only when Source Texture has a texture. Select Average for a smooth result that matches the overall palette. Select Dominant when two different hues share one brightness level, because Average blends them into a dull color.

The editor samples the ramp again whenever you change the texture, the resolution or the color mode. Sampling stays fast, because the sampler first reduces the texture to 256 pixels on its longest side.

Target

The target section describes the surface that PolyBash renders through this surface variant.

Field Description
Target Texture The albedo texture that blocks render through this surface variant. It also drives the surface variant preview.
Target Normal The normal map of the target texture. Leave it empty for a color-only surface variant.
Normal Strength The strength of the paired normal. A value of 0 is flat, 1 is the authored strength, and a negative value inverts the normal.
Surface Tiling The scale of the surface transform: how much of the target texture one block covers.
Surface Offset The translation of the surface transform, in texture widths.
Surface Rotation The rotation of the surface transform, in degrees, from -180 to 180.

Target Texture is usually the same texture as Source Texture. The fields are separate, so that you can sample the ramp from a small texture and render a larger version of the same texture.

Target Normal must describe the same surface as Target Texture, and not a separate detail pattern. PolyBash samples both textures with the same surface transform, so a crack in the color is also a crack in the normal.

Surface transform

The three surface fields form one transform, which places the patch of the target texture that one block covers. PolyBash applies the scale first, then the rotation, and then the translation. The albedo capture, the normal capture and the surface variant preview all apply the same transform. A texture definition can override the tiling, and never the offset or the rotation.

Surface Tiling sets how much of the texture one block covers. A value of 0.5 means that each block covers a quarter of the texture, so the features look coarse. A value above 1 repeats the texture inside one block.

Surface Offset shifts the sampled patch, so a value of 0.25 on the X axis moves the texture one quarter to the left. During a capture each block also receives a random offset in addition to this value, so that neighboring blocks never show the same patch.

Surface Rotation turns the texture around the center of the patch. The content stays in place, and only the orientation changes.

The inspector shows a warning when the paired normal is inconsistent. Correct each of these conditions:

  • The normal map uses a texture type other than Normal Map.
  • The normal map and the albedo texture have different sizes.
  • Either texture uses a wrap mode other than Repeat. The random per-block offset and any rotation require Repeat, because any other mode smears the edges.

Gradients

Field Description
Gradient A The target palette at interpolation 0.
Gradient B The target palette at interpolation 1.
Reverse Reverses the gradient, so that the color at 0 swaps with the color at 1.
Adjustments Color corrections that PolyBash applies when it bakes the lookup texture.

Author the left end of each gradient as the color of the darkest areas, and the right end as the color of the brightest areas.

Every block selects a random interpolation value between the two gradients, so gradient A and gradient B together define the range of one color family. To disable the variation, author both gradients with the same colors.

Each gradient has its own Adjustments group. The adjustments are not destructive, because PolyBash applies them at bake time and keeps your gradient keys unchanged.

Adjustment Description
Hue Shift Rotates the hue, in degrees, from -180 to 180.
Saturation Scales the color intensity. A value of 0 is grayscale, and 1 is no change.
Brightness Adds to the LAB lightness. The lightness range is 0 to 100.
Contrast Scales the lightness around mid gray. A value of 1 is no change.
Midtones Raises the midtones above 1, and lowers them below 1. The darkest and lightest ends stay unchanged.

Extract From Texture

This section creates a gradient from a reference image, so that you do not author the color keys by hand.

  1. Assign a texture to Source Texture in this section.
  2. Select the number of Buckets, from 8 to 64. A bucket is one brightness step.
  3. Select the Color Mode, which behaves like Ramp Color Mode.
  4. Select → Gradient A or → Gradient B.

The Source Texture field of this section is separate from the Source Texture field of the Source section. The asset does not save this field, so the field starts with the Source Texture of the asset each time that the inspector opens.

The result replaces the target gradient that you select. A Unity gradient accepts at most 8 color keys, so the extractor reduces the buckets to at most 8 keys. It selects the keys that reproduce the palette most closely, and it stops early when fewer keys already reproduce the palette.

Bake

Resolution (2^n) controls the width of the lookup texture, as a power of two. A value of 8 gives 256 pixels, and the label below the slider reports the current size.

The lookup texture holds three rows: the source ramp, gradient A, and gradient B. PolyBash bakes it whenever you change a setting, and it saves the result inside the asset, so no manual bake step exists.

A value of 8 is sufficient for most palettes. Raise the resolution when a gradient contains narrow color bands that the surface variant preview renders as steps.

Preview

The surface variant preview is the image in the Preview section. It renders the target texture through the current settings. When no target texture exists, it uses the source texture, and when neither exists, it uses a grayscale ramp.

The surface variant preview applies the surface transform, so it shows the patch that one block covers. Only the random per-block offset is missing, because the surface variant preview renders no block. The grayscale ramp is an exception, because it is a legend of the gradient rather than a surface.

Field Description
Interpolation The blend between gradient A and gradient B in the surface variant preview.
Detail Preservation How much of the per-pixel detail transfers into the output. A value of 0 gives the pure gradient colors.

Both sliders affect the surface variant preview and the texture that you save. They do not affect a capture, because each block receives a random interpolation value, and a capture always preserves the full detail.

The surface variant preview needs the shader Snowtop/PolyBash/Capture/GradientMap. When Unity cannot find that shader, a warning replaces the surface variant preview.

Save Preview

This section writes the surface variant preview to an image file. The file is a normal texture, so that you can use the result outside PolyBash.

Field Description
Save Location The destination folder, relative to the Assets folder, such as Textures. Leave it empty to save into Assets. Select the folder button to browse.
Texture Name The file name, without an extension. Leave it empty to use the name of the asset.
File Type PNG and TGA keep the alpha channel. JPG is always opaque.
Save Texture Renders the surface variant preview at the full resolution of its texture, and writes the file. That texture is the target texture, or the source texture when no target texture exists.

The saved file contains the same patch that the surface variant preview shows, because both apply the surface transform. To export the whole texture, set Surface Tiling to 1, Surface Offset to 0, and Surface Rotation to 0.

The destination folder must be inside the Assets folder. The field removes a leading Assets/, so Assets/Textures and Textures select the same folder. When you browse to a folder outside Assets, or enter a relative path that leaves Assets, a dialog opens and PolyBash saves nothing.

PolyBash imports the file and then highlights the result in the Project window. Save Texture replaces an existing file with the same name and the same extension, and it does not ask for a confirmation.

Apply a surface variant to a texture definition

Follow these steps to recolor the blocks of a texture definition:

  1. Select the texture definition asset.
  2. Open the Texture Generation foldout in the inspector.
  3. Find the Surface Variants list.
  4. Add one entry for each surface variant that you want to use.
  5. Assign a surface variant asset to each entry.
  6. Select Capture Preview to inspect the result, and Capture to Disk to write the final images.

Each block that the capture renders selects one entry from the list. An entry contains these fields:

Field Description
Surface Variant The surface variant asset for this entry. An entry without an asset is never selected.
Probability The relative likelihood of this entry. Enter any value that is 0 or greater.
Override Surface Tiling Uses the tiling of this entry instead of the tiling of the asset.
Surface Tiling The tiling for this entry, when the override is active.

To edit the surface variant of an entry without leaving the texture definition, select the entry in the list. Then open the Edit Surface Variant foldout below the list. The foldout contains the full inspector of that asset.

PolyBash normalizes the probabilities against each other, so they need not sum to 1. An entry with probability 0 is never selected.

The Random Seed field below the list controls both the entry selection and the interpolation value of every block. The same seed, the same layout and the same list reproduce the same colors. This seed is independent of the Random Seed of the Layout section, so that you can reshuffle the colors although the layout stays unchanged. The random per-block offset follows the Random Seed of the Layout section.

Use Override Surface Tiling when one shared surface must look coarse on a wall and fine on a path. The override avoids a duplicate of the surface variant asset. The override covers only the tiling, so the offset and the rotation always come from the asset.

Behavior per capture type:

  • Albedo and AlbedoLit captures render each block through the surface variant.
  • Normal captures use the Target Normal of the selected asset, with the same surface transform as the albedo. PolyBash combines it with the normal maps of the prefab.
  • Other capture types ignore the surface variant.

An empty surface variant list leaves the materials of the prefab unchanged. A list where no entry is selectable produces a warning in the console.

When the Prefabs list of the Layout section holds no prefab, a capture renders no blocks. It covers the area of the layout with the surface of one entry, which the Random Seed below the list selects. The normal capture uses the Target Normal of that entry, when the asset has one.

When you edit a surface variant asset, PolyBash refreshes the preview of every texture definition that uses it. The texture definition needs a value in its Material field for that refresh.

Apply one surface variant to a generator

To use one surface variant without a capture of block prefabs, add the Surface Variant Applier component to the GameObject of a generator. The component bakes the surface variant into an albedo texture, a normal texture when the surface variant has a Target Normal, and a material. It assigns that material to the fields that you select. The section Surface Variant Applier of the overview page describes the component.

Troubleshooting

Problem Cause and solution
The captured blocks show one flat color. The surface variant has no target texture and no source texture, and the console shows a warning. Assign a Target Texture.
Every block shows the same color. Gradient A and gradient B contain the same colors, or the list contains one entry with one flat gradient. Author a different gradient B.
The colors look dull. Two hues share one brightness level. Set Ramp Color Mode to Dominant.
The result ignores the texture detail. Detail Preservation is below 1 in the surface variant inspector or in the Surface Variant Applier. Set Detail Preservation to 1.
The colors differ from the gradients. The source ramp does not match the texture that the blocks render, so each pixel receives the difference between the source ramp and the texture. Verify that Source Texture is the texture that the blocks render.
The normal map and the color do not match. The paired normal describes a different surface, or its wrap mode is not Repeat. Read the warning in the inspector.
The surface variant preview is unavailable. Unity cannot find the capture shader. Verify that the file Assets/Snowtop/PolyBash/Shaders/CaptureGradientMap.shader exists.
The colors change after a rebuild. The Random Seed below the Surface Variants list changed, or the Layout section or the list changed. Restore the previous values.
The blocks keep the colors of their prefabs. The Surface Variants list is empty, or no entry has an asset and a probability above 0. Read the warning in the console.