2

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

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

我找到了这个答案,这似乎最接近我的问题—— 快速找到图像中最近的非黑色像素——但这不是 glsl 特定的。

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

4

2 回答 2

3

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

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

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

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

  1. 将输出缓冲区清除到最大值;
  2. 对于每个红色位置:
    1. 对于每个输出片段,计算与该位置的距离;
    2. 检查该片段已经存储了多少距离;
    3. 如果新距离小于存储的距离,则替换存储的版本。

在 OpenGL 中最简单的方法可能是使用深度缓冲区,因为它具有直接在硬件中实现的每个片段的步骤 (2) 和 (3)。

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

为了避免 2000 个红点变成 2000 次绘制算法,这会很快耗尽内存带宽,您可能需要编写一个单一的着色器,一次处理大量的红点并输出一个单一的深度值。

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

于 2013-10-16T00:49:19.360 回答
0

为什么不用大半径对整个图像进行高斯模糊处理,但是在每次迭代中,不断将红色像素以全强度添加回方程中,这样它们就会消失。最终模糊的红色通道将是您的距离值 - 较高的值更接近红色像素。这是一个近似值,但是您可以使用高度优化的模糊着色器。

于 2013-12-17T22:37:48.000 回答