1

For my android application, I want to apply brightness and contrast shader on same image.

At present I am using gpuimage plugin. In that I found two separate program for brightness and contrast as per the following.

 public static final String CONTRAST_FRAGMENT_SHADER = "" +
        "varying highp vec2 textureCoordinate;\n" + 
        " \n" + 
        " uniform sampler2D inputImageTexture;\n" + 
        " uniform lowp float contrast;\n" + 
        " \n" + 
        " void main()\n" + 
        " {\n" + 
        "     lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + 
        "     \n" + 
        "     gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);\n" + 
        " }";

public static final String BRIGHTNESS_FRAGMENT_SHADER = ""
        + "varying highp vec2 textureCoordinate;\n"
        + " \n"
        + " uniform sampler2D inputImageTexture;\n"
        + " uniform lowp float brightness;\n"
        + " \n"
        + " void main()\n"
        + " {\n"
        + "     lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n"
        + "     \n"
        + "     gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);\n"
        + " }";

Now applying both of the effects I write following code

public static final String CONTRAST_BRIGHTNESS_FRAGMENT_SHADER = ""
        + "varying highp vec2 textureCoordinate;\n"
        + " uniform sampler2D inputImageTexture;\n"
        + "varying highp vec2 textureCoordinate2;\n"
        + " uniform sampler2D inputImageTexture2;\n"
        + " uniform lowp float contrast;\n"
        + " uniform lowp float brightness;\n"
        + " \n"
        + " void main()\n"
        + " {\n"
        + "     lowp vec4 textureColorForContrast = texture2D(inputImageTexture, textureCoordinate);\n"
        + "     \n"
        + "     lowp vec4 contastVec4 = vec4(((textureColorForContrast.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColorForContrast.w);\n"
        + "     lowp vec4 textureColorForBrightness = texture2D(inputImageTexture2, textureCoordinate2);\n"
        + "     \n"
        + "     lowp vec4 brightnessVec4 = vec4((textureColorForBrightness.rgb + vec3(brightness)), textureColorForBrightness.w);\n"
        + "     gl_FragColor = contastVec4 + brightnessVec4;\n" + " }";

Doesn't able to get desire result. I can't able to figure out what I have to do next? What program I have to write?

3
  • From the looks of things, you probably do not need two sets of uniforms here. I assume the original shaders were a simple two-pass operation that used the same image and texture coordinates. The only interesting point of note is that if you are using linear texture filtering, then doing this in one pass may not produce the same results. That is because the original shader may have fetched the 4 nearest texels from the output of the first pass and done a weighted average before applying brightness adjustment. Commented Jun 12, 2014 at 17:07
  • There is also the issue of blending function now that I think about it. Your combined shader assumes additive blending (GL_ONE, GL_ONE). What is your actual blend function? Commented Jun 12, 2014 at 17:10
  • Does directly total of two vector work for me? If I only change blending function value. Commented Jun 13, 2014 at 7:18

1 Answer 1

3

Why would you add the 2 results in the end? What you need to do is fetch a texel and do the 2 mathematical operations on it. Try this:

lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec3 contrastedColor = ((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5));
gl_FragColor = vec4((contrastedColor + vec3(brightness)), textureColor.w);

Still this can produce a different result then using the 2 separate shaders so let's analyse a bit what goes on:

  • grab a texture color
  • apply contrast method
  • write colour to buffer (at this point the colour values are clamped in range [.0, 1.0])
  • grab a texture color
  • apply brightness
  • write colour to buffer

So what you should add is clamping the contrast colour contrastedColor to [0,1]. As for what M. Coleman said it is true you need to consider the possibility of the result being different because of fetching multiple texels BUT in your specific case that can NOT produce a different result and you are all good to go with it. As for the blending the assumption is being either disabled or (GL_ONE, GL_ZERO) which is the same thing (some other blending types might work as well).

Sign up to request clarification or add additional context in comments.

3 Comments

If blending were disabled, then the multi-pass technique first employed would do nothing. Which ever of the effects was applied last would be the only image processing that actually showed up. Knowing what needs to be done with the result of the two shaders will depend on knowing what the original blend function was. Because that function needs to be duplicated in the combined shader; right now the results of both are added, which is only the correct behavior if the original blend function was (GL_ONE, GL_ONE) == Src.rgba + Dst.rgba
Ah I see your point. You are looking from a perspective of drawing the texture to the buffer twice and combining the 2 results while I am looking from a perspective of using a FBO where the 2nd texture (in two pass case) is the target in first pass. Did you check the linked library for this information as if this is true it is definitely a bit strange approach: You gain nothing while you need to set additional blending depending on number of effects, 3 effects using (one,one) would have to be multiplied by 1/3 on each pass...
Oh, I made a rather stupid assumption now that you mention it... I just saw a sampler named inputImageTexture in both shaders and this part of the question: "I want to apply brightness and contrast shader on same image" and assumed that the sampler was using the same source texture in both passes. It is probably more likely that inputImageTexture refers to the output of the previous pass, rather than the original input image, in which case blending would not be necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.