用于模糊的OpenGL ES 2.0片段着色器速度慢且质量低

时间:2010-12-04 19:58:06

标签: iphone ipad ios opengl-es opengl-es-2.0

我正在尝试为iPad编写模糊着色器。我有它的工作,但我对结果不是很满意。我的帧速率非常不稳定,当模糊量很高时,模糊看起来像废话。

关于如何改善事物的任何想法?

一些示例输出:

alt text

uniform sampler2D texture;
varying mediump vec2 fragTexCoord;
varying mediump vec3 eyespaceNormal;

varying highp float blurAmount;

void main(void)
{
    highp vec2 gaussFilter[7];
    gaussFilter[0] = vec2(-3.0, 0.015625);
    gaussFilter[1] = vec2(-2.0, 0.09375);
    gaussFilter[2] = vec2(-1.0, 0.234375);
    gaussFilter[3] = vec2(0.0, 0.3125);
    gaussFilter[4] = vec2(1.0, 0.234375);
    gaussFilter[5] = vec2(2.0, 0.09375);
    gaussFilter[6] = vec2(3.0, 0.015625);

    highp float blurSize = blurAmount * 1.0;

    /////////////////////////////////////////////////
    // 7x1 gaussian blur fragment shader
    /////////////////////////////////////////////////

    highp vec4 color = vec4(0,0,0,1);

    for( int i = 0; i < 7; i++ )
    {
        color += texture2D( texture, vec2( fragTexCoord.x+gaussFilter[i].x*blurSize, fragTexCoord.y+gaussFilter[i].x*blurSize ) )*gaussFilter[i].y;
    }

    gl_FragColor = color;
}

编辑: 盒子模糊可能是要走的路。 这是着色器的框模糊版本:

highp vec4 color = vec4(0,0,0,1);

color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y - 4.0*blurAmount)) * 0.05;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y - 3.0*blurAmount)) * 0.09;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y - 2.0*blurAmount)) * 0.12;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y - blurAmount)) * 0.15;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y)) * 0.16;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y + blurAmount)) * 0.15;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y + 2.0*blurAmount)) * 0.12;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y + 3.0*blurAmount)) * 0.09;
color += texture2D(texture, vec2(fragTexCoord.x, fragTexCoord.y + 4.0*blurAmount)) * 0.05;

gl_FragColor = color;

这是盒子模糊输出(注意它只是一个水平模糊,但它可能足够我想要的): alt text

3 个答案:

答案 0 :(得分:10)

该着色器需要运行两次才能生效,您调用的blurSize应为vec2,其值应为vec2(0, 1.0/height),用于垂直模糊和{{1}对于水平模糊。

请参阅http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=240334

做两次模糊背后的想法是它会大大减少纹理查找次数,并希望提高速度。内核大小为7x7的两遍模糊将需要14次纹理查找,但如果它在嵌套循环中完成,则需要进行49次纹理查找。

答案 1 :(得分:3)

执行两次或更多次框模糊处理可将质量提高到非常接近的高斯模糊,同时保持相对较高的性能。并且盒子模糊也可以相对容易地加速。看看http://web.archive.org/web/20060718054020/http://www.acm.uiuc.edu/siggraph/workshops/wjarosz_convolution_2001.pdf

在任何情况下,在大多数移动的场景中,你可以使用低于保真度的渲染,而不是从截图中看起来很明显。

答案 2 :(得分:1)

目前尚不清楚您的代码到底在做什么。您正在使用texture2D,它建议使用2D过滤器。然而你的卷积矩阵有一个维度,你只循环一次。我可能错了,但似乎你正在对角地应用模糊。如果它意味着是2D滤镜,那么你需要两个(嵌套的)x和y循环来覆盖2D区域。

关于变量blurSize - 它的名字有点误导。模糊的大小取决于您的卷积矩阵。你的是7像素宽。这决定了规模。变量更像是模糊的“强度”,它只能淡化卷积矩阵的效果。如果给定的值过高,则会出现伪影。

我不是专家,除了“hello world”mandelbrot之外,我还没有写过任何像素着色器。如果我没错,那么模糊着色器是加速最差的之一。我看到的大多数实时模糊都是box-blurs。尝试从此处移植一些代码:gameDev thread