I want to change the brightness and contrast of a texture on the iPhone. I've been looking at the sample provided by apple (GLImageProcessing) but it only is able to do one at a time (calling both methods in the sample overwrites the previous result).
Brightness works great:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
if (brightness >= 1.0f) {
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
glColor4f(brightness-1, brightness-1, brightness-1, brightness-1);
} else {
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT);
glColor4f(1-brightness, 1-brightness, 1-brightness, 1-brightness);
}
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
How would i go with adding contrast to the texture after this? Alternatively would it be a better choice to move to OpenGL ES 2.0 and do this with shaders?
Here's the code for contrast in the sample from apple:
glActiveTexture(GL_TEXTURE0);
glVertexPointer (2, GL_FLOAT, sizeof(V2fT2f), &quad[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &quad[0].s);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 2);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
glColor4f(h, h, h, 0.75 - 0.5 * h); // 2x extrapolation
validateTexEnv();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Restore state
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
glActiveTexture(GL_TEXTURE0);
As you can probably guess my experience with OpenGL (ES) is pretty limited so anything that points me in the right direction is greatly appreciated
This is much easier to do with a fragment shader, at least in OpenGL 2.1 (I haven't used OpenGL ES). The book "OpenGL Shading Language" covers image processing in chapter 19. They give shaders for adjusting brightness and contrast. Here is my version, which combines the two half-and-half:
uniform sampler2D Texture;
uniform float Brightness;
uniform float Contrast;
uniform vec4 AverageLuminance;
void main(void)
{
vec4 texColour = texture2D(Texture, gl_TexCoord[0].st);
gl_FragColor = mix(texColour * Brightness,
mix(AverageLuminance, texColour, Contrast), 0.5);
}
Edit: some more details for completeness...
Brightness and contrast have a base value of 1.0, so passing that in for both will leave the texture unchanged. A value less than 1.0 will decrease brightness, and a value greater than 1.0 will increase it. A value less than 1.0 for contrast will make the texture more grey (less contrast), and a value greater than 1.0 will make it less grey (more contrast).
You can pass in (0.5, 0.5, 0.5, 1.0) for AverageLuminance for a quick-and-dirty grey value, but better results will be obtained by calculating a proper average luminance for your texture.
You could render the brightness-adjusted image to a framebuffer texture of the same size, then perform the contrast adjustment as you render this texture to the screen.
Image -> [Brightness] -> Texture -> [Contrast] -> Screen
Some useful reading on framebuffers and render-to-texture:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With