美文网首页
OpenGL进阶之构建通用框架

OpenGL进阶之构建通用框架

作者: 溫順尚早 | 来源:发表于2019-03-08 16:22 被阅读0次


    一、关于GLSurfaceView

    • 编写OpenGL ES应用的起始点是从类GLSurfaceView开始,GLSurfaceView是OpenGL ES API的核心类,在Android上使用Opengl操作的对象是GLSurfaceView,这是一个继承自View的扩展。

    • 实现两个必须调用的方法

      • setRenderer():设置renderer

      • setEGLContextClientVersion():设置OpenGL版本号

        public class DefaultSurfaceView extends BaseSurfaceView {
        
            public DefaultSurfaceView(Context context) {
                super(context);
                setEGLContextClientVersion();
                setRenderer();
            }
        
            @Override
            protected void setRenderer() {
                DefaultRenderer defaultRenderer = new DefaultRenderer(mContext);
                defaultRenderer.setBitmap(getBitmap());
                setRenderer(defaultRenderer);
                setRenderMode(RENDERMODE_WHEN_DIRTY);
            }
        
            @Override
            protected void setEGLContextClientVersion() {
                setEGLContextClientVersion(2);
            }
        }
        

    二、关于GLSurfaceView.Renderer

    • 在Android上使用GLSurfaceView来显示并完成图片的渲染,实现渲染需要实现GLSurfaceView.Render接口

    • 三个接口方法描述:

      • onDrawFrame(GL10 gl) ,该方法按照一定的刷新频率反复执行,定义实际的绘图操作;

      • onSurfaceCreated(GL10 gl, EGLConfig config),在创建SurfaceView的时候执行,主要用来设置一些绘制时不常变化的参数,比如:背景色,是否打开 z-buffer等。

      • onSurfaceChanged(GL10 gl, int width, int height),该方法在窗口重绘的时候执行,如果设备支持屏幕横向和纵向切换,这个方法将发生在横向<->纵向互换时。此时可以重新设置绘制的纵横比率。;

    public class DefaultRenderer extends BaseRenderer {
      @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            super.onSurfaceCreated(gl, config);
            // 创建可以绘制纹理的基类Filter
            defaultFilter = new DefaultFilter(mContext);
            videoBuffer = CoordinateHelper.calculateDefaultBuffer();
            // 创建纹理ID,如果频繁调用onDrawFrame(),则不可将ID创建放在其中,不及时销毁会爆内存的;
            defaultTextureId = ShaderHelper.createTexture(GLES20.GL_TEXTURE_2D, bitmap);
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            super.onSurfaceChanged(gl, width, height);
            calculateVertexMatrix();
        }
    
        private void calculateVertexMatrix() {
            Matrix.setIdentityM(vertexMatrix, 0);
            float bmpRatio = bitmap.getWidth() * 1.0f / bitmap.getHeight();
            float viewRatio = mViewWidth * 1.0f / mViewHeight;
            if (viewRatio < bmpRatio){
                // 齐高放大宽
                float scale = bmpRatio / viewRatio;
                Matrix.scaleM(vertexMatrix, 0, scale, -1.0f, 1.0f);
            }else{
                // 齐宽放大高
                float scale = viewRatio / bmpRatio;
                Matrix.scaleM(vertexMatrix, 0, 1.0f, -scale, 1.0f);
            }
        }
    
        @Override
        public void onDrawFrame(GL10 gl) {
            super.onDrawFrame(gl);
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            GLES20.glViewport(0, 0, mViewWidth, mViewHeight);
            if (defaultFilter != null) {
                defaultFilter.onDraw(vertexMatrix, ShaderHelper.IDENTITY_MATRIX,
                        defaultTextureId, videoBuffer);
            }
        }
    }
    

    三、关于Filter框架

    • 在项目中开发为了复用性更强,都要封装自己的通用框架,每个元素图层就是一个Filter。onDrawFrame中可能同时绘制很多元素,如背景、带美颜和滤镜效果的图片、前景、水印等,每一个元素对应一个Filter,方便图层初始和管理。

    • Fitler 封装的绘制步骤:

      • 构造函数,创建Shader程序,获取句柄。可以有子类传入着色器,也可使用默认着色器;

      public AbstractFilter(Context context) {
        mContext = context;
        mProgramHandle = createProgram(context);
        checkProgram();
      }
      
      public AbstractFilter(Context context, int programHandle) {
        mContext = context;
        mProgramHandle = programHandle;
        checkProgram();
      }
      
      public AbstractFilter(Context context, @RawRes int vertexSourceRawId, @RawRes int fragmentSourceRawId) {
          mContext = context;
          mProgramHandle = ShaderHelper.createProgram(context, vertexSourceRawId, fragmentSourceRawId);
          checkProgram();
      }
      
      public AbstractFilter(Context context, String vertexSource, String fragmentSource) {
          mContext = context;
          mProgramHandle = ShaderHelper.createProgram(vertexSource, fragmentSource);
          checkProgram();
      }
      
      protected int createProgram(Context context) {
          return ShaderHelper.createProgram(context,
                  R.raw.base_vertex_shader, R.raw.base_fragment_filter);
      }
      
      • 获取着色器中定义的属性句柄;

      protected void getGLSLValues() {
          aPositionLoc = GLES20.glGetAttribLocation(mProgramHandle, "aPosition");
          aTextureCoordLoc = GLES20.glGetAttribLocation(mProgramHandle, "aTextureCoord");
          uMVPMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle, "uMVPMatrix");
          uTexMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle, "uTexMatrix");
          mTextureLoc = GLES20.glGetUniformLocation(mProgramHandle, "sourceImage");
      }
      
      • 使用Program

      protected void useProgram() {
          GLES20.glUseProgram(mProgramHandle);
      }
      
      • 将句柄和纹理进行绑定

      protected void bindTexture(int textureId){
          GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
          GLES20.glBindTexture(getTextureTarget(), textureId);
          GLES20.glUniform1i(mTextureLoc, 0);
      }
      
      • 为属性句柄赋值

      protected void bindGLSLValues(float[] mvpMatrix, FloatBuffer vertexBuffer, int coordsPerVertex, int vertexStride,
                                  float[] texMatrix, FloatBuffer texBuffer, int texStride) {
          GLES20.glUniformMatrix4fv(uMVPMatrixLoc, 1, false, mvpMatrix, 0);
          GLES20.glUniformMatrix4fv(uTexMatrixLoc, 1, false, texMatrix, 0);
          GLES20.glEnableVertexAttribArray(aPositionLoc);
          GLES20.glVertexAttribPointer(aPositionLoc, coordsPerVertex,
                  GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
          GLES20.glEnableVertexAttribArray(aTextureCoordLoc);
          GLES20.glVertexAttribPointer(aTextureCoordLoc, 2,
                  GLES20.GL_FLOAT, false, texStride, texBuffer);
      }
      
      • 绘制

      protected void drawArrays(int firstVertex, int vertexCount) {
          GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, firstVertex, vertexCount);
      }
      
      • 将属性句柄解绑释放

      protected void unbindGLSLValues() {
          GLES20.glDisableVertexAttribArray(aPositionLoc);
          GLES20.glDisableVertexAttribArray(aTextureCoordLoc);
      }
      
      • 将纹理句柄解绑

      protected void unbindTexture() {
          GLES20.glBindTexture(getTextureTarget(), 0);
      }
      
      • 释放Program

      protected void disuseProgram() {
          GLES20.glUseProgram(0);
      }
      
      public void releaseProgram() {
          GLES20.glDeleteProgram(mProgramHandle);
          mProgramHandle = -1;
      }
      

    相关文章

      网友评论

          本文标题:OpenGL进阶之构建通用框架

          本文链接:https://www.haomeiwen.com/subject/fvorpqtx.html