Skip to content

Decal Projection

Chris A edited this page Oct 1, 2026 · 1 revision
Graphics3D 800, 600
SetBuffer BackBuffer()

camera = CreateCamera()
PositionEntity camera, 0, 0, -6

cube = CreateCube()

tex = LoadTexture("bullseye.png")

decal = CreateDecal(tex)
PositionEntity decal, 0, 0, -0.75
ScaleEntity decal, 2, 2, 1
ProjectDecal decal, cube

While Not KeyHit(1)
	UpdateWorld
	RenderWorld
	Flip
Wend

End

CreateDecal

Decal = CreateDecal([texture] [, parent])

Creates an empty decal entity with a transparent brush carrying texture (optional). Its position, rotation and scale define the projection box used by ProjectDecal. It has no geometry until something is projected into it, and returns 0 if parent is invalid

ProjectDecal

ProjectDecal decal, source

Bakes mesh geometry into decal. source can be any mesh entity, and every mesh in its hierarchy (children, and their children) is projected. The projection box is the decal's current world transform: position is the center of the box, rotation orients it, and scale is its size (width, height, depth). The texture projects along the decal's local +z, and only triangles inside the box are kept. Calling it again with another source puts one decal across several separate meshes

ClearDecal

ClearDecal decal

Removes all projected geometry, leaving the entity and its texture in place so it can be projected again. Useful for reusing a pool of decals


The projection is flat, not a UV wrap. Surfaces facing the decal's +z show the texture correctly, surfaces at an angle (the sides of a cube) are stretched, and back faces are projected too, mirrored, unless the box is shallow enough that they fall outside it

Set the decal's position, rotation and scale before calling ProjectDecal, moving it afterwards leaves the geometry baked off the surface. Geometry is stored in the decal's local space, so parenting the decal to the source (EntityParent decal, source, 1) makes it follow a moving mesh. Use an alpha texture for clean edges, the decal draws in the transparent pass so it will not z-fight with the surface underneath. A surface holds at most 65535 vertices, if you manage to crash by going over, BRAVO!

Clone this wiki locally