Sprite outline
Draw a border where a sprite's pixels meet the transparent space around it.
Cards
One live example to tweak, learn and copy.
How it works
A 2D game marks the selected unit, the item you can pick up or the enemy under the cursor with a colored border around the sprite. Drawing that border by hand would mean a second copy of every frame. A shader draws it from the sprite itself.
The idea fits in one sentence: a pixel belongs to the outline if it is transparent and one of its neighbours isn’t. The
shader reads the sprite’s alpha at the pixel and at the texelsOne element of a texture, the texture's version of a pixel. A sample blends nearby texels or returns the nearest one. Texel One element of a texture, the texture's version of a pixel. A sample blends nearby texels or returns the nearest one. Blending Combining the color a fragment shader outputs with the color already in the framebuffer, instead of replacing it. Transparency, additive glow and multiply all come from it.texel size = 1 / textureSize(sampler, 0)result = src × srcFactor + dst × dstFactor
then lays the result over the scene like any sprite.
Two details decide whether it works in a real project. The line grows outward, into space the sprite doesn’t use, so
the image needs empty pixels around its art or the line is cut off at the quad’s edge. And in a
sprite sheet (opens in a new tab)One image that holds many sprites or animation frames side by side. Each sprite reads only its own rectangle, but filtering and neighbour reads near its border can pick up the next frame's pixels. Sprite sheet One image that holds many sprites or animation frames side by side. Each sprite reads only its own rectangle, but filtering and neighbour reads near its border can pick up the next frame's pixels.
Further reading
- step (opens in a new tab)Reference
- smoothstep (opens in a new tab)Reference
- Shaping functions (opens in a new tab)Book
- texture (opens in a new tab)Reference
- texelFetch (opens in a new tab)Reference
- Using textures in WebGL (opens in a new tab)Docs
- Blending (opens in a new tab)Article
- WebGLRenderingContext: blendFunc() method (opens in a new tab)Docs
- Spatial shaders (opens in a new tab)Docs
- textureSize (opens in a new tab)Reference
- CanvasItem shaders (opens in a new tab)Docs
- Texture atlas (opens in a new tab)Reference