改进Opengl 2.0片段着色器

时间:2012-08-14 07:18:09

标签: opengl-es opengl-es-2.0 textures fragment-shader

如何改进此片段着色器:

  #ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform sampler2D u_texture;

uniform vec2 blurSize;
uniform vec4 substract;

  void main() {
    vec4 sum = vec4(0.0);
    sum += texture2D(u_texture, vec2(v_texCoord.x - 4.0 * blurSize.x, v_texCoord.y)) * 0.05;
    sum += texture2D(u_texture, vec2(v_texCoord.x - 3.0*blurSize.x, v_texCoord.y)) * 0.09;
    sum += texture2D(u_texture, vec2(v_texCoord.x - 2.0*blurSize.x, v_texCoord.y)) * 0.12;
    sum += texture2D(u_texture, vec2(v_texCoord.x - blurSize.x, v_texCoord.y)) * 0.15;
    sum += texture2D(u_texture, vec2(v_texCoord.x, v_texCoord.y)) * 0.16;
    sum += texture2D(u_texture, vec2(v_texCoord.x + blurSize.x, v_texCoord.y)) * 0.15;
    sum += texture2D(u_texture, vec2(v_texCoord.x + 2.0*blurSize.x, v_texCoord.y)) * 0.12;
    sum += texture2D(u_texture, vec2(v_texCoord.x + 3.0*blurSize.x, v_texCoord.y)) * 0.09;
    sum += texture2D(u_texture, vec2(v_texCoord.x + 4.0*blurSize.x, v_texCoord.y)) * 0.05;
    gl_FragColor = sum;    
}

我用它来模糊一条线,所以大部分时间都是混合相同的颜色。我希望它忽略(留下背景颜色)具有相同周围颜色的像素。我怎么能这样做?

2 个答案:

答案 0 :(得分:3)

忽略线条颜色的检查,我提出的一个建议是将纹理坐标计算移动到顶点着色器中并将它们作为变化传递。例如,您可以将vec2(v_texCoord.x - 4.0 * blurSize.x, v_texCoord.y)移动到顶点着色器中,并将其作为firstTextureCoordinate变化传递,以便您只需要执行

sum += texture2D(u_texture, firstTextureCoordinate) * 0.05;
片段着色器中的

这有两个显着的优点,第一个优点是,它不是对每个片段执行计算,而是每个顶点只运行一次计算,然后使用快速硬件插值将其提供给片段着色器。通常,顶点比片段少很少,因此可以节省一些计算。

第二个也许更重要的优点是,在基于图块的延迟渲染器(如iOS设备中的PowerVR系列)中,从作为变化输入的坐标进行纹理提取可避免依赖纹理读取。这让这些GPU在纹理提取上做了一些很好的缓存,我发现它在这个特定硬件上的性能上有很大的不同。

通过一些巧妙的逻辑,你可能仍然能够以削减的纹理拾取的数量,但是这是一个简单的优化我在OpenGL ES的片段着色器使用无处不在,它总是给我一个很好的性能提升。

答案 1 :(得分:1)

着色器中的很多if-check都是NO GO。

另一种选择可能是添加一个制服(如果你有很多行,则加一个统一的数组),它告诉着色器该行的中心(仅适用于你的线的x坐标)。

然后,着色器可以具有单个if检查,如下所示:

float spread = 4.0 * blurSize.x;
if(lineCentre-spread < gl_FragCoord.x && gl_FragCoord.x < lineCentre+spread){
   //You existing logic for blurr goes here.
}else{
    gl_FragColor = texture2D(u_texture, vec2(v_texCoord.x, v_texCoord.y)) * 0.16;
}

如果你周围有很多空白区域,这可以提高整体性能。