Components / Backgrounds / Brushed Metal
Brushed Metal
A metal panel lit by a light at the pointer, and the highlight streaks across the grain — the tell of real brushed metal. Brushing rocks the facet normals across the grooves, so reflection spreads that way. The shading is the anisotropic GGX microfacet model, with roughness αt along the grain and αb across it, Smith masking and Schlick Fresnel with the metal’s colour as F0. Take anisotropy to zero and the streak collapses to a polished spot. Press and the lamp dips toward the metal — the inverse-square law tightens and brightens the highlight under it; on touch a finger brings the light, and keyboard focus on anything placed on the plate draws it over.
Usage
import BrushedMetal from '@/components/brushed-metal'
<BrushedMetal angle={0} roughness={0.42}>
{content}
</BrushedMetal>Installation
npx shadcn@latest add https://morphiq.prathampatel.design/r/brushed-metal.jsonModel
D(h) = 1 / (π·αt·αb·((h·t/αt)² + (h·b/αb)² + (h·n)²)²)anisotropic GGX · αt along the grain, αb across it
Props
| Property | Type | Default | Description |
|---|---|---|---|
angle | number | 0 | Grain direction, degrees clockwise like CSS rotate. 0 brushes left to right. |
roughness | number | 0.42 | Roughness across the grain, 0..1. Higher spreads the streak further. |
anisotropy | number | 0.88 | How much smoother the metal is along the grain than across it, 0..1. 0 is polished, not brushed. |
grain | number | 1 | Depth of the scratches. 0 is a perfect brushed finish with no visible lines. |
color | string | '#c9cdd3' | The metal's reflectance at normal incidence (F0). Any CSS colour — gold is #ffc86e, copper #f6a882. |
intensity | number | 1 | Brightness of the light, as it is at its resting height. |
height | number | 240 | The light's height above the panel, px. Lower gives a tighter, more raking highlight. |
press | number | 0.3 | How far a press lowers the light, as a share of its height, 0..0.9. Brought closer it lights the metal under it more brightly and draws the streak in. 0 turns it off. |
resolution | number | 1.5 | Device-pixel-ratio cap for the canvas. |
children | ReactNode | — | Content laid on the plate. It stays real DOM above the canvas. |