如何在OpenGL图像查看器中跟踪“高亮”部分

6

我试图找到一种方法来为我的OpenGL图像查看器实现“高亮”功能。想法是让用户能够点击图像以突出显示一个区域,这方面进展顺利。我面临的问题是当用户第二次点击时。我希望保持两个高亮渲染在图像上它们被放置的位置。目前,当第二次点击到达时,第一个高亮消失了。

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

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上跟踪图像中每个像素的状态。我认为我可以通过创建一个与图像完全相同大小的位图(或者可能是表示每个像素的2D布尔数组)来实现这一点,并跟踪哪个片段被“突出显示”。然后,将整个数组作为统一块传递,并将每个v_TexCoordinate与数组中相应的值进行比较。我也不喜欢这个想法(虽然比#1好),因为它再次需要每帧将大量数据移动到GPU。这对于旧的Android设备来说很容易成为非起始器。
  3. 我发现了这个类似问题的答案here。提问者想要操纵纹理数据,而答案建议使用“Render-To-Texture”方法,其中使用FBO。我有点明白这个想法,但我真的看不出这将如何解决记住先前“高亮显示”的问题。也许我很傻,错过了这个答案可以告诉我的东西,但是... ¯\_(ツ)_/¯

我希望有更好的方法,但目前想不出来,希望有人能指点一下方向。


1
不相关,但你可能应该将距离检查从 sqrt( abs( a * a + b * b ) < d 更改为 abs( a * a + b * b ) < d * d,因为这样可以提高性能,避免使用 sqrt。不过驱动程序可能已经进行了优化。如果可以的话,尽量避免条件语句。 - Reaper
1个回答

2
如果您的高光效果只是简单的加法混合,那么请创建第二个纹理,并将高光区域渲染到其中。然后使用加法混合将其渲染在底层图层上方。这样做可能比尝试在GLSL中创建高光区域数据库要容易得多。"最初的回答"

花了我几个星期的时间才让它正常工作,但这个解决方案最终证明是正确的。谢谢! - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接