Skip to content

Laigter Alternative — Sprite Normal Maps in the Browser

Laigter is a desktop normal map generator for 2D sprites — paid builds on itch.io, a free GPL-3 build on GitHub — and a common pick among Godot pixel-art developers. The Studio's Texture workspace does the same first job in a browser tab and carries on to the engine. Both were run with default settings on the same CC0 assets and scored against real reference normal maps: Laigter came closer on 3D-rendered sprites, the Studio on tileable bricks and height maps.

Laigter is a free-software desktop app (GPL-3, builds on GitHub, paid builds on itch.io) that generates normal, specular, occlusion and parallax maps for 2D sprites, previews them under several lights and runs headless with --no-gui. Nerulio's Studio Texture workspace makes the normal map in a browser tab and continues into a verified Godot 4 scene or Unity 6 importer. On the same CC0 assets with default settings Laigter was closer on 3D-rendered sprites (18.3° against 20.0°), the Studio on tileable bricks and height maps; the right choice depends on the job.

Drop a sprite, a sprite sheet or a tileable texture (PNG)
Runs in your browser. Files are not uploaded.
Studio Texture workspace: a pixel-art torch cut into 6 frames, lit by a point light with its generated normal map
The real Studio with a CC0 asset (OpenGameArt).
Exports to
  • Godot 4 2D lightsVerified· Godot 4.7.2
  • Unity 6 URP 2DVerified· Unity 6000.5.3f1 (URP 17.5)
  • PNG set + JSONPlain files

What each tool does with a sprite

Both tools guess a height field from the picture and take its slope. Laigter's default builds a dome from the alpha outline, a good start for rounded objects, and adds detail from the colours. Its presets store the settings (and, since release 1.6, the lights); release 1.12.0 lets its app split a sprite sheet by frame count or grid size; 1.13.0 added light animations. Its README lists normal, parallax, specular and occlusion maps and command-line switches for each.

Nerulio's Studio suggests a bevel sized to the sprite (1.5 px for frames up to 128 px, about 0.9 × the typical inscribed radius above that), processes cut frames one by one, and lights the result with Godot 4's 2D formula, so the preview equals Godot's output within 1/255. It adds OpenGL/DirectX detection for maps from elsewhere, a height brush, quantised pixel-art normals and 16-bit height input.

On tileable textures the difference is the border. Laigter's default treats the image edge like a sprite edge and tilts a 3 px band on every side (roll error 63.8 on the bricks); its Tile preset removes that (roll 0, 16.5° from the reference, against the Studio's 14.7° with Wrap).

Lit in Godot 4.7.2 against the reference normals, the sprite gap is small: on the 3D-rendered asteroids Laigter's default was 6.32 levels off and the Studio 6.98. On the hand-painted torch every generator was worse than a flat map (flat 26.6, Studio 36.2, Laigter 51.0), so neither replaces painting stylised normals by hand.

Roll error
Generate, roll the texture by half, generate again, roll back and compare the border band; 0 means the map tiles without a seam.
Mean angle
The average angle between a tool's normals and the real reference normals; lower is closer.
Tile preset
Laigter's preset for repeating textures, which stops the border from being bevelled.

What it does

  • The bevel suggestion scales with the sprite: 1.5 px for pixel art up to 128 px, about 0.9 × the typical inscribed radius for larger art. The asteroid comparison with Laigter is what led to that rule (a fixed 4 px bevel scored 36.6°).
  • Pictures without transparent pixels get Wrap suggested, so a repeating texture has no lit band at its border (roll error 0 on the bricks).
  • Frames cut in the Sprite workspace are processed one by one with the same pixel parameters, so an animation keeps one relief and nothing bleeds between frames.
  • The export is a lit Godot scene (Sprite2D, CanvasTexture, a PointLight2D per light) and a Unity 6 URP 2D importer, both checked in the engines — not only a PNG.

Nerulio Studio and Laigter on the same assets

Mean angle to a real reference normal map, lower is better. Laigter 1.14.0 ran through its command line with defaults; the Studio with the parameters it suggests on opening. Neither was tuned per asset.

Nerulio StudioLaigter 1.14
Asteroids (normals rendered from 3D models)20.0°18.3° — the closest of the four tools tested
Hand-painted pixel torch38.1°41.6° (every generator was 37–42° off)
Tileable bricks from the colour image14.7°, roll error 027.3°, seam 24.0, roll error 63.8; with its Tile preset 16.5°, roll 0
Bricks from the 8-bit height map8.8° (7.7° read as a height map)29.8°; Tile preset 26.0°
Where it runsBrowser tab, free, files stay on your machineDesktop; paid on itch.io, free GPL-3 build on GitHub
Lit scene in GodotExport → open _lit.tscn (verified in Godot 4.7.2)Set up the CanvasTexture and lights yourself
Unity 6 URP 2DImporter and Light2D preview (verified in Unity 6)Set up by hand
A sprite sheetEach frame processed on its ownIts app splits a sheet by frame count or grid size (release 1.12.0); per-frame edges not measured, and its command line treats a sheet as one image
OpenGL or DirectX in an opened mapDetected with a confidence, applied only when you confirmNot offered

Source of these numbers: docs/STUDIO-TEXTURE.md (Head-to-head, 2026-09-24)

Where Laigter is the better choice

  • On sprites with a real 3D shape its default was the closest to the truth: 18.3° against the Studio's 20.0° on the asteroids. Its default dome bevel is a good start.
  • Presets, plus its own lit preview with several lights inside the app.
  • Batches from the command line (--no-gui), which fits a build that regenerates maps for whole folders.
  • A desktop program with its source under GPL-3, usable without any website.

How to do it

  1. Drop the sprite on this page (for a whole sheet, cut it in the Sprite workspace first); the Texture workspace draws a normal map straight away.
  2. Compare the suggested bevel with your art in the Normal map panel and change width or profile, or paint relief with the Height brush (B in Texture).
  3. Place lights with the Lights tool (L) and switch between Normal and Lit, or split the view with Compare (C).
  4. Export (Ctrl+E) and open the _lit.tscn in Godot, or run the importer in Unity.

Other ways to do it

OptionWhen it is the better choice
LaigterBatch generation in a build script (--no-gui), parallax and occlusion maps, light animations, a desktop app with no browser, and 3D-rendered sprites, where its default dome came closest (18.3°).
Nerulio Studio TextureA lit Godot 4 scene or Unity 6 URP 2D setup without wiring by hand, tileable textures with Wrap suggested automatically, sheets processed per frame, convention checks for maps from other tools, nothing to install.
SpriteIlluminator (paid, desktop)You want to paint normals: its Angle and Structure brushes and selection tools have no counterpart in the Studio, which has a height brush only.
Bake from 3D, or paint by handRendered sprites (a bake is the truth) or stylised pixel art (no generator matched the artist's torch).

Engine exports and how each was checked

"Verified" means the exported files were loaded by the real engine or tool on real CC0 assets and the result was compared with the source. Anything that was not loaded is labelled as such.

TargetFilesCheck
Godot 4 2D lights_lit.tscn · CanvasTexture .tres · normal / specular PNGVerified Godot 4.7.2Six real CC0 cases rendered by Godot (gl_compatibility): every checked frame within 1/255 of the Studio's lit preview. The same render with green flipped is 3.8–37 levels off, so the check can see a wrong convention.
Unity 6 URP 2DPNG · nerulio-texture.json · Editor/NerulioNormalMapImporter.csVerified Unity 6000.5.3f1 (URP 17.5)12 of 12 runs (6 cases in Gamma and Linear colour space): the lighting URP applied matches the exported normal map (mean error 0.0037–0.0085). URP draws its own light falloff, so brightness is Unity's, not the preview's.
PNG set + JSONalbedo · _n (OpenGL) · _n_dx (DirectX) · 16-bit height · AO · specular · manifestPlain filesPlain files for any engine or tool; no engine run is claimed for them.

Evidence

Godot 4.7.2 rendered 6 real CC0 cases (pixel art, an HD sprite, a tileable texture, an imported DirectX map): every checked frame within 1/255 of the Studio's preview. Unity 6000.5 URP 2D: 12 of 12 runs pass (6 cases × Gamma and Linear). OpenGL/DirectX detection on real maps of known convention: 128 full 1K maps 100 % right, and not one wrong "high" verdict in 1,562 samples (a naive "green-high means OpenGL" rule gets 46 %).

Limits

  • No command line or batch mode: the Studio processes one picture at a time in the browser.
  • No parallax map, and the specular map is exported for Godot only.
  • No light animation; lights are static in the preview and the export.
  • On the 3D-rendered asteroids Laigter's default was 1.7° closer to the true normals.
  • Checked in Chromium only; Firefox and WebKit were not run.
  • On a picture without transparent edges (a tileable texture) a flipped red channel cannot be told apart from a DirectX green; the Check panel says so and offers Flip red.
  • A sheet is lit as one picture until its frames are cut in the Sprite workspace; the Texture workspace does not cut frames.
  • The rim light is preview only, and Unity gets no specular map (Godot does).
  • Unity draws its own light falloff: the exported normal map is verified in Unity, the brightness curve is Unity's.

Versions and sources

Laigter 1.14.0 (the Windows build from GitHub, run through --no-gui with its default and its Tile preset) and Nerulio were measured on 2026-09-24 against real reference normals; the Godot-lit comparison ran in Godot 4.7.2 on 2026-09-25. Neither side was tuned per asset. Laigter's features above are taken from its README and release notes.

Official documentation used

Questions

Is there an online version of Laigter?

Laigter itself is a desktop program. If you want to stay in the browser, the Texture workspace generates the map in the tab without uploading the picture; the table shows where each tool came out closer.

Why did Laigter's brick map show a band at the border?

Its default treats the image border as a sprite edge and tilts a 3 px band on every side (roll error 63.8). Its Tile preset fixes that (roll 0). The Studio suggests Wrap for pictures without transparency.

Can I bring a normal map I already made in Laigter?

Yes. Open it with the sprite and choose it as the source. The Check panel reads its convention — on Laigter's outputs in this test it said OpenGL, high — and the lit preview and exports then use it.

Is it free, and do I need an account?

Everything on these pages is free and works without an account. There is no watermark and no export that is held back.

Are my sprites uploaded?

No. The Studio decodes, packs and exports in this browser tab. Projects are autosaved in the browser (IndexedDB) and can be saved as a .nerulio file.

Does it need Aseprite or an engine plugin installed?

No. .aseprite files are read and written in the browser, and each engine bundle carries what that engine needs (for Godot, the import settings and scene; for Unity and the Godot TileSet, a small editor script).