Android opengl glReadPixelsの遅い問題を解決する1

7821 ワード

Android opengl glReadPixelsの遅い問題を解決する
androidのgpuとcpuメモリは分離されているため、データのコピーの過程で非常に遅くなり、ネット上の資料は比較的少ない.以下は私がこの問題を解決したお菓子で、PBOコードを使って以下のようにします.
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;
" + "attribute vec4 inputTextureCoordinate;
" + "
" + "varying vec2 textureCoordinate;
" + "
" + "void main()
" + "{
" + " gl_Position = position;
" + " textureCoordinate = inputTextureCoordinate.xy;
" + "}"; String fShaderStr = "precision highp float;
" + "varying highp vec2 textureCoordinate;
" + "uniform sampler2D inputImageTexture;
" + "void main()
" + "{
" + " gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
" + "}
"; 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 。