用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低
Posted
技术标签:
【中文标题】用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低【英文标题】:OpenGL ES 2.0 fragment shader to blur is slow and low quality 【发布时间】:2010-12-04 19:58:05 【问题描述】:我正在尝试为 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;
这是框模糊输出(请注意,它只是水平模糊,但对于我想要的可能就足够了):
【问题讨论】:
【参考方案1】:该着色器需要运行两次才能正常工作,您调用的 blurSize
应该是 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 次纹理查找。
【讨论】:
是的,我认为这是我在调整代码方面的失误。谢谢。我认为我真的不需要完整的高斯来实现我的目的,因此简单的框模糊可能会足够好并且更快。【参考方案2】:执行两个或更多框模糊通道可将质量提高到非常接近高斯模糊,同时保持相对较高的性能。盒子模糊也可以相对容易地加速。看看http://web.archive.org/web/20060718054020/http://www.acm.uiuc.edu/siggraph/workshops/wjarosz_convolution_2001.pdf
在任何情况下,在大多数移动场景中,您都可以使用比屏幕截图看起来明显的更低保真度的渲染。
【讨论】:
【参考方案3】:不清楚您的代码到底在做什么。您使用的 texture2D 建议使用 2D 过滤器。然而你的卷积矩阵只有一维,你只循环一次。我可能错了,但您似乎是在对角线应用模糊。如果它是 2D 过滤器,那么您需要两个(嵌套)循环分别用于 x 和 y 来覆盖 2D 区域。
关于变量blurSize
- 它的名称有点误导。模糊的大小取决于您的卷积矩阵。你的是 7 像素宽。这决定了大小。该变量更像是模糊的“强度”,只能淡化卷积矩阵的效果。如果给定的值太高,就会出现伪像。
我不是专家,除了“hello world”mandelbrot 之外,我还没有写过任何像素着色器。如果我没记错的话,模糊着色器是加速最差的着色器之一。我看到的大多数实时模糊是box-blurs。尝试从这里移植一些代码:gameDev thread。
【讨论】:
我决定试试盒子模糊。似乎工作得很好,但我还没有在我的 iPad 上尝试过,看看它是否足够快,但看起来还不错。我将在上面的答案中发布代码。谢谢以上是关于用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低的主要内容,如果未能解决你的问题,请参考以下文章
如何在 OpenGL ES 2.0 中获得“发光”着色器效果?
如何使用 OpenGL ES 2.0 着色器完成这些图像处理任务?
IOS:OpenGL ES 2.0 与 3.0 中动态分支着色器的性能