离屏渲染(FBO)

正常情况下我们有一个顶点着色器一个片段着色器,其实这样我们的正常操作都是没问题的。但是我们有时候需要像先放大在设置纹理再缩小这样操作,那么一个顶点着色器和一个片段着色器就达不到我们的需求了,运用这个最多的就是相机的各自美颜效果,如果有美白,放大,高斯三个操作想在美白和放大之后加高斯就不用完全重新写,只需要在美白放大之后加上一层高斯的滤镜就能完成效果。

FBO

那么他的实现原理是什么呢。首先它叫做帧缓冲那么他缓冲的就是一帧的信息,比如颜色和深度。我们可以添加一个纹理附件,那么我们所有的操作就会渲染到这个纹理上面,就像上面说的美白效果,原图片就会变成一个美白后的图片的纹理,然后就可以再对这个纹理进行操作。
先来创建FBO

 int[] texture = new int[2];
    int[] fbo = new int[2];
    private int createFbo(int width, int height) {


        GLES20.glGenFramebuffers(2, fbo, 0);
        GLES20.glGenTextures(2, texture, 0);

        for (int i = 0; i < 2;i++){
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[i]);
            GLES20.glTexImage2D(
                    GLES20.GL_TEXTURE_2D,
                    0,
                    GLES20.GL_RGB,
                    width,
                    height,
                    0,
                    GLES20.GL_RGB,
                    GLES20.GL_UNSIGNED_BYTE,
                    null
            );
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);

            // Bind the framebuffer
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo[i]);
            GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_RGB, width, height);
            // Specify texture as color attachment
            GLES20.glFramebufferTexture2D(
                    GLES20.GL_FRAMEBUFFER,
                    GLES20.GL_COLOR_ATTACHMENT0,
                    GLES20.GL_TEXTURE_2D,
                    texture[i],
                    0
            );
            // Check for framebuffer complete
            int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
            if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
                Log.e("opengl", "Failed to create framebuffer!!!");
            }
        }
        return 0;
    }

这样我们就创建了两个FBO,并且把两个纹理绑定到了FBO上。
然后就可以在渲染的时候制定输出的FBO,当参数传的是0的时候就是输出到屏幕上

           GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo[0]);
            directDriver.draw(0,mMVPMatrix, mTextureMatrix, maxLerp, minLerp,textureId);
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo[1]);
            directDriver.draw(1,mMVPMatrix, mTextureMatrix, maxLerp, minLerp,texture[0]);
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); // 0代表屏幕
            directDriver.draw(2,mMVPMatrix, mTextureMatrix, maxLerp, minLerp,texture[1]);

在draw的时候我们就可以根据不同的FBO来加载选择不同的program来处理。

你可能感兴趣的:(离屏渲染(FBO))