glsl像素着色器 - 到最近目标像素的距离

时间:2013-10-15 23:58:37

标签: opengl glsl shader

我有一个2k x 1k的图像,随机放置“目标”像素。这些像素是纯红色的。

在frag / pixel着色器中,对于非红色(目标颜色)的每个像素,我需要找到距最近的红色像素的距离。我将使用此距离值来创建渐变。

我找到了这个答案,这似乎与我的问题最接近--- Finding closest non-black pixel in an image fast --- 但这不是特定的glsl。

我可以选择将红色目标像素作为纹理缓冲区数组发送到frag着色器中。但我认为如果我不需要它会更清洁。

2 个答案:

答案 0 :(得分:3)

着色器无法读取和写入相同的纹理,因为这会对执行序列引入太多约束和复杂性,并且会使缓存变得更加困难。所以你在谈论发送一些关于红色像素的数据并获取距离信息。

碎片着色器并行运行,执行随机访问纹理读取比从着色器外部已知位置读取要昂贵得多,这主要是由于流水线操作的考虑因素。预先编程的情况,其中采样坐标在顶点处已知,然后在几何体的面上进行插值,这仍然是访问纹理的最佳方式。

因此,编写一个着色器,对于每个像素,向外搜索红色像素将是非常低效的。这绝对是可能的,做了很多链接的算法,但可能不是最聪明的方法。

理想情况下,你会用相反的方式表达事物并使用某种积累。所以:

  1. 将输出缓冲区清除为最大值;
  2. 每个红色位置
    1. 对于每个输出片段,计算距离该位置的距离;
    2. 检查该片段已存储的距离;
    3. 如果新距离小于存储的距离,请替换存储的版本。
  3. 在OpenGL中执行此操作的最简单方法可能是使用深度缓冲区,因为它具有直接在硬件中实现的每片段步骤(2)和(3)。

    因此,对于每个片段,您将计算与当前红色片段的距离。你将把它作为深度输出。当您完成所有红点后,您可以使用深度缓冲区作为输出适当颜色的着色器的输入。

    为了避免2000个红点变成一个2000遍的绘图算法,这个算法很快就会对内存带宽产生影响,你可能想要编写一个单一的着色器,它可以同时处理大量的红点并输出一个深度值。

    您应该检查GL_MAX_UNIFORM_LOCATIONS以了解您可以一次推出多少件制服。在最新版本的桌面OpenGL上保证至少为1024。您可能希望动态生成着色器。

答案 1 :(得分:0)

为什么不高斯模糊大半径的整个图像,但是在每次迭代时都要将红色像素以完全强度添加回方程中,以便它们流出。最终模糊的红色通道将是您的距离值 - 较高的值更接近红色像素。这是近似值,但您可以使用经过大量优化的模糊着色器。