【问题标题】:improve Opengl 2.0 fragment shader改进 OpenGL 2.0 片段着色器
【发布时间】:2012-08-14 23:07:41
【问题描述】:

如何改进这个片段着色器:

  #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;    
}

我用它来模糊一条线,所以大多数时候它混合了相同的颜色。我希望它忽略(保留为背景颜色)具有相同周围颜色的像素。我怎么能这样做?

【问题讨论】:

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


    【解决方案1】:

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

    sum += texture2D(u_texture, firstTextureCoordinate) * 0.05;
    

    在您的片段着色器中。

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

    第二个也许更重要的优势是,在基于 tile 的延迟渲染器(如 iOS 设备中的 PowerVR 系列)上,从作为变量输入的坐标中提取纹理可以避免依赖纹理读取。这让这些 GPU 可以对纹理提取进行一些很好的缓存,而且我已经看到它在这个特定硬件上的性能产生了巨大的差异。

    通过一些巧妙的逻辑,您可能仍然能够减少纹理提取的数量,但这是我在 OpenGL ES 片段着色器中随处使用的简单优化,它总能给我带来不错的性能提升。

    【讨论】:

      【解决方案2】:

      着色器中的大量 if-checks 是不行的。

      另一个选项可能是添加一个统一(如果你有很多行,则添加一个统一数组),它告诉着色器该行的中心(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;
      }
      

      如果您周围有大量空白区域不会进行模糊处理,这可以提高整体性能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多