Есть ли быстрый способ применить шейдер на Framebuffer в openGL-ES? - PullRequest
0 голосов
/ 13 марта 2020

Я хочу применить шейдер к выходу внешнего и закрытого SDK (FLIR Android SDK). Я нахожусь в том же контексте OpenGL, что и рендер SDK, моя идея состоит в том, чтобы загрузить вывод их кадрового буфера в мою текстуру и применить к ней шейдер.

Мой первый вопрос: действительно ли это самый быстрый способ достижения моей цели?

И, во-вторых, почему при вызове GLES31.glCopyTexSubImage2D(GLES31.GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height)?

происходит недопустимая операция К сожалению, я абсолютный новичок в OpenGL, и большинство из следующих копий и вставок из разных учебных пособий.

Метод onDraw() следующего класса рендеринга вызывается после рендерера FLIR SDK onDraw() и до swap() из GLSurfaceView.

Мой класс рендеринга:

public class BasicRenderer implements GLSurfaceView.Renderer {
    //flir texture size
    private static int width = 1080;
    private static int height = 1440;
    //gl handles
    private int positionHandle;
    private int vPMatrixHandle;
    private int mTexCoordHandle;
    private int mSamplerHandle;
    //vertices
    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;
    private static int COORDS_PER_VERTEX = 3;
    private int vertexCount;
    private static int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
    //texture
    private FloatBuffer uvBuffer;
    private int[] textureName;
    //shader program
    private int mProgram;
    //shaders
    private static String vertShader = "uniform mat4 uMVPMatrix;" +
            "attribute vec4 vPosition;" +
            "attribute vec2 a_texCoord;" +
            "varying vec2 v_texCoord;" +
            "void main() {" +
            "  gl_Position = uMVPMatrix * vPosition;" +
            "  v_texCoord = a_texCoord;" +
            "}";
    private static String fragShader = "precision mediump float;" +
            "varying vec2 v_texCoord;" +
            "uniform sampler2D s_texture;" +
            "void main() {" +
            "vec4 pixel  = texture2D( s_texture, v_texCoord );" +
            "gl_FragColor = pixel;" +
            "}";
    // vPMatrix -> "Model View Projection Matrix"
    private final float[] vPMatrix = new float[16];
    private final float[] projectionMatrix = new float[16];
    private final float[] viewMatrix = new float[16];

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        initVertices();
        initTextureCoords();
        initTexture();
        setUpShader();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int externWidth, int externHeight) {
        //projection matrix
        Matrix.orthoM(projectionMatrix, 0, 0, width, 0f, height, 0f, 7);
        //camera view
        Matrix.setLookAtM(viewMatrix, 0, 0, 0, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        //combine projection and camera view
        Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        int err;
        GLES31.glViewport(0, 0, width, height);
        //use this shader
        GLES31.glUseProgram(mProgram);
        //apply projection and camera view
        vPMatrixHandle = GLES31.glGetUniformLocation(mProgram, "uMVPMatrix");
        GLES31.glUniformMatrix4fv(vPMatrixHandle, 1, false, vPMatrix, 0);
        //vertices to position
        positionHandle = GLES31.glGetAttribLocation(mProgram, "vPosition");
        GLES31.glEnableVertexAttribArray(positionHandle);
        GLES31.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES31.GL_FLOAT, false, 0, vertexBuffer); //TODO: stride necessary?
        // apply texture coords
        mTexCoordHandle = GLES31.glGetAttribLocation(mProgram, "a_texCoord");
        GLES31.glEnableVertexAttribArray(mTexCoordHandle);
        GLES31.glVertexAttribPointer(mTexCoordHandle, 2, GLES31.GL_FLOAT, false, 0, uvBuffer);
        if ((err = GLES31.glGetError()) != GLES31.GL_NO_ERROR) {
            Log.e("GL ERROR", "1->" + GLU.gluErrorString(err));
        }
        //GLES31.glEnable(GLES31.GL_TEXTURE_2D);
        GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textureName[0]);
        GLES31.glCopyTexSubImage2D(GLES31.GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);

        if ((err = GLES31.glGetError()) != GLES31.GL_NO_ERROR) {
            Log.e("GL ERROR", "2->" + GLU.gluErrorString(err));
        }

        // tell gl to use this active texture as sampler
        mSamplerHandle = GLES31.glGetUniformLocation(mProgram, "s_texture");
        GLES31.glUniform1i(mSamplerHandle, 0);

        if ((err = GLES31.glGetError()) != GLES31.GL_NO_ERROR) {
            Log.e("GL ERROR", "3->" + GLU.gluErrorString(err));
        }

        //draw triangles
        //6 => drawOrder.length
        GLES31.glDrawElements(GLES31.GL_TRIANGLES, 6, GLES31.GL_SHORT, drawListBuffer);

        if ((err = GLES31.glGetError()) != GLES31.GL_NO_ERROR) {
            Log.e("GL ERROR", "4->" + GLU.gluErrorString(err));
        }

        //disable attrip arrays
        GLES31.glDisableVertexAttribArray(positionHandle);
        GLES31.glDisableVertexAttribArray(mTexCoordHandle);
    }

    private void setUpShader() {
        int vertexShader = loadShader(GLES31.GL_VERTEX_SHADER, vertShader);
        int fragmentShader = loadShader(GLES31.GL_FRAGMENT_SHADER, fragShader);
        mProgram = GLES31.glCreateProgram();             // create empty OpenGL ES Program
        GLES31.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
        GLES31.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
        GLES31.glLinkProgram(mProgram);                  // creates OpenGL ES program executables
        String vS = GLES31.glGetShaderInfoLog(vertexShader);
        String fS = GLES31.glGetShaderInfoLog(fragmentShader);
        if (!vS.isEmpty() || !fS.isEmpty()) {
            Log.e("setUpShader", "shader program failed");
        }
    }

    static int loadShader(int type, String shaderCode) {
        int shader = GLES31.glCreateShader(type);
        GLES31.glShaderSource(shader, shaderCode);
        GLES31.glCompileShader(shader);
        return shader;
    }

    private void initVertices() {
        //see width (1080) and height (1440) of flir texture
        float squareCoords[] = {
                0f, 0f, 0.0f,   // top left
                0f, 1440f, 0.0f,   // bottom left
                1080f, 1440f, 0.0f,   // bottom right
                1080f, 0f, 0.0f}; // top right
        short drawOrder[] = {0, 1, 2, 0, 2, 3}; // order to draw vertices
        vertexCount = squareCoords.length / COORDS_PER_VERTEX;
        // (# of coordinate values * 4 bytes per float)
        ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);
        // (# of coordinate values * 2 bytes per short)
        ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);
    }

    private void initTextureCoords() {
        // (# of coordinate values * 4 bytes per float)
        float[] uvs = new float[]{
                1.0f, 1.0f,
                0.0f, 0.0f,
                0.0f, 1.0f,
                1.0f, 0.0f
        };
        ByteBuffer bb3 = ByteBuffer.allocateDirect(uvs.length * 4);
        bb3.order(ByteOrder.nativeOrder());
        uvBuffer = bb3.asFloatBuffer();
        uvBuffer.put(uvs);
        uvBuffer.position(0);
    }

    private void initTexture() {
        textureName = new int[1];
        GLES31.glGenTextures(1, textureName, 0);
        GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textureName[0]);
        // params if texture needs to scale up/down
        GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MIN_FILTER, GLES31.GL_NEAREST);
        GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_NEAREST);
        //GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_S, GLES31.GL_CLAMP_TO_EDGE);
        GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA, width, height, 0, GLES31.GL_RGBA, GLES31.GL_UNSIGNED_BYTE, null);

    }
}
...