【发布时间】:2019-07-15 03:40:03
【问题描述】:
我正在想办法为我的 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 端。
到目前为止,我有一些想法,但我希望比我更聪明的人能告诉我一个更好的方法来做到这一点。
- 我最不喜欢的策略是跟踪 CPU 端的 XY 接触点,并在每一帧传递更新的列表。这里明显的缺陷是,触摸列表可以快速获得大量的快速屠宰性能。我希望用户能够根据需要突出显示整个图像,而这种解决方案似乎并不实用。
- 在 CPU 上跟踪图像中每个像素的状态。我想我可以通过创建一个位图(或者可能是一个代表每个像素的 2D bool 数组)图像的确切大小并跟踪哪个片段被“突出显示”来做到这一点。然后,将整个数组作为统一传递,并将每个 v_TexCoordinate 与数组中的相应值进行比较。我也不喜欢这个想法(尽管它比 #1 更好),因为它再次需要将大量数据洗牌到 GPU 每一帧。在旧的 Android 设备上,这很容易无法启动。
- 我遇到了here 对类似问题的回答。提问者想要操纵纹理数据,答案建议在使用 FBO 的地方使用“渲染到纹理”方法。我有点明白这个想法,但我真的不明白这将如何解决记住以前的“亮点”的问题。也许我很愚蠢,错过了这个答案可以告诉我的一些东西,但是......¯\_(ツ)_/¯
必须有更好的方法,但我目前是空的,我希望有人能指出我正确的方向。
【问题讨论】:
-
不相关,但您可能应该将距离检查从
sqrt( abs( a * a + b * b ) < d更改为abs( a * a + b * b ) < d * d,因为这样可以提高性能,因为您可以避免使用sqrt。不过,驱动程序可能已经在优化它。如果可以,请避免使用条件语句。