如何在 OpenGL 图像查看器中跟踪 'highlights'

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

我想找出一种方法来为我的 OpenGL 图像查看器实现 'highlighting' 功能。我的想法是,我希望用户能够点击图像来突出显示一个区域,目前为止进展顺利。我面临的问题是用户第二次点击时。我想在放置它们的图像上保留两个高光渲染。在第二次点击到达的那一刻,第一个突出显示消失了。

这是我当前的片段着色器:

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);
    }
}

相当简单,我传入图像、突出显示颜色以及用户点击屏幕的位置的 x 和 y。如果片段在该点的一定距离内,我会添加高光。到目前为止效果很好。

很明显,一旦触摸点移动,原来的高光就消失了。

我的目标是尽可能多地使用此功能 运行 GPU 端。

这是我到目前为止的一些想法,但我希望比我聪明的人能告诉我一个更好的方法来做到这一点。

  1. 我最不喜欢的策略是跟踪 CPU 侧的 XY 接触点并在每一帧传递更新的列表。这里的明显缺陷是触摸列表可以快速获得快速屠宰性能。我希望用户能够根据需要突出显示整个图像,而这个解决方案似乎并不实用。
  2. 在 CPU 上跟踪图像中每个像素的状态。我想我可以通过创建一个位图(或者可能是一个代表每个像素的二维布尔数组)图像的确切大小并跟踪哪个片段是 'highlighted' 来做到这一点。然后,将整个数组作为统一向下传递,并将每个 v_TexCoordinate 与数组中的相应值进行比较。我也不喜欢这个想法(尽管它比 #1 更好),因为它再次需要每帧将大量数据混洗到 GPU。这很容易成为旧 android 设备上的非启动器。
  3. 我看到了这个对类似问题的回答 here。提问者想要操纵纹理数据,答案建议在使用 FBO 的地方使用 'Render-To-Texture' 方法。我有点明白了,但我真的不明白这将如何解决记住以前 'highlights' 的问题。也许我很愚蠢,错过了这个答案可以告诉我的一些东西,但是......¯\_(ツ)_/¯

必须有更好的方法,但我目前一无所获,我希望有人能为我指明正确的方向。

如果您的高光只是简单地叠加,则创建第二个纹理并将高光区域渲染到其中。简单地通过在底层上添加混合来渲染它。尝试在 GLSL 中创建高亮区域数据库可能要容易得多。