GUI: Animated light effect on logo

In the following picture you can see two lines on the logo…

logo

…that should move from left to right to imitate a light effect.

What I’ve achieved so far:

Logo (Parent)

  • Box as child (one line) as stencil mask
    • Logo as grandchild

The problem: If I animate the position.x of the box, the second logo (grandchild) moves also. I could probably reverse the movement by animating the logo’s position.x too but that looks overcomplicated to me. Is there an easy why to achieve that?

1 Like

if parent is a GUI node, you can use stencil mode on it. Remove grandchild.

The problem with your approach is that the child (the box) would be cut off (stencil mask) by the parent’s box not by the parent’s non-transparent area.

It can be done with a shader - here’s an easy example, but with sprite:

I see, if I can make something like this in GUI quickly :wink:

Ok, first version would be something like this:

Zrzut ekranu z 2025-01-14 18-30-10

Fragment program for this is very simple:

varying mediump vec2 var_texcoord0;
varying lowp vec4 var_color;

uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;
uniform mediump vec4 stripe_data; // (x - position, y - width, z - sharpness, w - angle)

void main()
{
    lowp vec4 tex = texture2D(texture_sampler, var_texcoord0.xy);

    // Calculate the distance from the stripe center
    mediump float dist_from_stripe = abs(var_texcoord0.x - stripe_data.x);

    // Compute the stripe intensity with sharpness
    mediump float stripe = 1.0 - smoothstep(
        stripe_data.y * (1.0 - stripe_data.z),  // Start of transition
        stripe_data.y,                          // End of transition
        dist_from_stripe
    );

    // Create the stripe effect as a highlight
    lowp vec4 highlight = vec4(1.0) * stripe;

    // Add stripe highlight to non-transparent pixels
    gl_FragColor = tex * var_color + highlight * tex.w;
}

Adding rotation complicates it a bit, but all you need is rotated_coords addition:

    // Rotate texture coordinates
    mediump float cos_angle = cos(stripe_data.w);
    mediump float sin_angle = sin(stripe_data.w);
    mediump vec2 rotated_coords = vec2(
        var_texcoord0.x * cos_angle - var_texcoord0.y * sin_angle,
        var_texcoord0.x * sin_angle + var_texcoord0.y * cos_angle
    );

And use rotated_coords in dist_from_stripe instead.

You can animate it with gui.set() in a .gui_script:

function init(self)
	self.box_node = gui.get_node("box")
	self.position_x = 0
end

function update(self, dt)
	self.position_x = self.position_x + 0.01
	if self.position_x > 1.5 then self.position_x = -0.5 end
	gui.set(self.box_node, "stripe_data", vmath.vector4(self.position_x, 0.2, 0.2, 0))
end

Effect:

Project (let it be also my entry to Defold Community Challenge :smiley: ):

2 Likes

And I think I made a more complicated solution actually :sweat_smile:

But answering your question - yes, animating the position simultaneously in the other direction is simpler - it’s just one additional line of code in the end! :smiley:

2 Likes

Well, thank you. That’s awesome.

Could I reuse this approach to add that highlight effect to fonts or are fonts handled differently?

I think so, fonts can take custom material too :smiley:

1 Like