使用OpenGL ES应用亮度和对比度

时间:2009-10-01 20:32:15

标签: iphone image-processing opengl-es image-manipulation

我想更改iPhone上纹理的亮度对比度。我一直在查看apple(GLImageProcessing)提供的示例,但它只能一次执行一个(调用示例中的两个方法都会覆盖以前的结果)。

亮度效果很好:

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

在此之后如何添加纹理对比度?或者,移植到OpenGL ES 2.0并使用着色器执行此操作会更好吗?

以下是来自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);

正如您可能猜到的,我对OpenGL(ES)的体验非常有限,因此非常感谢任何指向正确方向的内容

3 个答案:

答案 0 :(得分:7)

使用片段着色器更容易,至少在OpenGL 2.1中(我没有使用过OpenGL ES)。 “OpenGL着色语言”一书涵盖了第19章中的图像处理。它们提供了用于调整亮度和对比度的着色器。这是我的版本,它结合了两个半:

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

修改:有关完整性的更多细节......

亮度和对比度的基值为1.0,因此将其传递给两者将使纹理保持不变。小于1.0的值将降低亮度,大于1.0的值将增加亮度。对比度小于1.0的值将使纹理更灰(对比度更低),大于1.0的值将使灰色更少(对比度更高)。

您可以为AverageLuminance传入(0.5,0.5,0.5,1.0)快速灰度值,但通过计算纹理的适当平均亮度可以获得更好的结果。

答案 1 :(得分:1)

您可以将亮度调整后的图像渲染为相同大小的帧缓冲纹理,然后在将此纹理渲染到屏幕时执行对比度调整。

Image -> [Brightness] -> Texture -> [Contrast] -> Screen

对帧缓冲区和渲染到纹理的一些有用的阅读:

答案 2 :(得分:0)

我的GL有点生疏,但是从示例代码中可以创建一个与现有场景混合的纹理。因此,您可以只创建两个纹理,确保它们不会相互踩踏,然后然后将它们混合在一起。他们做了不同的事情,所以我怀疑你能否将它们组合在同一个纹理中。我首先订购对比度,因为它是一个更复杂的混合。