SpriteForge.tech
Play the demo Compare Blog Pricing Open the studio

Pixel art normal map generator

Free · no account · runs in your browser, nothing is uploaded

Make your sprites react to 2D lights without hand-painting a normal map for every frame. Add a sprite or a sprite sheet, drag a light across it, and download a normal map for Unity, Godot or GameMaker.

How it guesses the shape: every patch of one colour becomes its own rounded surface, and the whole silhouette gets a soft volume on top. That suits clean pixel art with a limited palette. It can't know that a gem should stand out or that a cape hangs behind the armour, so you can raise or lower any colour yourself.

Choose a sprite, or drop or paste one here. A PNG with a transparent background, up to 2048 × 2048 px; sprite sheets welcome.
Lit preview loading…
Drag to move it
Normal map
Pick a pixel to set its colour's height
Colour heights Each colour sits at a height, lighter colours higher by default. Pick one and raise what should stand out, lower what sits behind. Dashed: the outline, kept at the edge.
No colour pickedPick a colour above, or a pixel on the map.
Normal map Same size and layout as your sprite, so one map covers a whole sheet. Alpha is 255 everywhere and the area around the sprite is flat (128, 128, 255), so engines don't light the transparent edge as a dark rim.

Sprite sheet
× px

Shape
2.4

How strongly each colour region bulges.

1.00×

The soft roundness of the whole silhouette.

1.00×

How far colours step up or down from each other: the ledge a light rakes across.

Format

OpenGL (green up) for Unity, Godot and most engines. DirectX (green down) for engines and shaders that expect it. If light seems to come from below, switch.

Using the normal map in your engine

Unity (URP 2D)

  • Import the normal map with Texture Type: Default, sRGB (Color Texture) off, Filter Mode: Point and Compression: None. Default rather than Normal map: these are plain RGB maps, and the Normal map type re-encodes them.
  • Open the sprite in the Sprite Editor, switch to Secondary Textures, and add one named _NormalMap with the normal map as its texture. A sliced sheet works as is: every sprite picks up its own frame of the map.
  • On each Light 2D that should use it, set Normal Maps → Quality to Fast or Accurate.

Godot 4

  • Create a CanvasTexture, put the sprite in Diffuse → Texture and the normal map in Normal Map → Texture, then use the CanvasTexture as the texture of your Sprite2D (or in an AnimatedSprite2D's frames).
  • Set the node's Texture → Filter to Nearest so the pixels stay hard.
  • Light it with a PointLight2D and give the light some Height; at height 0 only the edges facing it catch light. Godot reads OpenGL maps (green up).

GameMaker

  • GameMaker has no built-in normal-mapped 2D lights, so the map goes to a lighting shader. Import it as its own sprite with the same size and frames, and pass it as a second texture: texture_set_stage(u_normal, sprite_get_texture(spr_hero_normal, image_index)).
  • Both sprites need matching UVs: tick Separate Texture Page on both, or pass the normal sprite's UVs from sprite_get_uvs. Turn off texture interpolation.
  • If your shader lights the sprite from below, download the other format.

Other engines

Defold, LÖVE, Phaser, MonoGame or your own shader: this is a standard tangent-space normal map at the sprite's resolution, decoded as rgb × 2 − 1. Pick OpenGL unless your engine documents DirectX (green down).

How the normal map is made

  1. Colour regions. Every connected patch of one exact colour is a surface: it gets a small dome of its own and sits at a base height, its brightness unless you set one. The step from one colour to the next is the ledge a moving light rakes across, which is what makes a belt, a crown or a cape read as separate parts. The outline colour is found automatically and kept at the edge.
  2. Outline volume. The silhouette as a whole gets a soft, rounded volume, so the sprite turns away from the light at its edges instead of looking like a flat cutout.
  3. Blend. The two are combined (a whiteout blend of the two normals) and saved at the sprite's own resolution, one normal per pixel.

The outline-volume step is a port of Sprite Fusion's open-source sprite-normals (MIT licence, © 2026 Hugo Duprez), used without its shading-to-relief part. Thanks to Sprite Fusion for publishing it. The colour-region step comes from Gacha Dungeon, our own game, where it lights every outfit; the sample is three of them.

Tips

  • Clean, flat colours work best. Every exact colour is a surface, so anti-aliased, painted or scaled art (hundreds of near-identical colours) breaks into tiny regions. Pixel art with a deliberate palette is the ideal input.
  • Raise what stands out, lower what sits behind. A gem, a buckle or a nose up; a cape under armour, the inside of a hood or an eye socket down. A colour keeps its height in every frame of a sheet.
  • Watch it move. Orbit the light and look for parts that light the wrong way round; that's usually one colour at the wrong height.
  • Animations. The outline volume follows each pose. If an idle animation seems to breathe under a still light, lower Outline volume a little.
  • One-pixel details such as a blade or an antenna get almost no volume. At sprite sizes that usually looks right.

Questions

Is my sprite uploaded anywhere?

No. The generator runs entirely in your browser: the file is read on your device and the normal map is computed in a Web Worker. The sprite is never sent to SpriteForge or anyone else. The page counts visits with cookie-free analytics; that never includes your sprite.

Which engines can use the normal map?

Any engine that lights sprites with a tangent-space normal map: Unity's URP 2D lights (as the sprite's _NormalMap secondary texture), Godot 4 (the normal map of a CanvasTexture), GameMaker through a lighting shader, and engines like Defold, LÖVE or Phaser through their own shaders. Download it as OpenGL (green up) for Unity, Godot and most others, or DirectX (green down) for engines and shaders that expect that.

Does it work with sprite sheets and animations?

Yes. Enter the size of one frame and every frame is shaped on its own, so neighbouring frames never bleed into each other, and the map keeps the sheet's exact size and layout. Colour heights apply to every frame, so a colour sits at the same height in the whole animation.

How is this different from a normal map made from brightness?

Many generators read a sprite's brightness as height, so painted highlights turn into bumps and dark outlines into grooves. This one treats every patch of one colour as its own surface, gives the whole silhouette a soft volume, and lets you set how high each colour sits: raise a gem, push a cape behind the armour.

Can I use the normal maps commercially?

SpriteForge claims no rights over the normal maps you make here. A normal map is made from your sprite, so the sprite's rights apply: if you made it or may use it, you can use its normal map too, including in a commercial game.

Free pixel art maker · Image to pixel art · Compare AI pixel-art tools · Blog · Home