2016-10-01 64 views
1

我试图在Android OS上通过OpenGL ES 2.0更改图像的颜色。这是我的代码。如何在Android上使用OpenGL ES 2.0渲染大尺寸图像

德州类

public class Tex { 
    private FloatBuffer mVertexBuffer; 
    private ShortBuffer mDrawListBuffter; 
    protected FloatBuffer mUvBuffer; 
    protected static float mUvs[]; 
    private final float[] mMtrxView = new float[16]; 
    public static final String vs_Image 
      = "uniform mat4 uMVPMatrix;" 
      + "attribute vec4 vPosition;" 
      + "attribute vec2 a_texCoord;" 
      + "varying vec2 v_texCoord;" 
      + "void main() {" 
      + "  gl_Position = uMVPMatrix * vPosition;" 
      + "  v_texCoord = a_texCoord;" 
      + "}"; 
    public static final String fs_Image 
      = "precision mediump float;" 
      + "varying vec2 v_texCoord;" 
      + "uniform sampler2D s_texture;" 
      + "void main() {" 
      + "  vec4 tex = texture2D(s_texture, v_texCoord);" 
      + "  float tintR = 0.6;" 
      + "  float tintG = 0.3;" 
      + "  float tintB = 0.0;" 
      + "  float tr = clamp(tex.r * (1.0 - tintR) + tintR, 0.0, 1.0);" 
      + "  float tg = clamp(tex.g * (1.0 - tintG) + tintG, 0.0, 1.0);" 
      + "  float tb = clamp(tex.b * (1.0 - tintB) + tintB, 0.0, 1.0);" 
      + "  gl_FragColor = vec4(tr, tg, tb, tex.a);" 
      + "}"; 
    float mSquareCoords[] = { 
      -1.0f, 1.0f, 0.0f, 
      -1.0f, -1.0f, 0.0f, 
      1.0f, -1.0f, 0.0f, 
      1.0f, 1.0f, 0.0f 
    }; 
    private short mDrawOrder[] = {0, 1, 2, 0, 2, 3}; 
    private final int mProgram; 
    int[] mTextureNames; 
    MainGLRenderer mMainGLRenderer; 
    int mWidth, mHeight; 
    Bitmap mBitmap; 

    public Tex(MainGLRenderer mainGLRenderer, Bitmap bitmap) { 
     mMainGLRenderer = mainGLRenderer; 

     ByteBuffer bb = ByteBuffer.allocateDirect(mSquareCoords.length * 4); 
     bb.order(ByteOrder.nativeOrder()); 
     mVertexBuffer = bb.asFloatBuffer(); 
     mVertexBuffer.put(mSquareCoords); 
     mVertexBuffer.position(0); 

     ByteBuffer dlb = ByteBuffer.allocateDirect(mDrawOrder.length * 2); 
     dlb.order(ByteOrder.nativeOrder()); 
     mDrawListBuffter = dlb.asShortBuffer(); 
     mDrawListBuffter.put(mDrawOrder); 
     mDrawListBuffter.position(0); 

     mUvs = new float[] { 
       0.0f, 0.0f, 
       0.0f, 1.0f, 
       1.0f, 1.0f, 
       1.0f, 0.0f, 
     }; 
     ByteBuffer bbUvs = ByteBuffer.allocateDirect(mUvs.length * 4); 
     bbUvs.order(ByteOrder.nativeOrder()); 
     mUvBuffer = bbUvs.asFloatBuffer(); 
     mUvBuffer.put(mUvs); 
     mUvBuffer.position(0); 

     int vertexShader = mMainGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vs_Image); 
     int fragmentShader = mMainGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fs_Image); 

     mProgram = GLES20.glCreateProgram(); 
     GLES20.glAttachShader(mProgram, vertexShader); 
     GLES20.glAttachShader(mProgram, fragmentShader); 
     GLES20.glLinkProgram(mProgram); 

     initTexture(bitmap); 
    } 

    private void initTexture(Bitmap bitmap) { 
     mWidth = bitmap.getWidth(); 
     mHeight = bitmap.getHeight(); 
     GLES20.glViewport(0, 0, mWidth, mHeight); 

     mTextureNames = new int[1]; 
     GLES20.glGenTextures(1, mTextureNames, 0); 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureNames[0]); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

     draw(); 
    } 

    public void draw() { 
     GLES20.glUseProgram(mProgram); 
     Matrix.setIdentityM(mMtrxView, 0); 

     int positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); 
     GLES20.glEnableVertexAttribArray(positionHandle); 
     GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer); 

     int texCoordLoc = GLES20.glGetAttribLocation(mProgram, "a_texCoord"); 
     GLES20.glEnableVertexAttribArray(texCoordLoc); 
     GLES20.glVertexAttribPointer(texCoordLoc, 2, GLES20.GL_FLOAT, false, 0, mUvBuffer); 

     int mtrxHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
     GLES20.glUniformMatrix4fv(mtrxHandle, 1, false, mMtrxView, 0); 

     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureNames[0]); 
     GLES20.glDrawElements(GLES20.GL_TRIANGLES, mDrawOrder.length, GLES20.GL_UNSIGNED_SHORT, mDrawListBuffter); 

     GLES20.glDisableVertexAttribArray(positionHandle); 
     GLES20.glDisableVertexAttribArray(texCoordLoc); 

     mBitmap = getBitmap(); 
    } 

    public Bitmap getBitmap() {  
     IntBuffer intBuffer = IntBuffer.allocate(mWidth * mHeight); 
     GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, intBuffer); 

     int[] intArrayO = intBuffer.array(); 
     int[] intArrayR = new int[mWidth * mHeight]; 
     for (int i = 0; i < mHeight; i++) { 
      for (int j = 0; j < mWidth; j++) { 
       intArrayR[(mHeight - i - 1) * mWidth + j] = intArrayO[i * mWidth + j]; 
      } 
     } 

     Bitmap postBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); 
     postBitmap.copyPixelsFromBuffer(intBuffer.wrap(intArrayR)); 

     return postBitmap; 
    } 

    public Bitmap getmBitmap() { 
     return mBitmap; 
    } 
} 

在MainActivity

public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.btn_run: 
       Bitmap bitmap = mGLSurfaceView.mRenderer.mTex.getmBitmap(); 
       mImageView.setImageBitmap(bitmap); 

       String storageDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + Environment.DIRECTORY_DCIM + "/Camera"; 
       File dir = new File(storageDir); 
       if (!dir.exists()) dir.mkdir(); 

       String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
       String path = storageDir + "/IMG_" + timeStamp + ".jpg"; 
       File file = new File(path); 

       ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
       bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); 
       byte[] byteData = stream.toByteArray(); 

       try { 
        FileOutputStream fos = new FileOutputStream(file); 
        fos.write(byteData); 
        fos.flush(); 
        fos.close(); 
       } 
       catch (Exception e) { 

       } 

       Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
       Uri uri = Uri.parse("file://" + path); 
       intent.setData(uri); 
       sendBroadcast(intent); 
       break; 
     } 
    } 

正如你可以看到上面的代码中的onClick方法,onClick()方法调用getmBitmap()方法,然后我可以得到渲染图像。它适用于小分辨率图像。但是,渲染图像对于像3840 x 2160这样的高分辨率是不正常的。在渲染图像中,小尺寸和颜色变化的原始图像位于左下角。其余区域以黑色填充。我不知道什么是错的。我必须为高分辨率图像设置一些东西吗?我需要建议。请帮忙。

回答

0

你在渲染什么?

您正在上传较大的纹理,但如果您没有更改要渲染的帧缓冲区的大小,那么您将无法获得更大的图像。

+0

如何更改framebuffer的大小?我必须使用什么方法来做到这一点?请给我更多的提示。我是OpenGL ES编程的初学者。 –

+0

对于帧缓冲区对象(屏幕外渲染),您需要在分配存储区中附加较大的纹理或渲染缓冲区附件。对于屏幕上的渲染,我怀疑你运气不好 - 你不可能得到比设备的物理显示更大的窗口表面。 – solidpixel

相关问题