用于图像处理的OpenGL ES 2.0着色器示例?

ohh*_*hho 9 iphone shader image-processing opengl-es-2.0

我正在学习着色器编程并寻找示例,特别是用于图像处理.我想对我的照片应用一些Photoshop效果,例如曲线,色阶,色调/饱和度调整等.

Tom*_*mmy 10

我假设你有一个简单的无争议的顶点着色器,因为它与问题并不真正相关,例如:

void main()
{
    gl_Position = modelviewProjectionMatrix * position;
    texCoordVarying = vec2(textureMatrix * vec4(texCoord0, 0.0, 1.0));
}
Run Code Online (Sandbox Code Playgroud)

因此,如果禁用了光照,那么与ES 1.x大致相同,包括几乎没有人使用过的纹理矩阵.

我不是Photoshop专家,所以请原谅我对各种工具的看法 - 特别是如果我错了.

我认为我说水平工具有效地拉伸(和剪辑)亮度直方图是对的吗?在这种情况下,示例着色器可以是:

varying mediump vec2 texCoordVarying;
uniform sampler2D tex2D;

const mediump mat4 rgbToYuv = mat4( 0.257,  0.439,  -0.148, 0.06, 
                                    0.504, -0.368,  -0.291, 0.5,
                                    0.098, -0.071,   0.439, 0.5, 
                                     0.0,     0.0,     0.0, 1.0);

const mediump mat4 yuvToRgb = mat4( 1.164,  1.164,  1.164,  -0.07884, 
                                    2.018, -0.391,    0.0,  1.153216,
                                      0.0, -0.813,  1.596,  0.53866, 
                                      0.0,    0.0,    0.0,  1.0);

uniform mediump float centre, range;    

void main()
{
    lowp vec4 srcPixel = texture2D(tex2D, texCoordVarying);
    lowp vec4 yuvPixel = rgbToYuv * srcPixel;

    yuvPixel.r = ((yuvPixel.r - centre) * range) + 0.5;

    gl_FragColor = yuvToRgb * yuvPixel;
}
Run Code Online (Sandbox Code Playgroud)

您可以通过设置要通过的范围的中心(将移动到输出范围的中心)和您想要通过的总范围来控制(整个范围为1.0,0.5为一半)范围等).

有趣的是我从RGB输入空间切换到YUV颜色空间进行中间调整.我使用矩阵乘法来做到这一点.然后我调整亮度通道,并应用另一个从YUV转换回RGB的矩阵.对我而言,在亮度/色度色彩空间中工作是最有意义的,从那里我相当随意地选择了YUV,尽管它具有ES作为RGB空间的简单线性变换的ES的巨大优势.

我理解曲线工具也重新映射亮度,但是根据某个函数f(x)= y,它是单调递增的(因此,只会与任何水平或垂直相交一次)并在接口中设置为以某种方式从左下到右上的曲线.

因为GL ES在数据结构方面并不出色,并且尽可能避免分支,我建议最好的方法是上传256x1亮度纹理,其中'x'的值为f(x).然后你可以只通过辅助纹理进行映射,例如:

... same as before down to ...
lowp vec4 yuvPixel = rgbToYuv * srcPixel;

yuvPixel.r = texture2D(lookupTexture, vec2(yuvPixel.r, 0.0));

... and as above to convert back to RGB, etc ...
Run Code Online (Sandbox Code Playgroud)

您正在使用备用纹理单元来有效地索引查找表.在支持ES 2.0的iOS设备上,您至少可以获得8个纹理单元,因此您希望有一个备用.

色调/饱和度调整更难以显示,因为从RGB到HSV的映射涉及很多条件,但过程基本相同 - 从RGB到HSV的映射,在H和S上执行所需的修改,映射回RGB和输出.

基于一个快速谷歌搜索,该网站提供了一些可下载的代码,其中包括一些Photoshop的功能(虽然不是曲线或水平,这样我可以看到),并显著,功能用品示例实现RGBToHSLHSLToRGB.它适用于桌面GLSL,它具有更多预定义的变量,类型和功能,但您不应该遇到任何大问题.只需记住添加精度修饰符并为缺席minmax函数提供自己的替换.


小智 6

对于曲线,photoshop使用双三次样条插值.对于给定的一组控制点,您可以预先计算每个通道和主曲线的所有256个值.我发现将结果存储为256x1纹理并将其传递给着色器然后更改每个组件的值更容易:

uniform sampler2D curvesTexture;

vec3 RGBCurvesAdjustment(vec3 color)
{
    return vec3(texture2D(curvesTexture, vec2(color.r, 1.0)).r,
                texture2D(curvesTexture, vec2(color.g, 1.0)).g,
                texture2D(curvesTexture, vec2(color.b, 1.0)).b);
}
Run Code Online (Sandbox Code Playgroud)