Android OpenGL 2.0低FPS如何解决?

时间:2020-06-12 02:46:34

标签: android filter opengl-es webrtc frame-rate

当我向相机添加滤镜时,fps太低。普通滤镜适合30 fps。 当我添加模糊滤镜时,某些测试手机的fps为10-20 fps。但是,在某些手机上,fps会低于10。 如果您查看源代码并让我知道在哪里修复它,我将不胜感激。

public class InstaFilter extends GPUImageFilter {
    protected static final String VERTEX_SHADER = "attribute vec4 position;\n" +
            " attribute vec4 inputTextureCoordinate;\n" +
            " \n" +
            " varying vec2 textureCoordinate;\n" +
            " \n" +
            " void main()\n" +
            " {\n" +
            "    gl_Position = position;\n" +
            "    textureCoordinate = inputTextureCoordinate.xy;\n" +
            " }\n";

    protected int [] GL_TEXTURES = { GLES20.GL_TEXTURE3, GLES20.GL_TEXTURE4, GLES20.GL_TEXTURE5,
            GLES20.GL_TEXTURE6, GLES20.GL_TEXTURE7, GLES20.GL_TEXTURE8 };

    protected int textureNum; //MAX 6
    protected int [] coordinateAttributes;
    protected int [] inputTextureUniforms;
    protected int [] sourceTextures;
    protected ByteBuffer[] coordinatesBuffers;
    protected Bitmap[] bitmaps;
    ByteBuffer bBuffer;
    FloatBuffer fBuffer;
    float[] buffer;

    public InstaFilter(String fragmentShader, int textures) {
        this(VERTEX_SHADER, fragmentShader, textures);
    }

    public InstaFilter(String vertexShader, String fragmentShader, int textures) {
        super(vertexShader, fragmentShader);
        textureNum = textures;
        coordinateAttributes = new int[textureNum];
        inputTextureUniforms = new int[textureNum];
        sourceTextures = new int[textureNum];
        for (int i = 0; i < textureNum; i++) {
            sourceTextures[i] = OpenGlUtils.NO_TEXTURE;
        }
        coordinatesBuffers = new ByteBuffer[textureNum];
        bitmaps = new Bitmap[textureNum];
        setRotation(Rotation.NORMAL, false, false);
    }

    public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) {
        float[] buffer = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical);

        if(bBuffer == null){
            bBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
        }


        if(fBuffer == null){
            fBuffer = bBuffer.asFloatBuffer();
        }

        fBuffer.put(buffer);
        fBuffer.flip();


        for (int i = 0; i < textureNum; i++) {
            coordinatesBuffers[i] = bBuffer;
        }

    }

    @Override
    public void onInit() {
        super.onInit();
        Log.d("InstaFilter", "onInit()");
        int k;
        for (int i = 0; i < textureNum; i++) {
            k = i + 2;
            coordinateAttributes[i] = GLES20.glGetAttribLocation(getProgram(), String.format("inputTextureCoordinate%d", k));
            inputTextureUniforms[i] = GLES20.glGetUniformLocation(getProgram(), String.format("inputImageTexture%d", k));
            GLES20.glEnableVertexAttribArray(coordinateAttributes[i]);
            if (bitmaps[i] != null && !bitmaps[i].isRecycled()) {
                loadBitmap(i, bitmaps[i]);
            }
        }
    }

    public void onDestroy() {
        super.onDestroy();
        if (textureNum > 0) {
            try{
                GLES20.glDeleteTextures(1, sourceTextures, 0);

                for (int i = 0; i < textureNum; i++) {
                    sourceTextures[i] = OpenGlUtils.NO_TEXTURE;
                    if (bitmaps[i] != null && !bitmaps[i].isRecycled()) {
                        bitmaps[i].recycle();
                        bitmaps[i] = null;
                    }
                }
            } catch (Exception e) {
            }
        }
    }


    public void setBitmap(final int index, final Bitmap bitmap) {

        if (bitmap != null && bitmap.isRecycled()) {
            return;
        }
        if (bitmap == null) {
            return;
        }
        bitmaps[index] = bitmap;
    }

    private void loadBitmap(final int index, final Bitmap bitmap) {
        if (bitmap != null && bitmap.isRecycled()) {
            return;
        }
        if (bitmap == null) {
            return;
        }
        runOnDraw(new Runnable() {
            public void run() {
                if (bitmap == null || bitmap.isRecycled()) {
                    return;
                }
                if (sourceTextures[index] == OpenGlUtils.NO_TEXTURE) {
                    GLES20.glActiveTexture(GL_TEXTURES[index]);
                    sourceTextures[index] = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false);
                }
            }
        });
    }

    @Override
    protected void onDrawArraysPre() {
        for (int i = 0; i < textureNum; i++) {
            GLES20.glEnableVertexAttribArray(coordinateAttributes[i]);
            GLES20.glActiveTexture(GL_TEXTURES[i]);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, sourceTextures[i]);
            GLES20.glUniform1i(inputTextureUniforms[i], i + 3);
            coordinatesBuffers[i].position(0);
            GLES20.glVertexAttribPointer(coordinateAttributes[i], 2, GLES20.GL_FLOAT, false, 0, coordinatesBuffers[i]);
        }
    }
}

BlurFilter

public class BlurFilter extends InstaFilter{
    public static final String BLUR_FRAGMENT_SHADER = "precision lowp float;\n" +
            " uniform vec3 iResolution; \n" +
            " uniform sampler2D inputImageTexture;\n" +
            " varying vec2 textureCoordinate; \n" +
            " uniform float size;\n" +
            " \n" +
            " void mainImage(out vec4 fragColor, in vec2 fragCoord){ \n" +
            " float Pi = 6.28318530718; \n" +
            " float Directions = 16.0; \n" +
            " float Quality = 3.0; \n" +
            " vec2 Radius = size/iResolution.xy; \n" +
            " vec2 uv = fragCoord/iResolution.xy; \n" +
            " vec4 Color = texture2D(inputImageTexture, uv); \n" +
            " for( float d=0.0; d<Pi; d+=Pi/Directions){ \n" +
            "   for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality){ \n" +
            "       Color += texture2D( inputImageTexture, uv+vec2(cos(d),sin(d))*Radius*i); \n" +
            "   } \n" +
            " }\n" +
            " Color /= Quality * Directions - 15.0;\n" +
            " fragColor =  Color;\n" +
            "}\n" +
            "\n" +
            " void main() { \n" +
            " mainImage(gl_FragColor, textureCoordinate*iResolution.xy);\n" +
            " }\n";

    protected static final String BLUR_VERTEX_SHADER = "attribute vec2 position;\n" +
            " attribute vec2 inputTextureCoordinate;\n" +
            " \n" +
            " varying vec2 textureCoordinate;\n" +
            " \n" +
            " void main()\n" +
            " {\n" +
            "    textureCoordinate = inputTextureCoordinate;\n" +
            "    gl_Position = vec4 ( position.x, position.y, 0.0, 1.0 );\n" +
            " }\n";

    private int iResolutionLocation;
    private int[] iResolutionArray;
    private float sizeLevel;
    private int sizeLocation;

    public BlurFilter(Context context) {
        super(BLUR_VERTEX_SHADER, BLUR_FRAGMENT_SHADER, 0);
        this.iResolutionArray = new int[]{getOutputWidth(), getOutputHeight()};
    }

    @Override
    public void onInit() {
        super.onInit();
        iResolutionLocation = GLES20.glGetUniformLocation(getProgram(), "iResolution");
        sizeLocation = GLES20.glGetUniformLocation(getProgram(), "size");
        sizeLevel = 70.0f;
        this.setFloat(this.sizeLocation, sizeLevel);
    }
    @Override
    public void onOutputSizeChanged(int width, int height){
        super.onOutputSizeChanged(width, height);
        this.iResolutionArray = new int[]{width, height};
        setFloatVec3(iResolutionLocation, new float[]{(float) iResolutionArray[0], (float) iResolutionArray[1], 1.0f});
    }

    public void setBlurSize(float size){
        this.sizeLevel = size;
        Log.d("BlurFilter", "BlurFilter size : " + this.sizeLevel);
        this.setFloat(sizeLocation, this.sizeLevel);
    }
}

常规过滤器

public class IFNormalFilter extends InstaFilter{
    public static final String SHADER = "precision lowp float;\n" +
            " precision lowp float;\n" +
            " varying highp vec2 textureCoordinate;\n" +
            " \n" +
            " uniform sampler2D inputImageTexture;\n" +
            "\n" +
            " void main()\n" +
            " {\n" +
            "     \n" +
            "     vec3 texel = texture2D(inputImageTexture, textureCoordinate).rgb;\n" +
            "     \n" +
            "     gl_FragColor = vec4(texel, 1.0);\n" +
            " }";

    public IFNormalFilter(Context context) {
        super(SHADER, 0);
    }
}

0 个答案:

没有答案