The document is the decal system reference. For content creators, it describes how to create decal materials, add decals to a level, manipulate them and control what they affect. For programmers, this page contains an overview of the decal system architecture.
What are decals?
A decal is a type of primitive that projects a material onto surfaces in a scene. Decals specify an oriented volume that is intersected with the scene geometry when the decal is created. All surfaces lying within the decal volume have the decal material projected onto them. Decals in UE3 are unlike projectors in UE2 in that once created, decals are unchanging. In other words, an actor moving between the decal and a receiving surface will not have the decal material projected onto it. True light projector behaviour is achieved in UE3 with LightFunctions (see Lighting Reference). Decals are great for providing variety to a scene, hiding mesh instancing, covering up seams, etc.
"Static" decals are decals that are placed in the level in UnrealEd. The runtime cost of a static decal is roughly the same as a static mesh, except that decals have far fewer polys and do not collide, block, or cast shadows.
"Dynamic" decals are decals spawned during gameplay -- as a weapon hit effect, for example. Decals spawned in game have a one-time creation cost, after which the per-frame cost is the same as a static decal (just the draw call).
Decal Materials are a special type of material that have additional shader code specific to the way decals are lit. Decals can be assigned regular materials, but this will cause the lighting on your decal to be incorrect. Rebuilding a map or checking a map for errors will notify you of decals which have invalid materials.
Material instance chains are supported by decals, but as with simple materials, the decal will only light correctly if the material instances refer to decal materials.
Making the distinction between materials and decal materials is significant for a variety of reasons:
- Decals using transparent materials render differently with respect to fog than other transparent mesh types.
- Decals using lit materials must transform normals computed in the material to the decal tangent frame.
- Shaders that aren't used with decals (e.g. shadows, z-only, velocity, etc) are not compiled for decal materials, meaning that a decal material applied to a non-decal mesh will not correctly e.g. cast shadows, participate in motion blur, etc.
Creating Decal Materials
Like regular materials, Decal Materials are created by right-clicking in the Content Browser and selecting New Decal Material. Select a name for the material and a destination package and press OK. You will see a new decal material object in the Content Browser; double-click on it to open the material editor and configure your material.
Adding decals to the level
The easiest way to add decals to a scene is to select a decal material in the Generic Browser, then hold down 'D' and left click on a surface in the perspective viewport. This will create a decal that projects onto that surface. Alternatively, you can create a decal through the regular right click menu's Add Actor options; however, decals instanced this way will have to be manually oriented.
Sizing, tiling and offsetting
Once the decal is created, it can be positioned and oriented using the translation and rotation widgets.
The non-uniform scaling widget controls the width, height and far-plane distance of the decal volume.
The Decal Material can be tiled and offset (moved) by setting the OffsetX, OffsetY, TileX and TileY properties. These properties are also linked to the non-uniform scaling widget; shift dragging on the non-uniform scaling widget controls the decal material tiling, while ALT dragging controls the offset.
In the image below, a wide tiling decal covers a seam between BSP pieces.
Controlling receiving surfaces
The DecalFilter property category contains a list of properties that can be used to control what surfaces the decal can project onto. Checkboxes are provided for controlling whether the decal can project onto BSP, skeletal meshes, static meshes or terrain.
In the image below, the decal has been set to not project onto BSP, and thus only the portion of decal on the static mesh is visible.
Decals also have Filter and FilterMode properties that allow per-actor control over what the decal can project onto. In the example below, a static mesh has been added to with a FilterMode of FM_Ignore, meaning only that static mesh is ignored by the decal.
See the Decals Technical Guide.
Conflict with mipmaps
Enabling mipmapping on decal textures can produce artifacts around decal edges:
Here is a detailed description of the problem and its workaround:
Decal texture coordinates are computed by projecting the receiving geometry onto the decal image plane.
If receiving geometry is clipped against the decal frustum (the default behaviour), no fill exists outside the decal frustum, and the
value all decal texture coordinates will be in [0,1].
If the decal component is projecting on terrain or has UDecalComponent::bNoClip set to TRUE, then the decal geometry is not clipped to the decal frustum; rather, the original mesh's vertices are used as 'decal vertices'. As compared to the default behaviour, the 'noClip' path results in extra fill, but a cheaper association time as no clipping is performed.
Note that in the 'noClip' approach, vertices that project outside of the decal image plane will have negative-valued texture coordinates, meaning that the address mode of textures used in the decal material need to use clamped texture addressing.
The streaking is because the filtering used to compute the lower-level mips is bleeding non-zero colour to an edge texel, and that texel is being streaked across other fragments because of the clamped addressing on the texture. To fix the streaking, open the texture properties for the textures in the decal material and set the bPreserveBorderR/G/B/A flags on the texture, so that transparent border pixels are preserved on lower mips.
If a placed decal isn't showing up in the editor or in game, check the following:
- The viewport is set to the 'Lit' viewmode (decals don't show up if there's no lighting).
- The decal is in the same level as the receiver (or duplicated into each level in the case of having to project on receivers from multiple levels).
- bAcceptsStaticDecals is TRUE on the receiving mesh components.
- The decal has the appropriate bProjectsOnBSP/StaticMeshes/etc flags set.
- The decal doesn't have anything in it's decal filter.
Decals use a depth bias to avoid z-fighting with the attached geometry, and they don't write to depth to avoid z-fighting with each other. In most cases, z-fighting caused by decals can be solved by tweaking the depth bias. For placed decals the depth bias can be set per-instance. This is usually the best way to go since it won't affect other parts of the game. For dynamically placed decals (blood, bullet marks, etc) tweak the global default. This is the DepthBias property of DecalComponent.uc, set in the DefaultProperties.