1.初始化纹理方法

public static int loadTexture(final Bitmap img, final int usedTexId, int i) {
        if(img == null)
            return NO_TEXTURE;
        
//        ByteBuffer img_buffer = ByteBuffer.allocate(img.getByteCount());
//        img.copyPixelsToBuffer(img_buffer);
        ByteBuffer pbo_point = null;
        int textures[] = new int[1];
        if (usedTexId == NO_TEXTURE) {
            GLES30.glGenTextures(1, textures, 0);
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
            GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
                    GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
            GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
                    GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
            GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
                    GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
            GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
                    GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
            GLES30.glGenBuffers(1, pbo);
            GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbo.get(0));
            GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER,width*height*4, null, GLES30.GL_DYNAMIC_READ);
            GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);
             GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, img, 0);
        } 
        else {
              GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, usedTexId);
//              GLUtils.texSubImage2D(GLES30.GL_TEXTURE_2D, 0, 0, 0, img);
              textures[0] = usedTexId;
        }
        return textures[0];
    }

2.初始化PBO

public static int loadFramebuffer(int texture, int width,int height){
    
        IntBuffer framebuffer = IntBuffer.allocate(1);
        IntBuffer depthRenderbuffer = IntBuffer.allocate(1);
        IntBuffer max = IntBuffer.allocate(10);
        int temp = 0;
        GLES30.glGetIntegerv(GLES30.GL_MAX_RENDERBUFFER_SIZE, max);
        temp = max.get(0);
        if (temp <= width && temp <= height)
        {
            return -1;
        }
        GLES30.glGenFramebuffers(1, framebuffer);
        GLES30.glGenRenderbuffers(1, depthRenderbuffer);
        GLES30.glBindRenderbuffer(GLES30.GL_RENDERBUFFER, depthRenderbuffer.get(0));
        GLES30.glRenderbufferStorage(GLES30.GL_RENDERBUFFER, GLES30.GL_RGBA, width, height);
        
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer.get(0));
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, texture, 0);
        GLES30.glFramebufferRenderbuffer(GLES30.GL_FRAMEBUFFER,GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_RENDERBUFFER, depthRenderbuffer.get(0));
        
        int status = 0;
        status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
        if (status == GLES30.GL_FRAMEBUFFER_COMPLETE){
            Log.d(TAG,"frame buffer init ok!!!!!!!");
            GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
            GLES30.glDeleteRenderbuffers(1, depthRenderbuffer);
            GLES30.glDeleteFramebuffers(1, framebuffer);
            return framebuffer.get();
        }
        Log.d(TAG,"frame buffer init file!!!!!!!");
        return -1;
        
    }

3.surface creat 初始化

public void onSurfaceCreated ( GL10 glUnused, EGLConfig config )
   {
      String vShaderStr =
              "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" +
            "}";           
 
      String fShaderStr =
          "precision highp float;                          \n"
         + "varying highp vec2 textureCoordinate;\n"
         +  "uniform sampler2D inputImageTexture;\n"
         + "void main()                                  \n"
         + "{                                            \n"
         + "  gl_FragColor = texture2D(inputImageTexture, textureCoordinate);    \n"
         + "}                                            \n";
 
      int vertexShader;
      int fragmentShader;
      int programObject;
      int[] linked = new int[1];
 
      // Load the vertex/fragment shaders
      vertexShader = LoadShader ( GLES30.GL_VERTEX_SHADER, vShaderStr );
      fragmentShader = LoadShader ( GLES30.GL_FRAGMENT_SHADER, fShaderStr );
 
      // Create the program object
      programObject = GLES30.glCreateProgram();
 
      if ( programObject == 0 )
      {
         return;
      }
 
      GLES30.glAttachShader ( programObject, vertexShader );
      GLES30.glAttachShader ( programObject, fragmentShader );
 
      // Bind vPosition to attribute 0
      GLES30.glBindAttribLocation ( programObject, 0, "vPosition" );
 
      // Link the program
      GLES30.glLinkProgram ( programObject );
 
      // Check the link status
      GLES30.glGetProgramiv ( programObject, GLES30.GL_LINK_STATUS, linked, 0 );
 
      if ( linked[0] == 0 )
      {
         Log.e ( TAG, vShaderStr );
         Log.e ( TAG, fShaderStr );
         Log.e ( TAG, "Error linking program:" );
         Log.e ( TAG, GLES30.glGetProgramInfoLog ( programObject ) );
         GLES30.glDeleteProgram ( programObject );
         return;
      }
 
      // Store the program object
      mProgramObject = programObject;
       mGLAttribPosition = GLES30.glGetAttribLocation(programObject, "position");
       mGLUniformTexture = GLES30.glGetUniformLocation(programObject, "inputImageTexture");
       mGLAttribTextureCoordinate = GLES30.glGetAttribLocation(programObject,
               "inputTextureCoordinate");
       Log.d(TAG,"id = " + color_id + "mGLUniformTexture= " + mGLUniformTexture);
     // GLES30.glClearColor ( 1.0f, 1.0f, 1.0f, 0.0f );
 
   }

4.最后使用pbo 画出来

public void onDrawFrame ( GL10 glUnused )
   {
      index++;
      mTextureId = loadTexture(bitmap,mTextureId,0);
      // Set the viewport
          GLES30.glViewport ( 0, 0, width ,height);
 
      // Clear the color buffer
      GLES30.glClearColor(0.0f,0.0f,0.0f,0.0f);
      GLES30.glClear ( GLES30.GL_COLOR_BUFFER_BIT );
      // Use the program object
      GLES30.glUseProgram ( mProgramObject );
 
 
      mVertices.position(0);
      GLES30.glVertexAttribPointer ( mGLAttribPosition, 3, GLES30.GL_FLOAT, false, 0, mVertices );
      GLES30.glEnableVertexAttribArray ( mGLAttribPosition );
      
      mGLTextureBuffer.position(0);
      GLES30.glVertexAttribPointer ( mGLAttribTextureCoordinate, 2, GLES30.GL_FLOAT, false, 0, mGLTextureBuffer );
      GLES30.glEnableVertexAttribArray ( mGLAttribTextureCoordinate );
     
//      
      if (mTextureId >= 0)
      {
          //loadFramebuffer(mTextureId,width,height);
          GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
          GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId);
          GLES30.glUniform1i(mGLUniformTexture, 0);
          
      }
      GLES30.glDrawArrays ( GLES30.GL_TRIANGLE_STRIP, 0, 4 );
       Log.d("jni", "刷新时间");
      return;
   }

总结:虽然使用一个PBO但是效果改变不是很明显,因为单个PBO传输还是需要等待的,假如使用2个pbo,这样错开接收就会使效率大大提高,请看下篇使用2个PBO速度慢的问题。


轻口味
16.8k 声望3.7k 粉丝

移动端十年老人,主要做IM、音视频、AI方向,目前在做鸿蒙化适配,欢迎这些方向的同学交流:wodekouwei