Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep track of 'highlights' in OpenGL Image Viewer

I am trying to figure out a way to implement a 'highlighting' feature for my OpenGL image viewer. The idea is that I want the user to be able to tap the image to highlight an area, this has gone well so far. The problem I am facing is when the user taps a second time. I want to keep both highlights rendering over the image where they were placed. At the moment when the second tap arrives, the first highlight disappears.

This is my current fragment shader:

precision mediump float;
uniform vec4 vColor;
varying vec2 v_TexCoordinate;
uniform sampler2D u_Image;
uniform float u_touchX;
uniform float u_touchY;

void main() {

    float radius = 0.1;
    float a = v_TexCoordinate.x - u_touchX;
    float b = v_TexCoordinate.y - u_touchY;
    float d = sqrt(abs(a*a + b*b));

    if(d < radius){
        gl_FragColor = texture2D(u_Image, v_TexCoordinate) + vColor;
    }else{
        gl_FragColor = texture2D(u_Image, v_TexCoordinate);
    }
}

Fairly simple, I pass in the image, highlight color and the x and y of where the user tapped the screen. If the fragment is within a certain distance of that point I add the highlight. Works great thus far.

Obviously though, once that touch point moves the original highlight is gone.

My goal here is to have as much of this feature running GPU side as possible.

Here are a few thoughts I've had so far but I'm hoping that someone more clever than I can show me a better way to do this.

  1. The strategy I like the least would be keep track of XY touch points on the CPU side and pass down the updated list every frame. The obvious flaw here is that the list of touches could get large quickly slaughtering performance quickly. I want the user to be able to highlight the whole image if they want and this solution just doesn't seem practical.
  2. Keep track of the state of each pixel in the image on CPU. I think I could do this by creating a Bitmap (or maybe a 2D bool array representing each pixel) the exact size of the image and keep track of which fragment is 'highlighted'. Then, pass that whole array down as a uniform and compare each v_TexCoordinate with the corresponding value in the array. I don't like this idea either (though its better than #1) because it again would require shuffling a lot of data to the GPU every frame. This could easily be a non starter on old android devices.
  3. I came across this answer here to a similar question. The asker wants to manipulate texture data and the answer suggests using a 'Render-To-Texture' approach where you use FBO's. I kind of get the idea but I don't really see how this would solve the issue of remembering previous 'highlights'. Maybe I'm being daft and missing something that this answer could tell me but... ¯\_(ツ)_/¯

There has to be a better way but I'm currently coming up empty and I'm hoping someone can point me in the right direction.

like image 696
Nick Avatar asked Jul 11 '19 04:07

Nick


1 Answers

If your highlight is simply additive, then create a second texture and render the highlight regions into it. Simply render that with additive blending over the underlying layer. It's probably far easier to do that that trying to create a database of highlight regions in GLSL.

like image 153
robthebloke Avatar answered Nov 15 '22 05:11

robthebloke