首页 > 解决方案 > 如何创建一个从查找表映射颜色的简单片段着色器?

问题描述

我正在尝试为我的 Android 应用程序创建像 Instagram 这样的图像过滤器。我是图像处理的新手,刚刚偶然发现了这个称为颜色映射的术语。经过大量研究,我尝试使用 OpenGL 使用查找表 (LUT) 创建自己的过滤器。但是在将滤镜添加到相机后,结果如下:

在此处输入图像描述

你可以看到我的拇指边缘有一种奇怪的蓝色。它只发生在图像的过度曝光区域。

这是片段着色器代码:

#extension GL_OES_EGL_image_external : require
precision lowp float;
             
varying highp vec2 vTextureCoord;
             
uniform samplerExternalOES inputImage;
uniform sampler2D lookup;
             
void main() {
     vec2 tiles    = vec2(8.0);
     vec2 tileSize = vec2(64.0);
     vec4 texel = texture2D(inputImage, vTextureCoord);
     float index = texel.b * (tiles.x * tiles.y - 1.0);
     float index_min = min(62.0, floor(index));
     float index_max = index_min + 1.0;

     vec2 tileIndex_min;
     tileIndex_min.y = floor(index_min / tiles.x);
     tileIndex_min.x = floor(index_min - tileIndex_min.y * tiles.x);
     vec2 tileIndex_max;
     tileIndex_max.y = floor(index_max / tiles.x);
     tileIndex_max.x = floor(index_max - tileIndex_max.y * tiles.x);

     vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, texel.rg);
            
     vec2 tableUV_1 = tileIndex_min / tiles + tileUV / tiles;
     vec2 tableUV_2 = tileIndex_max / tiles + tileUV / tiles;
            
     vec3 lookUpColor_1 = texture2D(lookup, tableUV_1).rgb;
     vec3 lookUpColor_2 = texture2D(lookup, tableUV_2).rgb;
     vec3 lookUpColor   = mix(lookUpColor_1, lookUpColor_2, index-index_min);
     gl_FragColor = vec4(lookUpColor, 1.0);
}

这是查找表。这是一个基本查找表。我尝试编辑查找表并应用过滤器,但结果是相同的,与表无关。

是什么导致了这个问题?谁能告诉我如何创建一个简单的片段着色器,将颜色从查找表映射到当前纹理?任何帮助,将不胜感激。问候。

这是加载纹理的代码:

public static int loadTexture(final Bitmap img) {
        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
        return textures[0];
    }

标签: androidopengl-esopengl-es-2.0

解决方案


不确定您的外部采样器正在使用什么色彩空间或伽玛,但看起来您正在获取零到一范围之外的输入值,因此过度暴露的区域正在跳过 LUT 平铺边界。

作为诊断,将您的输入限制在 0 和 1 之间,但这很少是正确的“正确修复”,因为颜色的裁剪会很明显。

像这样的东西:

     vec4 texel = texture2D(inputImage, vTextureCoord);
     texel = min(texel, 1.0);

推荐阅读