glsl片段着色器中的特定坐标输出?

时间:2013-07-30 10:30:01

标签: glsl shader gpu

有没有办法,而不是使用预定的坐标作为gl_FragColor的输出,用其坐标设置特定像素的颜色?

我目前正在尝试通过着色器实现Mean Shift算法。我的输入是黑白纹理,其中白点代表要聚集的点,黑色代表无数据。

计算邻域中所有点位置的加权平均值后,我必须将结果位置的像素设置为代表群集的新颜色。

例如,如果我查看以像素为中心的18x18邻域与fragcoord相关并找到3个白色像素: Fragcoord = 30,33 像素1:坐标(30,33) 像素2:坐标(27,33) 像素3:坐标(30,30)

在计算了他们的平均位置之后,我会(29,32)。有没有办法在具有不同fragcoord的着色器单元中将29,32处的像素设置为不同的颜色(例如,30,33)?

像gl_FragColor(vec2(29,32))= vec4(1.0,1.0,1.0,1.0); ?

2 个答案:

答案 0 :(得分:3)

不,那是不可能的。为特定位置的特定片段调用片段着色器,并且只能输出该特定片段的值(或者对整个片段进行discrad),然后在预先确定的片段位置将其写入帧缓冲区。

您可以做的不是将输出写入帧缓冲区,而是写入其他存储区,可以是任意图像(使用image load/store)或shader storage buffer。但这两个功能需要相当现代的硬件功能(GL 4+硬件)。在这种情况下,您也可以首先使用正确的compute shader(或者像 CUDA OpenCL 这样的实际计算框架,如果你不需要任何其他OpenGL功能。)


另一种适用于旧硬件的方法是在顶点着色器而不是片段着色器中进行处理。这样您就可以相应地计算顶点的剪辑空间位置(然后变成片段位置)。使用几何着色器而不是顶点着色器时,您甚至可以分散数据(为单个输入计算多个输出)或丢弃内容。

答案 1 :(得分:2)

正如克里斯蒂安所说,这是不可能的;如果您可以使用它,计算框架或图像加载/存储是您切换到的最佳选择。

如果你必须使用没有图像加载/存储的GLSL,你有一个选项:如果你的图像总共有n个像素,那么将n个顶点作为点发送到顶点着色器;在顶点着色器中,根据你的gl_VertexID读取纹理(在GLSL 1.10中可用...如果你有1.40+你可能应该使用实例和gl_InstanceID),并定位点,这样当它进入片段着色器时,它涵盖了你想要的像素。然后让像素着色器输出为白色,无论如何。

它是一个黑客,但如果你没有其他选择,它可能会正常工作。