I don’t have a working concrete example for you, but it should be fairly analogous to the way directional lighting is done in 3d, except with a slight simplification: You don’t need to send normal data down to the gpu as a vertex attribute. Since it’s a sprite, you can always just assume that the geometry normal is (0, 0, 1).
So, if you took the builtin sprite.fp shader:
varying mediump vec4 position;
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D DIFFUSE_TEXTURE;
uniform lowp vec4 tint;
void main()
{
// Pre-multiply alpha since all runtime textures already are
lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
gl_FragColor = texture2D(DIFFUSE_TEXTURE, var_texcoord0.xy) * tint_pm;
}
And modified it to be something a bit more like this (WARNING, totally untested!):
varying mediump vec4 position;
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D DIFFUSE_TEXTURE;
uniform lowp sampler2D NORMAL_TEXTURE;
uniform lowp vec4 tint;
uniform lowp vec4 light_color;
uniform lowp vec4 light_direction;
void main()
{
lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
vec4 diffuse = texture2D(DIFFUSE_TEXTURE, var_texcoord0.xy) * tint_pm;
vec3 norm;
norm.xy = texture2D(NORMAL_TEXTURE, var_texcoord0.xy).rg * 2.0 - 1.0;
norm.z = sqrt(1.0 - dot(norm.xy, norm.xy));
vec3 ambient = vec3(0.2);
vec3 light = light_color.rgb * max(-dot(norm, light_direction.xyz), 0.0) + ambient.rgb;
light = clamp(light, 0.0, 1.0);
gl_FragColor = vec4(diffuse.rgb * light.rgb, diffuse.a);
}
I think that should get you most of the way there. Of course, you’ll have to add the additional uniforms to the .material file, otherwise this fragment program won’t work…
As for creating 2d lights in the scene, you’d probably want to make game objects that represent the lights, and then have your render script take the orientation of the light, convert it to a direction vector, and bind that as the light direction before rendering the scene.