Decals — stickers in 3D
The Decal node for bullet holes, graffiti, dirt masks, footprints, and other overlays on geometry.
Decal is a node in Godot that projects a texture onto the surfaces beneath it. It’s the classic technique for:
- Bullet holes on a wall
- Dirt on the floor, puddles
- Graffiti, posters
- Tire tracks
- Cracks, blood, scorch marks from explosions
It is implemented as a separate render pass and does not sit on the geometry — so you can “stick” it onto any surface without modifying meshes.
CSS mix-blend-mode: multiply or Canvas globalCompositeOperation = 'multiply' over a
background. In 3D, browsers have no equivalent — this is specific to real-time graphics.
Basic usage
- Add a Decal node to the scene.
- In the Inspector, set
texture_albedo— the main texture. - (Optional)
texture_normal— a normal map for relief. - (Optional)
texture_orm— an Occlusion/Roughness/Metallic mask. - Rotate and scale the node: the decal’s bounding box determines which area it projects onto.
cull_mask— a filter by visual layers (only certain objects receive the decal).
World3D
├── Floor (StaticBody3D + MeshInstance3D)
└── BulletHole (Decal)
texture_albedo: bullet_hole.png (RGBA)
size: (0.3, 0.3, 0.3) # 30×30 cm area
rotation: looking at -Y (down — onto the floor)
Programmatic spawn
extends Node
@export var decal_scene: PackedScene # a Decal as a PackedScene
@export var lifetime: float = 30.0
func spawn_bullet_hole(at: Vector3, normal: Vector3) -> void:
var decal := decal_scene.instantiate() as Decal
add_child(decal)
decal.global_position = at + normal * 0.01 # slightly above the surface
# Orient the decal so it looks "down" (along -Y) onto the normal
decal.look_at(at - normal, Vector3.UP if abs(normal.y) < 0.9 else Vector3.BACK)
# A little rotation randomization for a natural look
decal.rotate_object_local(Vector3.UP, randf() * TAU)
# Remove after lifetime — the typical approach for a "fading out" effect
var tween := create_tween()
tween.tween_interval(lifetime * 0.7)
tween.tween_property(decal, "albedo_mix", 0.0, lifetime * 0.3)
tween.tween_callback(decal.queue_free)
albedo_mix is a float 0..1 that controls the decal’s “strength”. Animate it to 0 → the decal fades out smoothly.
Decal parameters
size: Vector3— the projection’s bounding box (X×Y across the surface, Z — the projection depth).texture_albedo+albedo_mix— the color texture and its strength.texture_normal+normal_fade— the normal map and how strongly it’s applied.texture_orm— combined Occlusion/Roughness/Metallic.texture_emission+emission_energy— self-illuminating decals (lights, screens).modulate: Color— an overall multiply color (for recoloring without replacing the texture).upper_fade/lower_fade— fade at the corners of the bounding box.distance_fade_*— fade with distance (for optimization; distant decals disappear).cull_mask— a bitmask of visual layers; the decal is visible only on those layers.
In scenes with active gunfire, hundreds of decals accumulate. Without distance_fade_enabled = true
- sensible
begin/lengthvalues, the renderer processes them all. With fade, distant ones smoothly become transparent and are skipped, leaving only the ~30-50 nearest ones visible.
Rendering requirements
- Forward+ or the Mobile renderer. On Compatibility (WebGL), decals work, but in a reduced form and through emulation.
- A Decal does not write to the depth buffer — it sits on top of the pixel. This means: it is not visible around a corner or through walls, and sorting with transparent objects can be tricky.
When a decal is NOT the choice
- Large, precise markings on the floor (for example, lane markings for a render-to-map) — it may be cheaper to bake them into the floor texture or a second UV layer.
- Geometry that should affect physics (a bulge, a figurine) — a Decal is purely visual; it does not change the collision shape.
- Animated decals — they are supported (a sprite sheet via a UV shift in
texture_albedo), but through a ShaderMaterial; the standard Decal node has no animation in the Inspector.
Comparison with Unity
Unity has an equivalent: the Decal Projector in URP (com.unity.render-pipelines.universal/Decals).
The concept and API are almost 1-to-1: also a projector, texture_albedo, distance fade, cull mask. The
differences are in performance details: the Unity URP Decal Projector is usually more expensive than a Godot Decal in Forward+.