OpenGLES 2.0으로 실시간 필터가 적용된 카메라 미리보기를 구현하였습니다.
그리고 찍힌 사진에도 동일하게 필터가 적용될 수 있도록
찍힌 Bitmap을 받아 OpenGLES로 rendering 해주는 renderBitmap() 메서드를 만들었는데요.
코드는 다음과 같습니다.
public Bitmap renderBitmap(Bitmap bitmap) {
synchronized (this) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] textureName = new int[1];
GLES20.glGenTextures(textureName.length, textureName, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureName[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
int[] renderBuffer = new int[3];
GLES20.glGenRenderbuffers(renderBuffer.length, renderBuffer, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renderBuffer[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_RGBA, width, height); // specified the render buffer to be color render buffer.
int[] frameBuffer = new int[1];
GLES20.glGenFramebuffers(frameBuffer.length, frameBuffer, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textureName[0], 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_RENDERBUFFER, renderBuffer[0]);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, renderBuffer[1]);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_STENCIL_ATTACHMENT, GLES20.GL_RENDERBUFFER, renderBuffer[2]);
GLES20.glUseProgram(mProgramImage);
int positionHandle = GLES20.glGetAttribLocation(mProgramImage, "vPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer);
int texCoordHandle = GLES20.glGetAttribLocation(mProgramImage, "vTexCoord");
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, mTexCoordBuffer);
int bright = GLES20.glGetUniformLocation(mProgramImage, "brightness");
int contr = GLES20.glGetUniformLocation(mProgramImage, "contrast");
int satur = GLES20.glGetUniformLocation(mProgramImage, "saturation");
int tintr = GLES20.glGetUniformLocation(mProgramImage, "tintR");
int tintg = GLES20.glGetUniformLocation(mProgramImage, "tintG");
int tintb = GLES20.glGetUniformLocation(mProgramImage, "tintB");
GLES20.glUniform1f(bright, mCameraParams.mBrightness / 200.0f);
GLES20.glUniform1f(contr, mCameraParams.mContrast / 200.0f);
GLES20.glUniform1f(satur, (mCameraParams.mSaturation + 100) / 100.0f);
GLES20.glUniform1f(tintr, mCameraParams.mTintR / 200.0f); // * (1 - 0.213f)
GLES20.glUniform1f(tintg, mCameraParams.mTintG / 200.0f); // * (1 - 0.715f)
GLES20.glUniform1f(tintb, mCameraParams.mTintB / 200.0f); // * (1 - 0.072f)
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureName[0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mDrawOrder.length, GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(texCoordHandle);
Log.i("CheckLog", "Status of Framebuffer : " + GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)); // 36053 is complete state number.
IntBuffer intBuffer = IntBuffer.allocate(width * height);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, intBuffer);
int[] intArrayO = intBuffer.array();
int[] intArrayR = new int[width * height];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
intArrayR[(height - i - 1) * width + j] = intArrayO[i * width + j];
}
}
Bitmap pBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
pBitmap.copyPixelsFromBuffer(intBuffer.wrap(intArrayR));
return pBitmap;
}
}
FrameBuffer가 제대로 형성이 안되었는지
Log 체크하는 부분에서는 계속 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 값만 반환하고
return 되는 bitmap도 사이즈는 정상이나 검은색으로 비어있습니다.
위 renderBitmap() 메서드가 호출될 때는 카메라 미리보기의 OpenGLES 처리와 꼬이지 않도록
onDrawFrame() 메서드 내부의 OpenGLES 코드들에 대해 동기화 처리는 했구요.
잘 아시는 분들께 도대체 뭐가 잘못된 것인지 도움좀 구합니다.ㅠ
아무리 OpenGL 경험이 거의 없는 상태로 만들었다지만...
몇일째 구글링을 해봐도 답을 얻을 수 없는게
뭔가 크게 잘못생각하고 만든게 아닐까 하는 걱정이 드네요...