6

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

关于如何改进的任何想法?

一些示例输出:

替代文字

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;

这是框模糊输出(请注意,它只是水平模糊,但对于我想要的可能就足够了): 替代文字

4

3 回答 3

10

该着色器需要运行两次才能工作,您所说blurSize的应该是 a vec2,其值应该是vec2(0, 1.0/height)垂直模糊和vec2(1.0/width, 0)水平模糊。

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

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

于 2010-12-04T22:03:57.717 回答
3

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

在任何情况下,在大多数移动场景中,您都可以使用比屏幕截图看起来明显的低保真度渲染。

于 2010-12-10T13:09:25.370 回答
1

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

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

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

于 2010-12-04T20:52:11.147 回答