How to properly run normal maps on animated sprites?

Dear friends,

I just started working with shaders on Solar2D.
I’m trying to run a normal map over animated sprites, but I’m not figuring out how to do that.

For example, the following code works for showing a “static” image with its normal map:

local multiTexture =
{
    type = "composite",
    paint1 = {type="image", filename="MyTexture.png"},
    paint2 = {type="image", filename="MyNormalMap.png"}
}
local rect = display.newRect(0, 0, 256, 256)
rect.fill = multiTexture
rect.fill.effect = "composite.normalMapWith1PointLight"
rect.fill.effect.pointLightColor = {1, 1, 1, 1}
rect.fill.effect.ambientLightIntensity = 0.2
rect.fill.effect.attenuationFactors = {0.5, 1, 1}
rect.fill.effect.pointLightPos = {0.5, 0.5, 0.2}

But how should I procede if the rect were a sprite created by display.newSprite?

local boySheet = graphics.newImageSheet("BoyRunning.png", {width = 153, height = 153, numFrames = 10})
local boySheetNormalMap = graphics.newImageSheet("BoyRunningNormalMap.png", {width = 153, height = 153, numFrames = 10})

local paintBoy = {type = "image", sheet = boySheet}
local paintBoyNormalMap = {type = "image", sheet = boySheetNormalMap}

local multiTextureSprite =
{
    type = "composite",
    paint1 = paintBoy,
    paint2 = paintBoyNormalMap 
}

local boySprite = display.newSprite(boySheet, {start = 1, count = 10, time = 500})
boySprite.fill.effect = "composite.normalMapWith1PointLight"
boySprite.fill.effect.pointLightColor = {1, 1, 1, 1}
boySprite.fill.effect.ambientLightIntensity = 0.2
boySprite.fill.effect.attenuationFactors = {0.5, 1, 1}
boySprite.fill.effect.pointLightPos = {0.5, 0.5, 0.2}
boySprite:play()

Of course the code above doesn’t work, but it helps to clarify what I mean.

Any help?

Thanks in advance!

This is high on my wishlist! Currently, composite paint only accepts image files for its paint parameters. There are potential workarounds but the approaches I have tried have been computationally expensive. Now that Solar2D is open source, I’m hoping to hire someone to add that functionality to the codebase someday (my C++ skills are not up to that task yet).

FYI - This was a limiting factor in my marketplace shader

A possible solution would be to use Spine for animation so you reuse the same objects instead of using a spritesheet

Thanks for replying, sporkfin.

It’s good to know that I’m not the only one who want that feature :slight_smile:

For the project I’m working on, I just have a few animated sprites. So I was thinking of splitting their sprite sheets into single image files and creating my own sprite animation system to be able to use normal map. I know this would cause a drop in performance, but maybe it wouldn’t be so impacting for my case.

Btw, your Dynamic Shader is a very nice tool!

Thanks! Theoretically, you should be able to adjust the fill.x and fill.y and use the full sprite sheet and its normal map.

I guess the big question is whether or not you will be shading in real time or just using the normal maps for depth.

1 Like