Simplify GPU image filter implementation

Signed-off-by: Leo Ma <begeekmyfriend@gmail.com>
camera2
Leo Ma 9 years ago
parent 44d9e47484
commit 81696ed5ad

@ -11,17 +11,17 @@ import com.seu.magicfilter.utils.OpenGlUtils;
import android.opengl.GLES20;
public class MagicBaseGroupFilter extends GPUImageFilter{
protected static int[] frameBuffers = null;
protected static int[] frameBufferTextures = null;
public class MagicBaseGroupFilter extends GPUImageFilter {
private static int[] frameBuffers = null;
private static int[] frameBufferTextures = null;
private int frameWidth = -1;
private int frameHeight = -1;
protected List<GPUImageFilter> filters;
public MagicBaseGroupFilter(List<GPUImageFilter> filters){
this.filters = filters;
public MagicBaseGroupFilter(List<GPUImageFilter> filters) {
this.filters = filters;
}
@Override
public void onDestroy() {
for (GPUImageFilter filter : filters) {
@ -29,14 +29,14 @@ public class MagicBaseGroupFilter extends GPUImageFilter{
}
destroyFramebuffers();
}
@Override
public void init() {
for (GPUImageFilter filter : filters) {
filter.init();
}
}
@Override
public void onInputSizeChanged(final int width, final int height) {
super.onInputSizeChanged(width, height);
@ -44,41 +44,41 @@ public class MagicBaseGroupFilter extends GPUImageFilter{
for (int i = 0; i < size; i++) {
filters.get(i).onInputSizeChanged(width, height);
}
if(frameBuffers != null && (frameWidth != width || frameHeight != height || frameBuffers.length != size-1)){
if (frameBuffers != null && (frameWidth != width || frameHeight != height || frameBuffers.length != size - 1)) {
destroyFramebuffers();
frameWidth = width;
frameHeight = height;
}
if (frameBuffers == null) {
frameBuffers = new int[size-1];
frameBufferTextures = new int[size-1];
frameBuffers = new int[size - 1];
frameBufferTextures = new int[size - 1];
for (int i = 0; i < size-1; i++) {
for (int i = 0; i < size - 1; i++) {
GLES20.glGenFramebuffers(1, frameBuffers, i);
GLES20.glGenTextures(1, frameBufferTextures, i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameBufferTextures[i]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffers[i]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, frameBufferTextures[i], 0);
GLES20.GL_TEXTURE_2D, frameBufferTextures[i], 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
}
}
@Override
public int onDrawFrame(final int textureId, final FloatBuffer cubeBuffer,
final FloatBuffer textureBuffer) {
@ -91,29 +91,29 @@ public class MagicBaseGroupFilter extends GPUImageFilter{
GPUImageFilter filter = filters.get(i);
boolean isNotLast = i < size - 1;
if (isNotLast) {
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffers[i]);
GLES20.glClearColor(0, 0, 0, 0);
filter.onDrawFrame(previousTexture, mGLCubeBuffer, mGLTextureBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
previousTexture = frameBufferTextures[i];
}else{
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
filter.onDrawFrame(previousTexture, cubeBuffer, textureBuffer);
} else {
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
filter.onDrawFrame(previousTexture, cubeBuffer, textureBuffer);
}
}
return OpenGlUtils.ON_DRAWN;
return OpenGlUtils.ON_DRAWN;
}
@Override
public int onDrawFrame(final int textureId) {
if (frameBuffers == null || frameBufferTextures == null) {
public int onDrawFrame(int textureId, boolean needFbo) {
if (frameBuffers == null || frameBufferTextures == null) {
return OpenGlUtils.NOT_INIT;
}
int size = filters.size();
int size = filters.size();
int previousTexture = textureId;
for (int i = 0; i < size; i++) {
GPUImageFilter filter = filters.get(i);
GPUImageFilter filter = filters.get(i);
boolean isNotLast = i < size - 1;
if (isNotLast) {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffers[i]);
@ -121,13 +121,13 @@ public class MagicBaseGroupFilter extends GPUImageFilter{
filter.onDrawFrame(previousTexture, mGLCubeBuffer, mGLTextureBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
previousTexture = frameBufferTextures[i];
}else{
filter.onDrawFrame(previousTexture, mGLCubeBuffer, mGLTextureBuffer);
} else {
filter.onDrawFrame(previousTexture, mGLCubeBuffer, mGLTextureBuffer);
}
}
return OpenGlUtils.ON_DRAWN;
return OpenGlUtils.ON_DRAWN;
}
private void destroyFramebuffers() {
if (frameBufferTextures != null) {
GLES20.glDeleteTextures(frameBufferTextures.length, frameBufferTextures, 0);
@ -138,8 +138,8 @@ public class MagicBaseGroupFilter extends GPUImageFilter{
frameBuffers = null;
}
}
public int getSize(){
return filters.size();
public int getSize() {
return filters.size();
}
}

@ -9,40 +9,40 @@ import com.seu.magicfilter.utils.OpenGlUtils;
public class MagicLookupFilter extends GPUImageFilter {
public static final String LOOKUP_FRAGMENT_SHADER = ""+
"varying highp vec2 textureCoordinate;\n" +
" \n" +
" uniform sampler2D inputImageTexture;\n" +
" uniform sampler2D inputImageTexture2; // lookup texture\n" +
" \n" +
" void main()\n" +
" {\n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" +
" \n" +
" mediump float blueColor = textureColor.b * 63.0;\n" +
" \n" +
" mediump vec2 quad1;\n" +
" quad1.y = floor(floor(blueColor) / 8.0);\n" +
" quad1.x = floor(blueColor) - (quad1.y * 8.0);\n" +
" \n" +
" mediump vec2 quad2;\n" +
" quad2.y = floor(ceil(blueColor) / 8.0);\n" +
" quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n" +
" \n" +
" highp vec2 texPos1;\n" +
" texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n" +
" texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n" +
" \n" +
" highp vec2 texPos2;\n" +
" texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n" +
" texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n" +
" \n" +
" lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1);\n" +
" lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2);\n" +
" \n" +
" lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n" +
" gl_FragColor = vec4(newColor.rgb, textureColor.w);\n" +
" }";
public static final String LOOKUP_FRAGMENT_SHADER = "" +
"varying highp vec2 textureCoordinate;\n" +
" \n" +
" uniform sampler2D inputImageTexture;\n" +
" uniform sampler2D inputImageTexture2; // lookup texture\n" +
" \n" +
" void main()\n" +
" {\n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" +
" \n" +
" mediump float blueColor = textureColor.b * 63.0;\n" +
" \n" +
" mediump vec2 quad1;\n" +
" quad1.y = floor(floor(blueColor) / 8.0);\n" +
" quad1.x = floor(blueColor) - (quad1.y * 8.0);\n" +
" \n" +
" mediump vec2 quad2;\n" +
" quad2.y = floor(ceil(blueColor) / 8.0);\n" +
" quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n" +
" \n" +
" highp vec2 texPos1;\n" +
" texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n" +
" texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n" +
" \n" +
" highp vec2 texPos2;\n" +
" texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n" +
" texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n" +
" \n" +
" lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1);\n" +
" lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2);\n" +
" \n" +
" lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n" +
" gl_FragColor = vec4(newColor.rgb, textureColor.w);\n" +
" }";
protected String table;
@ -50,44 +50,44 @@ public class MagicLookupFilter extends GPUImageFilter {
super(MagicFilterType.LOCKUP, LOOKUP_FRAGMENT_SHADER);
this.table = table;
}
public int mLookupTextureUniform;
public int mLookupSourceTexture = OpenGlUtils.NO_TEXTURE;
protected void onInit(){
super.onInit();
mLookupTextureUniform = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2");
private int mLookupTextureUniform;
private int mLookupSourceTexture = OpenGlUtils.NO_TEXTURE;
protected void onInit() {
super.onInit();
mLookupTextureUniform = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2");
}
protected void onInitialized(){
super.onInitialized();
runOnDraw(new Runnable(){
public void run(){
mLookupSourceTexture = OpenGlUtils.loadTexture(MagicFilterFactory.getCurrentContext(), table);
}
});
protected void onInitialized() {
super.onInitialized();
runOnDraw(new Runnable() {
public void run() {
mLookupSourceTexture = OpenGlUtils.loadTexture(MagicFilterFactory.getCurrentContext(), table);
}
});
}
protected void onDestroy() {
super.onDestroy();
int[] texture = new int[]{mLookupSourceTexture};
GLES20.glDeleteTextures(1, texture, 0);
mLookupSourceTexture = -1;
}
protected void onDrawArraysAfter() {
if (mLookupSourceTexture != -1) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
}
}
protected void onDrawArraysPre() {
if (mLookupSourceTexture != -1) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mLookupSourceTexture);
GLES20.glUniform1i(mLookupTextureUniform, 3);
}
}
protected void onDestroy(){
super.onDestroy();
int[] texture = new int[]{mLookupSourceTexture};
GLES20.glDeleteTextures(1, texture, 0);
mLookupSourceTexture = -1;
}
protected void onDrawArraysAfter(){
if (mLookupSourceTexture != -1){
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
}
}
protected void onDrawArraysPre(){
if (mLookupSourceTexture != -1){
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mLookupSourceTexture);
GLES20.glUniform1i(mLookupTextureUniform, 3);
}
}
}

@ -222,87 +222,12 @@ public class GPUImageFilter {
return OpenGlUtils.ON_DRAWN;
}
public int onDrawFrame(int textureId) {
public int onDrawFrame(int textureId, boolean needFbo) {
if (!mIsInitialized) {
return OpenGlUtils.NOT_INIT;
}
GLES20.glUseProgram(mGLProgId);
runPendingOnDrawTasks();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLCubeId[0]);
GLES20.glEnableVertexAttribArray(mGLPositionIndex);
GLES20.glVertexAttribPointer(mGLPositionIndex, 2, GLES20.GL_FLOAT, false, 4 * 2, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLTextureId[0]);
GLES20.glEnableVertexAttribArray(mGLTextureCoordinateIndex);
GLES20.glVertexAttribPointer(mGLTextureCoordinateIndex, 2, GLES20.GL_FLOAT, false, 4 * 2, 0);
GLES20.glUniformMatrix4fv(mGLTextureTransformIndex, 1, false, mGLTextureTransformMatrix, 0);
if (textureId != OpenGlUtils.NO_TEXTURE) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
GLES20.glUniform1i(mGLInputImageTextureIndex, 0);
}
onDrawArraysPre();
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
onDrawArraysAfter();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glDisableVertexAttribArray(mGLPositionIndex);
GLES20.glDisableVertexAttribArray(mGLTextureCoordinateIndex);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return OpenGlUtils.ON_DRAWN;
}
public int onDrawFrameOES(int textureId) {
if (!mIsInitialized) {
return OpenGlUtils.NOT_INIT;
}
GLES20.glUseProgram(mGLProgId);
runPendingOnDrawTasks();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLCubeId[0]);
GLES20.glEnableVertexAttribArray(mGLPositionIndex);
GLES20.glVertexAttribPointer(mGLPositionIndex, 2, GLES20.GL_FLOAT, false, 4 * 2, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLTextureId[0]);
GLES20.glEnableVertexAttribArray(mGLTextureCoordinateIndex);
GLES20.glVertexAttribPointer(mGLTextureCoordinateIndex, 2, GLES20.GL_FLOAT, false, 4 * 2, 0);
GLES20.glUniformMatrix4fv(mGLTextureTransformIndex, 1, false, mGLTextureTransformMatrix, 0);
if (textureId != OpenGlUtils.NO_TEXTURE) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
GLES20.glUniform1i(mGLInputImageTextureIndex, 0);
}
onDrawArraysPre();
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
onDrawArraysAfter();
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
GLES20.glDisableVertexAttribArray(mGLPositionIndex);
GLES20.glDisableVertexAttribArray(mGLTextureCoordinateIndex);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return OpenGlUtils.ON_DRAWN;
}
public int onDrawToTexture(int textureId) {
if (!mIsInitialized) {
return OpenGlUtils.NOT_INIT;
}
if (mGLFboId == null) {
if (needFbo && mGLFboId == null) {
return OpenGlUtils.NO_TEXTURE;
}
@ -326,13 +251,16 @@ public class GPUImageFilter {
}
onDrawArraysPre();
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mGLFboId[0]);
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
GLES20.glReadPixels(0, 0, mInputWidth, mInputHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mGLFboBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
if (needFbo) {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mGLFboId[0]);
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
GLES20.glReadPixels(0, 0, mInputWidth, mInputHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mGLFboBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
onDrawArraysAfter();
@ -343,14 +271,15 @@ public class GPUImageFilter {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return mGLFboTextureId[0];
return needFbo ? mGLFboTextureId[0] : OpenGlUtils.ON_DRAWN;
}
public int onDrawToTextureOES(int textureId) {
public int onDrawFrameOES(int textureId, boolean needFbo) {
if (!mIsInitialized) {
return OpenGlUtils.NOT_INIT;
}
if (mGLFboId == null) {
if (needFbo && mGLFboId == null) {
return OpenGlUtils.NO_TEXTURE;
}
@ -374,13 +303,16 @@ public class GPUImageFilter {
}
onDrawArraysPre();
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mGLFboId[0]);
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
GLES20.glReadPixels(0, 0, mInputWidth, mInputHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mGLFboBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
if (needFbo) {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mGLFboId[0]);
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
GLES20.glReadPixels(0, 0, mInputWidth, mInputHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mGLFboBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
onDrawArraysAfter();
@ -391,10 +323,11 @@ public class GPUImageFilter {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return mGLFboTextureId[0];
return needFbo ? mGLFboTextureId[0] : OpenGlUtils.ON_DRAWN;
}
protected void onDrawArraysPre() {}
protected void onDrawArraysAfter() {}
protected void runPendingOnDrawTasks() {

@ -109,8 +109,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
surfaceTexture.getTransformMatrix(mtx);
magicFilter.setTextureTransformMatrix(mtx);
magicFilter.onDrawFrameOES(mTextureId);
magicFilter.onDrawToTextureOES(mTextureId);
magicFilter.onDrawFrameOES(mTextureId, true);
mGLIntBufferCache.add(magicFilter.getGlFboBuffer());
synchronized (writeLock) {
writeLock.notifyAll();

Loading…
Cancel
Save