andrés
andrés

Reputation: 412

improve Opengl 2.0 fragment shader

How can I improve this 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;    
}

I'm using it to blur a line, so most of the time it is blending the same color. I would like for it to ignore (leave as background color) the pixels that have the same surrounding colors. How could I do that?

Upvotes: 0

Views: 1442

Answers (2)

Brad Larson
Brad Larson

Reputation: 170309

Ignoring the checks for line colors, one suggestion I'd make would be to move the texture coordinate calculations up into your vertex shader and pass them in as varyings. For example, you could move the vec2(v_texCoord.x - 4.0 * blurSize.x, v_texCoord.y) into the vertex shader, and pass it in as a firstTextureCoordinate varying so that you just need to do

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

in your fragment shader.

This has two significant advantages, the first being that rather than performing a calculation on every fragment, it only runs this calculation once per vertex and then uses quick hardware interpolation to feed that into the fragment shader. You usually have a lot fewer vertices than fragments, so that can save on some calculations.

The second and perhaps more significant advantage is that on tile-based deferred renderers like the PowerVR series in iOS devices, doing texture fetches from coordinates fed in as varyings avoids dependent texture reads. This lets these GPUs do some nice caching on the texture fetches, and I've seen it make a huge difference in performance on this particular hardware.

With some clever logic, you might still be able to cut down on the number of texture fetches, but this is a simple optimization I use everywhere in my OpenGL ES fragment shaders and it always gives me a nice performance boost.

Upvotes: 3

CuriousChettai
CuriousChettai

Reputation: 1882

A lot of if-checks in the shader is a NO GO.

The other option probably is to add a uniform(or a uniform array if u have many lines) which tells the shader where the center(x coord only for yourlines) of the line would be.

The shader can then have a single if check as in:

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

This can improve overall performance if you have a lot of blank space around which doesn't undergo blurring.

Upvotes: 1

Related Questions