Hi, so I’ve been wanting to make a bit of a 2d lighting system with normal mapping. I’ve read a lot of the forum posts and existing workarounds and that we need multi texture support for sprites, which is being worked on.
I also have been learning more about shaders. I found this shadertoy example that seems really nice: https://www.shadertoy.com/view/lstyDr. It seems to do the normalization as part of its code, so only one sampler is needed still, so I thought I’d see if I could make it work as the sprite shader.
So I copied the sprite vertex/fragment shader programs and made a new material and tried to translate it. It just kind of renders a single color for the most part though. Here is what I have:
varying mediump vec2 var_texcoord0;
uniform lowp vec4 mousepos;
uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;
#define fac 1.
const int numLights = 2;
vec3 esnm2(in vec2 uv, in vec2 t)
{
return normalize(vec3(
texture(texture_sampler, vec2(uv.x + t.x*fac, uv.y)).x - texture(texture_sampler, vec2(uv.x - t.x*fac, uv.y)).x,
texture(texture_sampler, vec2(uv.x, uv.y + t.y*fac)).x - texture(texture_sampler, vec2(uv.x, uv.y - t.y*fac)).x,
1
));
}
struct material {
vec3 ambient, diffuse, specular;
float shininess;
};
struct light {
vec3 o, ambient, diffuse;
float power;
};
vec3 shade(in vec3 p, in material m0, in vec3 N, in light[numLights] l) {
vec3 ambient = m0.ambient;
vec3 diffuse = m0.diffuse;
for(int i=0; i<numLights; ++i)
{
ambient += l[i].ambient;
float d = distance(l[i].o, p);
vec3 ldir = p-l[i].o;
vec3 L = normalize(ldir);
float NdotL = dot(N,L);
diffuse += NdotL*l[i].diffuse*l[i].power/d;
}
return (ambient+diffuse)/float(numLights);
}
void main()
{
vec2 res = vec2(1.92, 1.08); // <3>
vec2 uv = var_texcoord0.xy/res.xy;
float aspect = res.y/res.x;
vec2 p = uv*2.-1.;
uv.y*=aspect;
p.y*=aspect;
vec2 mouse = mousepos.xy/res.xy;
vec2 mousep = mouse*2.-1.;
mousep.y *= aspect;
light[numLights] l;
l[0] = light(vec3(mousep, -.02), vec3(.075, .056, 0), vec3(.5, .34, 0), .2);
l[1] = light(vec3(mousep+0.3, -.02), vec3(.075, .056, 0), vec3(.3, .34, 0), .6);
material m0 = material(vec3(.056), vec3(.1, .089, .08), vec3(.56, .54, .34), 10.0);
vec3 N = esnm2(uv, 1./res.xy);
vec3 col = shade(vec3(p,0), m0, N, l);
gl_FragColor = vec4(col,1);
}
I added a vec4 variable to the fragment shader in the material for mousepos and update it with a script which does not seem to work at all. (the script works, I can put a print there to see mouse pos move around but it does not change the shader at all.)
function init(self)
msg.post(".", "acquire_input_focus")
end
function on_input(self, action_id, action)
if action.x and action.y then
sprite.set_constant("#sprite", "mousepos", vmath.vector4(action.x, action.y, 1, 1))
end
end
I am pretty new to all this. Any help converting this shadertoy to defold would be awesome! Thanks.