使用着色器创建模糊滤镜 - 从片段着色器访问相邻像素?

时间:2011-07-27 18:53:35

标签: opengl-es-2.0 shader

我想在OpenGL ES 2.0中使用片段着色器创建模糊效果。我感兴趣的算法只是一个平均模糊 - 将所有相邻像素添加到我自己并除以9以进行标准化。

但是我有两个问题:

1)这是否需要我首先渲染到帧缓冲区,然后切换渲染目标?或者是否有更简单的方法

2)假设我将“源”图像绑定为模糊纹理0,并输出模糊纹理。如何访问不是我当前正在处理的像素。 vert着色器调用了我的像素i,但我需要访问我周围的像素。怎么样?我如何知道我是否是一个边缘案例(字面意思是在屏幕的边缘)

(3:是否有更合适的算法让模糊的磨砂玻璃看起来模糊)

2 个答案:

答案 0 :(得分:11)

详细阐述马蒂亚斯所说的话:

  1. 是。您将图像渲染为纹理(最好使用FBO),然后在第二个(模糊)传递中绑定此纹理并从中读取。您无法一步执行渲染和模糊传递,因为您无法访问当前渲染的帧缓冲区。这会引入数据依赖性,因为你的邻居不需要它们的最终颜色,或者更糟糕的颜色取决于你。

  2. 您可以在特殊片段着色器变量gl_FragCoord中获取当前像素的坐标,并将这些作为纹理坐标用于包含先前渲染图像的纹理,同样gl_FragCoord.x +/- 1gl_FragCoord.y +/- 1为了邻居。但是像Matias所说的那样,你需要分别根据(图像的)宽度和高度来分配这些值,因为纹理坐标在[0,1]中。通过使用GL_CLAMP_TO_EDGE作为纹理的包装模式,边缘情况由纹理硬件自动处理。所以在一个边缘你仍然得到9个值,但只有6个不同的值(另外3个,实际上在图像之外的那些,只是它们内部邻居的重复)。

答案 1 :(得分:1)

1)是的,使用FBO是可行的方法。

2)使用数学,如果你是像素(x,y),那么邻居是(x + 1,y),(x,y + 1),(x + 1,y + 1),( x-1,y)等边缘情况用纹理的包裹模式处理。请注意,由于GL_TEXTURE_2D使用标准化坐标,因此偏移量不是1,而是纹理的1 /宽度和1 /高度。