Android GPUImage源码分析(四) Lookup滤镜的使用

 Android GPUImage源码分析(四) Lookup滤镜的使用

一、lookup滤镜输入双纹理输入滤镜

/****
 * 双纹理输入滤镜
 */
public class GPUImageTwoInputFilter extends GPUImageFilter {
    /**顶点坐标shader**/
    private static final String VERTEX_SHADER = "attribute vec4 position;\n" +
            "attribute vec4 inputTextureCoordinate;\n" +    /**纹理坐标1输入**/
            "attribute vec4 inputTextureCoordinate2;\n" +     /**纹理坐标2输入**/
            " \n" +
            "varying vec2 textureCoordinate;\n" +      /**纹理坐标1 输出**/
            "varying vec2 textureCoordinate2;\n" +    /**纹理坐标2 输出**/
            " \n" +
            "void main()\n" +
            "{\n" +
            "    gl_Position = position;\n" +
            "    textureCoordinate = inputTextureCoordinate.xy;\n" +
            "    textureCoordinate2 = inputTextureCoordinate2.xy;\n" +
            "}";

    private int filterSecondTextureCoordinateAttribute;
    private int filterInputTextureUniform2;
    private int filterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
    private ByteBuffer texture2CoordinatesBuffer;
    private Bitmap bitmap;

    public GPUImageTwoInputFilter(String fragmentShader) {
        this(VERTEX_SHADER, fragmentShader);
    }

    public GPUImageTwoInputFilter(String vertexShader, String fragmentShader) {
        super(vertexShader, fragmentShader);
        setRotation(Rotation.NORMAL, false, false);
    }

    @Override
    public void onInit() {
        super.onInit();
        /**纹理坐标2输入**/
        filterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2");
        /**纹理2输入**/
        filterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
        /**使能纹理坐标2**/
        GLES20.glEnableVertexAttribArray(filterSecondTextureCoordinateAttribute);
    }

    @Override
    public void onInitialized() {
        super.onInitialized();
        if (bitmap != null && !bitmap.isRecycled()) {
            setBitmap(bitmap);
        }
    }
    /***这个输入是输入第二个纹理的输入,如lookup滤镜的中lookup图片 512*512,
     * 区别:第一个纹理是用户图片,使用Render直接传入来的纹理**/
    public void setBitmap(final Bitmap bitmap) {
        if (bitmap != null && bitmap.isRecycled()) {
            return;
        }
        this.bitmap = bitmap;
        if (this.bitmap == null) {
            return;
        }
        runOnDraw(new Runnable() {
            public void run() {
                if (filterSourceTexture2 == OpenGlUtils.NO_TEXTURE) {
                    if (bitmap == null || bitmap.isRecycled()) {
                        return;
                    }
                    /**激活纹理内存单元3 GL_TEXTURE3**/
                    GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
                    /**加载bitmap对应的纹理**/
                    filterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false);
                }
            }
        });
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void recycleBitmap() {
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
            bitmap = null;
        }
    }

    public void onDestroy() {
        super.onDestroy();
        GLES20.glDeleteTextures(1, new int[]{
                filterSourceTexture2
        }, 0);
        filterSourceTexture2 = OpenGlUtils.NO_TEXTURE;
    }

    /**绘制数组前的设置**/
    @Override
    protected void onDrawArraysPre() {
        GLES20.glEnableVertexAttribArray(filterSecondTextureCoordinateAttribute);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE3);/**绑定纹理2对应的纹理内存单元3**/
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture2);/**绑定纹理2**/
        GLES20.glUniform1i(filterInputTextureUniform2, 3);      /**纹理2输入**/

        texture2CoordinatesBuffer.position(0);
        /***设置纹理属性数组**/
        GLES20.glVertexAttribPointer(filterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, texture2CoordinatesBuffer);
    }

    /**设置纹理坐标Buffer**/
    public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) {
        float[] buffer = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical);

        ByteBuffer bBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
        FloatBuffer fBuffer = bBuffer.asFloatBuffer();
        fBuffer.put(buffer);
        fBuffer.flip();
        texture2CoordinatesBuffer = bBuffer;
    }
}

二、lookup滤镜片段shader是重点

public class GPUImageLookupFilter extends GPUImageTwoInputFilter {

    public static final String LOOKUP_FRAGMENT_SHADER =
            "varying highp vec2 textureCoordinate;\n" +  /**纹理1坐标输出***/
            " varying highp vec2 textureCoordinate2; // TODO: This is not used\n" +
            " \n" +
            " uniform sampler2D inputImageTexture;\n" +  /****用户纹理输入***/
            " uniform sampler2D inputImageTexture2; // lookup texture\n" + //lookup 素材
            " \n" +
            " uniform lowp float intensity;\n" +  //强度
            " \n" +
            " void main()\n" +
            " {\n" +
            "     highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + //取得用户纹理的纹素
            "     \n" +
            "     highp float blueColor = textureColor.b * 63.0;\n" + //蓝色通道乘以63
            "     \n" +
            "     highp vec2 quad1;\n" +
            "     quad1.y = floor(floor(blueColor) / 8.0);\n" +  //蓝色通道除以8作为 y坐标
            "     quad1.x = floor(blueColor) - (quad1.y * 8.0);\n" +   //蓝色通道减去 y坐标乘以8
            "     \n" +
            "     highp vec2 quad2;\n" +
            "     quad2.y = floor(ceil(blueColor) / 8.0);\n" +
            "     quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n" +
            "     \n" +
            "     highp vec2 texPos1;\n" +
            "     texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n" + /**quad1下R通道相关**/
            "     texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n" +/**quad1G通道相关**/
            "     \n" +
            "     highp vec2 texPos2;\n" +
            "     texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n" +/**quad2下R通道相关**/
            "     texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n" +/**quad2G通道相关**/
            "     \n" +
            "     lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1);\n" +  /**取得新颜色1**/
            "     lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2);\n" + /**取得新颜色2**/
            "     \n" +
            "     lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n" +
            "     gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);\n" + /**混合**/
            " }";

    private int intensityLocation;
    private float intensity;

    public GPUImageLookupFilter() {
        this(1.0f);
    }

    public GPUImageLookupFilter(final float intensity) {
        super(LOOKUP_FRAGMENT_SHADER);
        this.intensity = intensity;
    }

    @Override
    public void onInit() {
        super.onInit();
        intensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity");
    }

    @Override
    public void onInitialized() {
        super.onInitialized();
        setIntensity(intensity);
    }

    public void setIntensity(final float intensity) {
        this.intensity = intensity;
        setFloat(intensityLocation, this.intensity);
    }
}

三、lookup图片为 512*512 rgba类型 png

Android GPUImage源码分析(四) Lookup滤镜的使用_第1张图片

四、滤镜的使用

          FilterType.LOOKUP_AMATORKA -> GPUImageLookupFilter().apply {
                bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.lookup_amatorka)
            }

 

你可能感兴趣的:(GPUImage源码分析)