2d material with a normal map - sprite shading if defold possible?

Hi, I recently bought sprite illuminator:
www.youtube.com/watch?v=YMTZ_urkVjQ
It allows me to quickly and easily generate a normal map for any sprite/atlas.

Is it possible in defold to give your sprite a material that supports a normal map?
Something that is more than a flat diffuse shader would be awesome to have!

If so - how do you then create 2d lights in the scene that can affect a sprite with a normal map?

Are there any example projects we can study?

4 Likes

I believe that @patsy and @FredrikMalmer played with directional light in Defold at a hack day a while back. Guys, can you share some learnings?

3 Likes

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.

6 Likes

I would really love to implement your suggestion, but my shader scripting knowledge in defold is not advanced enough to push this further to a point where it is functional

Can any of the more advanced users here create a shader that can be used in a project?

1 Like

So, I was trying to recreate such 2.5D lighting on my own, as none of examples on the forum worked for me. The thing I don’t understand is:

It’s elementary to make 2.5D lighting but I can’t get how to create those samplers2D to the sprite in Defold?

You can’t supply extra textures like this to sprites at the moment. AFAIK once the multi texture / material update happens this kind of effect will be very easy to do properly so worth to wait for now.

2 Likes

Ok, so this stuff won’t work for now :confused: I wasn’t sure about it, but I had in mind this multitexture feature, so it should be obvious. So I should better try to understand your example in DefFX, I’ll probably get there with questions :wink:

Tilemap version works but it still has problems since we don’t get everything we need to handle rotation properly if I remember right. That too will hopefully be solved in the future.

IMO if you want to add some lighting you should put your energy into a post processing render target lighting method maybe with some edge detection and wait for whenever we will get the features we need to use different texture maps on sprites.

1 Like

Got some more info about this in the Q&A section of the 2022 Defold Con:

“Better texture support like normals should be in the roadmap.”

Here’s the Github link to follow the progress:
https://github.com/defold/defold/issues/3233

9 Likes

Would love to hear, if passing second texture to sprites materials will be possible! :wink:

1 Like