Role Technical Artist
Timeline 2026
Team Size Solo Project
Tools Unity, C#, Editor Scripting
UnityC#Editor ToolingProcedural Mesh GenerationImage ProcessingTechnical ArtOpen Source

Overview

Screenshot of the tool editor window in Unity.
Image Relief editor: source image on left, displaced 3D panel in the live preview on the right

Image Relief is a Unity editor tool that turns any image into a physical-feeling bas-relief panel — a flat slab where brighter pixels rise and darker pixels recede. Drop in a source image, adjust how brightness maps to height, and the tool builds a displaced mesh grid and a Sobel-derived normal map in real time. When the result looks right, a single button exports the mesh, material, and prefab ready to drop into a scene.

The use case is props that should read as carved, cast, or stamped, like stone inscriptions, metal emblems, decorative panels, architectural ornament, where the shape comes from an image rather than hand-modeled geometry.

The tool grew directly out of the normal-map baking step in Profile Lathe, generalized from procedural flute patterns to arbitrary image input.

Design decisions

Three height-mask modes

The core question is how pixel brightness becomes mesh height, and the answer depends on the source image. A greyscale gradient photograph needs a different mapping than a flat logo with a white shape on black. The tool exposes three modes rather than one: Luminance maps brightness directly to height (smooth, good for photographic sources); Threshold produces a hard binary raised/not-raised shape with a softness falloff (good for logos and silhouettes); Hybrid uses the threshold to define the shape while letting internal luminance add surface detail within it. Choosing the right mode for the source material is the main authoring decision.

Three mask-mode previews side by side: Luminance, Threshold, and Hybrid on the same source image

Seeing the height field before it becomes geometry

The left panel shows a live greyscale preview of the height field as a flat 2D image. The mapping from source pixels to height (especially with blur, inversion, and softness in play) isn’t always obvious from the controls alone. Seeing the mask directly tells you what the mesh will be before it’s built, and makes tuning Threshold softness or Hybrid internal detail a visual operation rather than a guessing game.

Live 3D preview of a fingerprint relief panel orbited to a side angle showing both displaced silhouette and normal-map surface detail

Throttled normal baking

The mesh rebuilds on every control change so the geometry always reflects the current settings. Normal map baking is deferred to mouse-up: Sobel-filtering a full-resolution height field on every slider tick would stall the editor, but the preview stays useful during a drag — correct geometry, slightly outdated lighting. Baking on release keeps the interaction responsive without hiding the result.

A panel with a base slab.

Optional base slab

By default the tool produces a single displaced surface — enough for a panel mounted flush to a wall. Enabling the base slab adds a flat back face and a perimeter skirt, making the result a closed solid that looks physically grounded from any viewing angle. The skirt uses the border vertex positions from the front face, so the depth of the displacement is always reflected in the side profile.

How the pipeline works

The source image is read into a per-pixel luminance array, run through an optional separable box blur to soften high-frequency noise, then mapped to a normalized [0, 1] height field by the selected mode. Threshold and Hybrid both use a smooth-step falloff around the cutoff so the transition between raised and flat is tunable rather than aliased.

The height field drives two outputs in parallel. The mesh bilinearly samples the field at each grid vertex and displaces it along +Z by height × heightScale. The longer image axis maps to the configured resolution in cells; the shorter axis scales proportionally so the mesh always matches the source image’s aspect ratio. The normal map runs a 3×3 Sobel kernel over the height field, reconstructs the surface gradient at each texel, and packs the result into a tangent-space normal texture. The strength control scales the gradient before normalization, giving independent control over how contrast-y the lighting reads relative to how far the geometry actually moves.

Three panels of the same relief: 350k triangles without a normal map, 10k triangles without one with visibly smeared detail, and 10k triangles with the baked normal map nearly matching the 350k version

The geometry only needs to carry the silhouette and large forms; the normal map restores the fine ridges the lower-resolution grid drops. The comparison above makes the case: a 10k-triangle panel with the baked map reads almost identically to a 350k-triangle panel without one, at a fraction of the cost.

One-click readability fix

Unity textures are not CPU-readable by default, which would silently block pixel access. Rather than failing or surfacing a raw error, the tool detects the import setting at load time and shows a warning with a “Make Readable” button that reimports the texture with the flag enabled. It’s a minor UX detail, but removing that friction point is the difference between a tool that teaches you its error messages and one that gets out of the way.

Reflections & Growth

What I learned

Image Relief pushed the image-processing side of technical art work — reading pixels, building separable blur passes, and wiring Sobel gradients into normal encoding. Deciding where to draw the line between the height mask (the 2D representation) and the mesh and normal map (the 3D outputs) ended up being the main architectural question, and keeping those as distinct stages made it straightforward to preview the mask independently before committing to a rebuild.

Alignment with my goals as a technical artist

Relief panels and surface detail are a recurring prop-art problem in games, and a tool that solves it from a 2D source image — something artists already have — is a direct productivity gain. The connection back to Profile Lathe reinforced the value of extracting reusable subsystems: the normal-baking code is genuinely shared, not copy-pasted.

← Back to Tech Art