Geometry · interface

DecalOptions

A decal, as the receiving surface's own geometry clipped to a box and lifted off it.

Explained in Hello world, Meshes and geometry.

interface DecalOptions
import type { DecalOptions } from '@driftengine/core';

In depth

A forward renderer cannot write a decal cheaply into a G-buffer, because there is no G-buffer, and that is the fact every decal design here has to start from. What a forward renderer can do is the older technique, and it is the better-looking one: take the triangles the projector box covers, clip them to it, and draw that. The decal is then made of the surface, so it follows every curve and every bump exactly, which a projector re-drawing a quad cannot.

What it replaces, in a consumer's own words. Their road patches are strips of geometry lifted two millimetres above the carriageway: it works, it is a draw call per patch for something that exists only to sit on top of something else, and it does not follow a curved surface. Puddles after a storm, oil stains and skid marks were all waiting on the same row. This is one mesh for as many marks as you project into it, and it is the road's own shape.

Built once, not per frame. A decal is authored or placed by an event — a tyre locks, a barrel leaks — and then it is scenery. That is what makes clipping on the CPU the right cost: it happens at the moment the mark is made, and every frame afterwards it is one more mesh in the batch.

Its limits, stated rather than discovered. It is a static decal: the receiving mesh is sampled as it is, so a decal on something that later deforms rides the old shape. It reads positions and normals and nothing else, so the mark takes its own colour rather than tinting what is underneath. And a projector box covering a hundred thousand triangles clips a hundred thousand triangles, so a caller marking a large world hands in the piece of it they mean.

Properties

NameTypeDescription
centerreadonlyVec3Middle of the projector box, world space.
halfExtentsreadonlyVec3Half-size across, up, and along the projection. The third is how deep the box reaches.
forwardreadonlyVec3The direction the decal is projected along — for a mark on the ground, straight down.
More

A surface is marked when it faces back along this. Need not be normalised.

upreadonlyVec3Which way is up in the decal's own image, so a mark can be turned. Need not be normalised.
colorreadonlyoptionalVec3
offsetMreadonlyoptionalnumberHow far the decal is lifted off the surface, metres. Two millimetres by default.
More

Not a depth-bias setting in disguise. The lift is along each vertex's own normal, so it survives a surface that curves away under it where a constant depth offset would not, and it is small enough to be invisible at a metre and large enough to beat a 24-bit depth buffer at fifty.

facingCosreadonlyoptionalnumberHow far from facing the projector a surface may be turned and still be marked, as a cosine.
More

The reason this is not zero: a triangle exactly edge-on to the projector clips to a sliver of zero area that still costs six vertices, and one a hair past edge-on produces a mark stretched along a wall it was never aimed at. 0.1 keeps everything within about 84° of facing.

emissivereadonlyoptionalnumber
specularreadonlyoptionalnumber