Coding a bitmap to flash briefly

Hi all. @yojimbo and @ignatz I’m getting my head around shaders thanks to both of your hard work. I’ll let you know how I get on.

As I have two types of images, statics done as sprites and then animations done using the mesh anim technique If I get the shader working well I’ll use that on both.

For my sprite only objects it would be easy to create a white sprite as @TheSoldierKing said too, but as I have a lot of sprite sheets for ships and aliens it’s a lot harder as I’ll have to code a lot of different options. For example the main ship tilts left and right so to have a flash frame for each of those is a pain. Better to flash the sprite,

@stevon8tor Ill give that a go first and see how it works. I don’t think I’ll be able to use that with the mesh code but I can try :wink:

Thanks all your help is very much appreciated!

@Majormorgan actually you could, if you draw the mesh onto an image, then use that code, then use the new ‘white’ image to create another mesh or just keep it as an image, but idk how well it’d fit your code/purpose,xd

@Majormorgan hope you don’t mind me reviving your thread one month on.

I’ve been working on a retro platformer that uses mesh sheets with lots of rects on them, and I was again returning to this problem of how to make an individual rect flash, without making the whole mesh flash, and without having to extend the sprite sheet with white versions of each image in the sheet. I think I have a simple solution! It’s a shader which just multiplies the colour value by 4. So unless the sprite is very dark, if you set the rect colour to 255, this will boost the brightness so much that all the colours clip at 255, and the rect will display as white. To show the rect with its normal colours, set the rects colour to a quarter of what it normally is:

Enemy1.mesh.shader=blowOut
Enemy1.mesh:setRectColor(self.rectN, color(64)) --rect displays normally
...
Enemy1.mesh:setRectColor(self.rectN, color(255)) --rect displays white
...
function shaders() 
    blowOut=shader(
    [[
    uniform mat4 modelViewProjection;
    
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texCoord;
    
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    
    void main()
    {
        vColor = color;
        vTexCoord = texCoord;
        
        gl_Position = modelViewProjection * position;
    }
    ]],
    [[
    precision highp float;
    
    uniform lowp sampler2D texture;
    
    varying mediump vec4 vColor; //has to be mediump to handle *4 conversion
    varying highp vec2 vTexCoord;
    
    void main()
    {
        lowp vec4 col = clamp(texture2D( texture, vTexCoord ) * vColor, 0.0, 0.25) * 4.; //multiply colours by 4 to blow out the whites
    
        gl_FragColor = col;
    }
    ]]
    )
end

I called the shader blowOut, because in photography, if you clip the whites like this, it’s called blowing out the image (edit: added clamp).

hey @yojimbo2000 that sounds ace.

I’ll give it a go as I’m currently swapping out one full colour sheet for each object for an exact same object sheet filled in white.

thank you for persevering!

@yojimbo2000 - a couple of suggestions for your shader.

There’s no need to clamp the results, OpenGL does that for you. Also, previous testing has shown that minimising variables is good (not that matters when you only have one, but still…)

So this will work fine

gl_FragColor =  = texture2D( texture, vTexCoord ) * vColor * 4.; 

However, it’s a bit awkward having to scale all your colours down by 4. Why not set them normally, then have a variable that tells the shader when to use white. This should do it (untested)

Enemy1.mesh.shader=blowOut
Enemy1.mesh.shader.flash=false --rect displays normally
...
Enemy1.mesh.shader.flash=true --rect displays white

--fragment shader --

precision highp float;

uniform lowp sampler2D texture;
uniform bool flash;

varying mediump vec4 vColor; 
varying highp vec2 vTexCoord;

    void main()
    {
        if (flash) gl_FragColor = vec4(1.,1.,1.,1.);
        else gl_FragColor = texture2D( texture, vTexCoord ) * vColor;
    }

Having a shader flag wouldn’t work, because this is for lots of objects (rects) on one mesh, and I only want one rect to flash, not the whole mesh. Good point about the clamping though. If I have time later I’ll post a video.

What about something like this?

Enemy1.mesh.shader=blowOut
Enemy1.mesh.shader.flash=false --rect displays normally
...
Enemy1.mesh.shader.flash=true --rect displays white

--fragment shader --

precision highp float;

uniform lowp sampler2D texture;

varying mediump vec4 vColor; 
varying highp vec2 vTexCoord;

    void main()
    {
        lowp vec4 col = texture2D( texture, vTexCoord );
        if (vColor.r == 1.0) gl_FragColor = vec4(1.,1.,1.,col.a);
        else gl_FragColor = col * vColor;
    }

Just set the color of the mesh to solid white and it’ll be solid white. Any other color, even 254, will make it appear normally.

My method also gives you the option of animating a transition to and from solid white. The animation is quite quick, so maybe hard to see at 30 FPS, but the dudes below go straight to solid white before fading back to their prior colour. The hero and the enemies are all on the same mesh.

https://youtu.be/0EbJBClJISQ