Light demo
This demo shows how you can enhance a 2d sprite with normal maps to create real time light effects.
Move your mouse over the demo to change the light position.
Prerequisites
You already have normal maps for your sprites.
To learn how to create normal maps have a look at this tutorial. For more details about the SpriteIlluminator tool visit its documentation page.
Sprite sheets require a corresponding normal map sheet
The sprite sheet containing the normal maps must be packed with the same layout as the sheet containing the sprite images. TexturePacker has a dedicated mode to support this. This tutorial describes normal map packing in detail.
Throw light on your sprite
To load a sprite image together with its normal map, the file names of the
image and its normal map are passed to this.load.image()
as an array. In the
following example the normal maps are marked with a _n
suffix.
After loading the images, the sprite can be placed as usual. To enable dynamic
lighting the corresponding shaders are activated using setPipeline('Light2D')
.
Important: Light effects require a browser with WebGL support.
function preload()
{
this.load.image('character', ['assets/character/01.png', 'assets/character/01_n.png']);
}
function create()
{
var character = this.add.sprite(250, 300, 'character');
character.setPipeline('Light2D');
}
As we haven't added any light source yet, the scene remains black. Add these to lines
to the create()
function to switch on a light:
var light = this.lights.addLight(500, 250, 200);
this.lights.enable().setAmbientColor(0x555555);
This adds a point light at position (500,250) with radius 200. The ambient light increases the brightness of all pixels of the scene, independent of the position of the point light.
How to use sprite sheets with normal maps
For sprite sheets the normal maps must also be packed on a sheet.
TexturePacker automatically stores the file names of the textures in the generated JSON file,
a simple call of load.multiatlas()
loads both and links the normal map sheet to the
sprite image sheet:
function preload()
{
this.load.setPath('assets/');
this.load.multiatlas('character_sheet', 'character.json');
}
Adding sprites and animations works as usual, it's just the
setPipeline('Light2D')
call which is additionally needed to enable lighting:
// add sprite from sheet
var character_anim = this.add.sprite(550, 300, 'character_sheet', '01');
character_anim.setPipeline('Light2D');
// play animation
var frameNames = this.anims.generateFrameNames('character_sheet', { start: 1, end: 8, zeroPad: 2 });
this.anims.create({ key: 'walk', frames: frameNames, frameRate: 10, repeat: -1 });
character_anim.anims.play('walk');
Play around with it
To illuminate the sprites from different directions we attach the light position to the mouse pointer:
this.input.on('pointermove', function (pointer) {
light.x = pointer.x;
light.y = pointer.y;
});
Finally
That's all for this tutorial. You should now have learned how you use normal maps for dynamic lighting and how to use sprite sheets with normal maps.