├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── dming │ │ └── testopengl │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── animation.mp4 │ ├── java │ │ └── com │ │ │ └── dming │ │ │ └── testopengl │ │ │ ├── CameraActivity.java │ │ │ ├── CameraRenderer.java │ │ │ ├── CameraSize.java │ │ │ ├── LauncherActivity.java │ │ │ ├── filter │ │ │ ├── BaseFilter.java │ │ │ ├── BlurFilter.java │ │ │ ├── BurrFilter.java │ │ │ ├── CutApartFilter.java │ │ │ ├── EdgeFilter.java │ │ │ ├── IShader.java │ │ │ ├── LuminanceFilter.java │ │ │ ├── MultipleFilter.java │ │ │ ├── ShowGifFilter.java │ │ │ ├── ShowMovieFilter.java │ │ │ └── SoulFilter.java │ │ │ └── utils │ │ │ ├── DLog.java │ │ │ ├── FGLUtils.java │ │ │ ├── GLInterpolator.java │ │ │ └── ShaderHelper.java │ └── res │ │ ├── drawable-xxhdpi │ │ ├── t_gl.jpg │ │ └── test_gl.jpg │ │ ├── layout │ │ ├── act_test.xml │ │ └── activity_main.xml │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── raw │ │ ├── animation_frg.glsl │ │ ├── blur_frg.glsl │ │ ├── burr_frg.glsl │ │ ├── edge_frg.glsl │ │ ├── luminance_frg.glsl │ │ ├── multiple_frg.glsl │ │ ├── n_blur_frg.glsl │ │ ├── process_frg.glsl │ │ ├── process_ver.glsl │ │ ├── sharpen_frg.glsl │ │ └── soul_frg.glsl │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── dming │ └── testopengl │ └── ExampleUnitTest.java ├── build.gradle ├── giflib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── dming │ │ └── giflib │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── mogutou.gif │ │ └── mogutou2.gif │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── GLUtils.cpp │ │ ├── GLUtils.h │ │ ├── GifJni.cpp │ │ ├── GifPlayer.cpp │ │ ├── GifPlayer.h │ │ ├── PthreadSleep.cpp │ │ ├── PthreadSleep.h │ │ ├── SyncTime.cpp │ │ ├── SyncTime.h │ │ ├── giflib │ │ │ ├── config.h │ │ │ ├── dgif_lib.c │ │ │ ├── egif_lib.c │ │ │ ├── gif_err.c │ │ │ ├── gif_font.c │ │ │ ├── gif_hash.c │ │ │ ├── gif_hash.h │ │ │ ├── gif_lib.h │ │ │ ├── gif_lib_private.h │ │ │ ├── gifalloc.c │ │ │ ├── openbsd-reallocarray.c │ │ │ └── quantize.c │ │ └── log.h │ ├── java │ │ └── com │ │ │ └── dming │ │ │ └── testgif │ │ │ ├── DLog.java │ │ │ ├── EglHelper.java │ │ │ ├── FGLUtils.java │ │ │ ├── GifFilter.java │ │ │ ├── GifPlayer.java │ │ │ └── ShaderHelper.java │ └── res │ │ └── raw │ │ ├── gif_process_frg.glsl │ │ └── gif_process_ver.glsl │ └── test │ └── java │ └── com │ └── dming │ └── giflib │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── mdSrc ├── demo.gif └── nine_gl.apk └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | .idea/encodings.xml 12 | .idea/vcs.xml 13 | giflib/.cxx/ 14 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.dming.testopengl" 7 | minSdkVersion 17 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | // compileOptions { 20 | // targetCompatibility JavaVersion.VERSION_1_8 21 | // } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation 'com.android.support:appcompat-v7:28.0.0' 27 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 30 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 31 | implementation project(path: ':giflib') 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/dming/testopengl/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.dming.testopengl", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/assets/animation.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/assets/animation.mp4 -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/CameraActivity.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.graphics.Point; 7 | import android.graphics.SurfaceTexture; 8 | import android.hardware.Camera; 9 | import android.opengl.GLSurfaceView; 10 | import android.os.Bundle; 11 | import android.support.annotation.Nullable; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.view.GestureDetector; 14 | import android.view.MotionEvent; 15 | import android.view.Surface; 16 | import android.view.View; 17 | import android.view.WindowManager; 18 | 19 | import com.dming.testopengl.utils.DLog; 20 | 21 | import java.io.IOException; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | import java.util.SortedSet; 25 | import java.util.TreeSet; 26 | 27 | public class CameraActivity extends AppCompatActivity implements CameraRenderer.GLRunnable { 28 | 29 | private GLSurfaceView mGLSurfaceView; 30 | private CameraRenderer mCameraRenderer; 31 | // 32 | private int mCameraId; 33 | private Camera mCamera; 34 | private Camera.Parameters mCameraParameters; 35 | private final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo(); 36 | private static final int INVALID_CAMERA_ID = -1; 37 | protected final List mPreviewSizes = new ArrayList<>(); 38 | private SurfaceTexture mSurfaceTexture; 39 | private float[] mCameraMatrix = new float[16]; 40 | 41 | @SuppressLint("ClickableViewAccessibility") 42 | @Override 43 | protected void onCreate(@Nullable Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_main); 46 | mGLSurfaceView = findViewById(R.id.gl_show); 47 | mGLSurfaceView.setEGLContextClientVersion(2); 48 | mCameraRenderer = new CameraRenderer(mGLSurfaceView, this); 49 | mGLSurfaceView.setRenderer(mCameraRenderer); 50 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 51 | final GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() { 52 | 53 | @Override 54 | public boolean onSingleTapUp(MotionEvent e) { 55 | int w = mGLSurfaceView.getWidth(); 56 | int h = mGLSurfaceView.getHeight(); 57 | int w_3 = w / 3; 58 | int h_3 = h / 3; 59 | int x = (int) ((e.getX() - 5) / w_3); 60 | int y = (int) ((e.getY() - 5) / h_3); 61 | int index = x + y * 3; 62 | mCameraRenderer.chooseOneShaderOfNine(index); 63 | return true; 64 | } 65 | }; 66 | final GestureDetector gestureDetector = new GestureDetector(this, listener); 67 | mGLSurfaceView.setOnTouchListener(new View.OnTouchListener() { 68 | @Override 69 | public boolean onTouch(View v, MotionEvent event) { 70 | gestureDetector.onTouchEvent(event); 71 | return true; 72 | } 73 | }); 74 | } 75 | 76 | @Override 77 | public void onSurfaceCreated(final int textureId) { 78 | mSurfaceTexture = new SurfaceTexture(textureId); 79 | mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { 80 | @Override 81 | public void onFrameAvailable(SurfaceTexture surfaceTexture) { 82 | mGLSurfaceView.queueEvent(new Runnable() { 83 | @Override 84 | public void run() { 85 | if (mSurfaceTexture != null) { 86 | mSurfaceTexture.updateTexImage(); 87 | mSurfaceTexture.getTransformMatrix(mCameraMatrix); 88 | mCameraRenderer.setTexMatrix(mCameraMatrix); 89 | mGLSurfaceView.requestRender(); 90 | } 91 | } 92 | }); 93 | } 94 | }); 95 | chooseCamera(); 96 | openCamera(); 97 | if (isCameraOpened()) { 98 | try { 99 | mCamera.setPreviewTexture(mSurfaceTexture); 100 | } catch (IOException e) { 101 | } 102 | setCameraDisplayOrientation(this, mCamera, mCameraInfo); 103 | adjustCameraParameters(); 104 | } 105 | } 106 | 107 | @Override 108 | public void onSurfaceChanged(final int width, final int height) { 109 | mCameraRenderer.onSurfaceCreated(width, height); 110 | } 111 | 112 | @Override 113 | protected void onResume() { 114 | super.onResume(); 115 | mGLSurfaceView.onResume(); 116 | } 117 | 118 | @Override 119 | protected void onPause() { 120 | mGLSurfaceView.queueEvent(new Runnable() { 121 | @Override 122 | public void run() { 123 | if (isCameraOpened()) { 124 | mCamera.stopPreview(); 125 | } 126 | releaseCamera(); 127 | mCameraRenderer.onDestroy(); 128 | if (mSurfaceTexture != null) { 129 | mSurfaceTexture.release(); 130 | mSurfaceTexture = null; 131 | } 132 | } 133 | }); 134 | mGLSurfaceView.onPause(); 135 | super.onPause(); 136 | } 137 | 138 | private void chooseCamera() { 139 | for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) { 140 | Camera.getCameraInfo(i, mCameraInfo); 141 | if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { 142 | mCameraId = i; 143 | return; 144 | } 145 | } 146 | mCameraId = INVALID_CAMERA_ID; 147 | } 148 | 149 | private void openCamera() { 150 | if (mCamera != null) { 151 | releaseCamera(); 152 | } 153 | mCamera = Camera.open(mCameraId); 154 | mCameraParameters = mCamera.getParameters(); 155 | mPreviewSizes.clear(); 156 | for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) { 157 | // DLog.i("size->" + size.width + " " + size.height); 158 | mPreviewSizes.add(new CameraSize(size.width, size.height)); 159 | } 160 | 161 | } 162 | 163 | private void adjustCameraParameters() { 164 | CameraSize suitableSize = getDealCameraSize(mCameraInfo.orientation); 165 | final CameraSize size = suitableSize.getSrcSize(); 166 | mCameraParameters.setPreviewSize(size.getWidth(), size.getHeight()); 167 | setAutoFocusInternal(true); 168 | mCamera.setParameters(mCameraParameters); 169 | mCamera.startPreview(); 170 | } 171 | 172 | private void releaseCamera() { 173 | if (mCamera != null) { 174 | mCamera.release(); 175 | mCamera = null; 176 | } 177 | } 178 | 179 | public void setCameraDisplayOrientation(Activity activity, Camera camera, Camera.CameraInfo info) { 180 | int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 181 | int degrees = 0; 182 | switch (rotation) { 183 | case Surface.ROTATION_0: 184 | degrees = 0; 185 | break; 186 | case Surface.ROTATION_90: 187 | degrees = 90; 188 | break; 189 | case Surface.ROTATION_180: 190 | degrees = 180; 191 | break; 192 | case Surface.ROTATION_270: 193 | degrees = 270; 194 | break; 195 | } 196 | int result; 197 | if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 198 | result = (info.orientation + degrees) % 360; 199 | result = (360 - result) % 360; // compensate the mirror 200 | } else { 201 | // back-facing 202 | result = (info.orientation - degrees + 360) % 360; 203 | } 204 | DLog.i("result: " + result); 205 | camera.setDisplayOrientation(result); 206 | } 207 | 208 | private boolean setAutoFocusInternal(boolean autoFocus) { 209 | if (isCameraOpened()) { 210 | final List modes = mCameraParameters.getSupportedFocusModes(); 211 | if (autoFocus && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 212 | mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 213 | } else if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) { 214 | mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED); 215 | } else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) { 216 | mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY); 217 | } else { 218 | mCameraParameters.setFocusMode(modes.get(0)); 219 | } 220 | return true; 221 | } else { 222 | return false; 223 | } 224 | } 225 | 226 | boolean isCameraOpened() { 227 | return mCamera != null; 228 | } 229 | 230 | protected CameraSize getDealCameraSize(int rotation) { 231 | SortedSet greaterThanView = new TreeSet<>(); 232 | List lessThanView = new ArrayList<>(); 233 | WindowManager wm = (WindowManager) this 234 | .getSystemService(Context.WINDOW_SERVICE); 235 | Point point = new Point(); 236 | if (wm == null) { 237 | point.x = 1080; 238 | point.y = 1920; 239 | } else { 240 | wm.getDefaultDisplay().getSize(point); 241 | } 242 | if (point.x > 700 && point.x < 800) { 243 | point.x = 720; 244 | point.y = 1280; 245 | } else if (point.x > 1000 && point.x < 1100) { 246 | point.x = 1080; 247 | point.y = 1920; 248 | } 249 | final int viewWidth = point.x; 250 | final int viewHeight = point.y; 251 | DLog.i("viewWidth> " + viewWidth + " viewHeight>> " + viewHeight); 252 | for (CameraSize size : mPreviewSizes) { 253 | if (rotation == 90 || rotation == 270) { // width > height normal 254 | if (size.getWidth() >= viewHeight && size.getHeight() >= viewWidth) { 255 | greaterThanView.add(new CameraSize(size.getHeight(), size.getWidth(), size)); 256 | } else { 257 | lessThanView.add(new CameraSize(size.getHeight(), size.getWidth(), size)); 258 | } 259 | } else { // width < height normal 0 180 260 | if (size.getWidth() >= viewWidth && size.getHeight() >= viewHeight) { 261 | greaterThanView.add(new CameraSize(size.getWidth(), size.getHeight(), size)); 262 | } else { 263 | lessThanView.add(new CameraSize(size.getWidth(), size.getHeight(), size)); 264 | } 265 | } 266 | } 267 | CameraSize cSize = null; 268 | if (greaterThanView.size() > 0) { 269 | cSize = greaterThanView.first(); 270 | } else { 271 | int diffMinValue = Integer.MAX_VALUE; 272 | for (CameraSize size : lessThanView) { 273 | int diffWidth = Math.abs(viewWidth - size.getWidth()); 274 | int diffHeight = Math.abs(viewHeight - size.getHeight()); 275 | int diffValue = diffWidth + diffHeight; 276 | if (diffValue < diffMinValue) { // 找出差值最小的数 277 | diffMinValue = diffValue; 278 | cSize = size; 279 | } 280 | } 281 | if (cSize == null) { 282 | cSize = lessThanView.get(0); 283 | } 284 | } 285 | DLog.i("suitableSize>" + cSize.toString()); 286 | return cSize; 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/CameraRenderer.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLES20; 6 | import android.opengl.GLSurfaceView; 7 | import android.opengl.Matrix; 8 | 9 | import com.dming.testopengl.filter.BlurFilter; 10 | import com.dming.testopengl.filter.BurrFilter; 11 | import com.dming.testopengl.filter.CutApartFilter; 12 | import com.dming.testopengl.filter.EdgeFilter; 13 | import com.dming.testopengl.filter.IShader; 14 | import com.dming.testopengl.filter.LuminanceFilter; 15 | import com.dming.testopengl.filter.MultipleFilter; 16 | import com.dming.testopengl.filter.ShowGifFilter; 17 | import com.dming.testopengl.filter.ShowMovieFilter; 18 | import com.dming.testopengl.filter.SoulFilter; 19 | import com.dming.testopengl.utils.DLog; 20 | 21 | import javax.microedition.khronos.egl.EGLConfig; 22 | import javax.microedition.khronos.opengles.GL10; 23 | 24 | public class CameraRenderer implements GLSurfaceView.Renderer { 25 | 26 | private Context mContext; 27 | 28 | private int mTextureId; 29 | private int mWidth, mHeight; 30 | 31 | // private LineGraph mLineGraph; 32 | private CutApartFilter mCutApartFilter; 33 | private LuminanceFilter mLuminanceFilter; 34 | private BlurFilter mBlurFilter; 35 | private ShowGifFilter mShowGifFilter; 36 | private BurrFilter mBurrFilter; 37 | private ShowMovieFilter mShowMovieFilter; 38 | private MultipleFilter mMultipleFilter; 39 | private SoulFilter mSoulFilter; 40 | private EdgeFilter mEdgeFilter; 41 | // 42 | private IShader mCurShader; 43 | // 44 | private GLRunnable mGLRunnable; 45 | private GLSurfaceView mGLSurfaceView; 46 | // 47 | private int mPageIndex = -1; 48 | private float[] mTexMatrix = new float[16]; 49 | 50 | 51 | CameraRenderer(GLSurfaceView glSurfaceView, GLRunnable glRunnable) { 52 | this.mContext = glSurfaceView.getContext(); 53 | this.mGLSurfaceView = glSurfaceView; 54 | this.mGLRunnable = glRunnable; 55 | Matrix.setIdentityM(mTexMatrix, 0); 56 | } 57 | 58 | @Override 59 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 60 | DLog.i("onSurfaceCreated"); 61 | GLES20.glClearColor(0f, 0f, 0f, 1f); 62 | mTextureId = createOESTexture(); 63 | mGLRunnable.onSurfaceCreated(mTextureId); 64 | // mLineGraph = new LineGraph(mContext); 65 | mCutApartFilter = new CutApartFilter(mContext); 66 | mLuminanceFilter = new LuminanceFilter(mContext); 67 | mBlurFilter = new BlurFilter(mContext); 68 | mShowGifFilter = new ShowGifFilter(mContext); 69 | mBurrFilter = new BurrFilter(mContext); 70 | mShowMovieFilter = new ShowMovieFilter(mGLSurfaceView); 71 | mMultipleFilter = new MultipleFilter(mContext); 72 | mSoulFilter = new SoulFilter(mContext); 73 | mEdgeFilter = new EdgeFilter(mContext); 74 | 75 | chooseOneShaderOfNine(mPageIndex); 76 | } 77 | 78 | public void onSurfaceCreated(int width, int height) { 79 | if (this.mWidth != width || this.mHeight != height) { 80 | this.mWidth = width; 81 | this.mHeight = height; 82 | int w = mWidth / 3; 83 | int h = mHeight / 3; 84 | // mLineGraph.onChange(mWidth, mHeight); 85 | mCutApartFilter.onChange(w, h); 86 | mLuminanceFilter.onChange(w, h); 87 | mBlurFilter.onChange(w, h); 88 | mShowGifFilter.onChange(w, h); 89 | mBurrFilter.onChange(w, h); 90 | mShowMovieFilter.onChange(w, h); 91 | mMultipleFilter.onChange(w, h); 92 | mSoulFilter.onChange(w, h); 93 | mEdgeFilter.onChange(w, h); 94 | } 95 | } 96 | 97 | @Override 98 | public void onSurfaceChanged(GL10 gl, int width, int height) { 99 | DLog.i("onSurfaceChanged"); 100 | GLES20.glViewport(0, 0, width, height); 101 | mGLRunnable.onSurfaceChanged(width, height); 102 | } 103 | 104 | @Override 105 | public void onDrawFrame(GL10 gl) { 106 | if (mWidth == 0 || mHeight == 0) { 107 | return; 108 | } 109 | long time = System.currentTimeMillis(); 110 | int w = mWidth / 3; 111 | int h = mHeight / 3; 112 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 113 | // mLineGraph.onDraw(mTextureId, 0, 0, mWidth, mHeight); 114 | mCutApartFilter.onDraw(mTextureId, mTexMatrix, 0, h * 2, w, h + 1); 115 | mLuminanceFilter.onDraw(mTextureId, mTexMatrix, w, 0, w, h); 116 | mBurrFilter.onDraw(mTextureId, mTexMatrix, 0, h, w, h); 117 | mShowGifFilter.onDraw(mTextureId, mTexMatrix, w * 2, h * 2, w, h + 1); 118 | mBlurFilter.onDraw(mTextureId, mTexMatrix, w, h * 2, w, h + 1); 119 | mShowMovieFilter.onDraw(mTextureId, mTexMatrix, w * 2, h, w + 1, h); 120 | mMultipleFilter.onDraw(mTextureId, mTexMatrix, w, h, w, h); 121 | mSoulFilter.onDraw(mTextureId, mTexMatrix, 0, 0, w, h); 122 | mEdgeFilter.onDraw(mTextureId, mTexMatrix, w * 2, 0, w + 1, h); 123 | // 124 | if (mCurShader != null) { 125 | mCurShader.onDraw(mTextureId, mTexMatrix, 0, 0, mWidth, mHeight); 126 | } 127 | // DLog.i("time: " + (System.currentTimeMillis() - time)); 128 | int err = GLES20.glGetError(); 129 | if (err != 0) { 130 | DLog.i("gl err: " + err); 131 | } 132 | } 133 | 134 | public void setTexMatrix(float[] mTexMatrix) { 135 | this.mTexMatrix = mTexMatrix; 136 | } 137 | 138 | private static int createOESTexture() { 139 | int[] tex = new int[1]; 140 | //生成一个纹理 141 | GLES20.glGenTextures(1, tex, 0); 142 | //将此纹理绑定到外部纹理上 143 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); 144 | //设置纹理过滤参数 145 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 146 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 147 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 148 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 149 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 150 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 151 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 152 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 153 | //解除纹理绑定 154 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 155 | return tex[0]; 156 | } 157 | 158 | public void chooseOneShaderOfNine(int index) { 159 | if (mCurShader == null) { 160 | mPageIndex = index; 161 | if (index == 0) { 162 | mCurShader = mCutApartFilter; 163 | } else if (index == 1) { 164 | mCurShader = mBlurFilter; 165 | } else if (index == 2) { 166 | mCurShader = mShowGifFilter; 167 | } else if (index == 3) { 168 | mCurShader = mBurrFilter; 169 | } else if (index == 4) { 170 | mCurShader = mMultipleFilter; 171 | } else if (index == 5) { 172 | mCurShader = mShowMovieFilter; 173 | mShowMovieFilter.playVolume(); 174 | } else if (index == 6) { 175 | mCurShader = mSoulFilter; 176 | } else if (index == 7) { 177 | mCurShader = mLuminanceFilter; 178 | } else if (index == 8) { 179 | mCurShader = mEdgeFilter; 180 | } 181 | } else { 182 | if (mPageIndex == 5) { 183 | mShowMovieFilter.stopVolume(); 184 | } 185 | mPageIndex = -1; 186 | mCurShader = null; 187 | } 188 | } 189 | 190 | public void onDestroy() { 191 | this.mWidth = 0; 192 | this.mHeight = 0; 193 | this.mCurShader = null; 194 | // if (mLineGraph != null) { 195 | // mLineGraph.onDestroy(); 196 | // mLineGraph = null; 197 | // } 198 | if (mCutApartFilter != null) { 199 | mCutApartFilter.onDestroy(); 200 | mCutApartFilter = null; 201 | } 202 | if (mLuminanceFilter != null) { 203 | mLuminanceFilter.onDestroy(); 204 | mLuminanceFilter = null; 205 | } 206 | if (mBlurFilter != null) { 207 | mBlurFilter.onDestroy(); 208 | mBlurFilter = null; 209 | } 210 | if (mShowGifFilter != null) { 211 | mShowGifFilter.onDestroy(); 212 | mShowGifFilter = null; 213 | } 214 | if (mBurrFilter != null) { 215 | mBurrFilter.onDestroy(); 216 | mBurrFilter = null; 217 | } 218 | if (mShowMovieFilter != null) { 219 | mShowMovieFilter.onDestroy(); 220 | mShowMovieFilter = null; 221 | } 222 | if (mMultipleFilter != null) { 223 | mMultipleFilter.onDestroy(); 224 | mMultipleFilter = null; 225 | } 226 | if (mSoulFilter != null) { 227 | mSoulFilter.onDestroy(); 228 | mSoulFilter = null; 229 | } 230 | if (mEdgeFilter != null) { 231 | mEdgeFilter.onDestroy(); 232 | mEdgeFilter = null; 233 | } 234 | GLES20.glDeleteTextures(1, new int[]{mTextureId}, 0); 235 | } 236 | 237 | 238 | public interface GLRunnable { 239 | void onSurfaceCreated(int textureId); 240 | 241 | void onSurfaceChanged(int width, int height); 242 | } 243 | 244 | } 245 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/CameraSize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.dming.testopengl; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | /** 22 | * Immutable class for describing width and height dimensions in pixels. 23 | */ 24 | public class CameraSize implements Comparable { 25 | 26 | private final int mWidth; 27 | private final int mHeight; 28 | private CameraSize mSrcSize; 29 | 30 | public CameraSize(int size1, int size2) { 31 | this.mWidth = size1; 32 | this.mHeight = size2; 33 | } 34 | 35 | 36 | public CameraSize(int size1, int size2, CameraSize mSrcSize) { 37 | this.mWidth = size1; 38 | this.mHeight = size2; 39 | this.mSrcSize = mSrcSize; 40 | } 41 | 42 | 43 | public int getWidth() { 44 | return mWidth; 45 | } 46 | 47 | public int getHeight() { 48 | return mHeight; 49 | } 50 | 51 | public CameraSize getSrcSize() { 52 | return mSrcSize; 53 | } 54 | 55 | @Override 56 | public boolean equals(Object o) { 57 | if (o == null) { 58 | return false; 59 | } 60 | if (this == o) { 61 | return true; 62 | } 63 | if (o instanceof CameraSize) { 64 | CameraSize size = (CameraSize) o; 65 | return mWidth == size.mWidth && mHeight == size.mHeight; 66 | } 67 | return false; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return mWidth + "x" + mHeight; 73 | } 74 | 75 | @Override 76 | public int hashCode() { 77 | // assuming most sizes are <2^16, doing a rotate will give us perfect hashing 78 | return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2))); 79 | } 80 | 81 | @Override 82 | public int compareTo(@NonNull CameraSize another) { 83 | return mWidth * mHeight - another.mWidth * another.mHeight; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/LauncherActivity.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl; 2 | 3 | import android.Manifest; 4 | import android.annotation.SuppressLint; 5 | import android.content.Intent; 6 | import android.content.pm.PackageManager; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.support.annotation.NonNull; 10 | import android.support.annotation.Nullable; 11 | import android.support.v7.app.AppCompatActivity; 12 | 13 | public class LauncherActivity extends AppCompatActivity { 14 | 15 | 16 | @SuppressLint("ClickableViewAccessibility") 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 21 | getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()) 22 | != PackageManager.PERMISSION_GRANTED) { 23 | requestPermissions(new String[]{Manifest.permission.CAMERA}, 666); 24 | } else { 25 | startActivity(new Intent(this, CameraActivity.class)); 26 | finish(); 27 | } 28 | } 29 | 30 | @Override 31 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 32 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 33 | if (requestCode == 666 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 34 | startActivity(new Intent(this, CameraActivity.class)); 35 | finish(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/BaseFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLES20; 6 | import android.opengl.Matrix; 7 | 8 | import com.dming.testopengl.R; 9 | import com.dming.testopengl.utils.ShaderHelper; 10 | 11 | import java.nio.FloatBuffer; 12 | import java.nio.ShortBuffer; 13 | 14 | public class BaseFilter implements IShader { 15 | 16 | protected ShortBuffer mIndexSB; 17 | protected FloatBuffer mTexFB; 18 | protected FloatBuffer mPosFB; 19 | protected static final short[] VERTEX_INDEX = { 20 | 0, 1, 3, 21 | 2, 3, 1 22 | }; 23 | protected static final float[] VERTEX_POS = { 24 | -1, 1.0f, 0f, 25 | -1, -1.0f, 0f, 26 | 1, -1.0f, 0f, 27 | 1, 1.0f, 0f, 28 | }; 29 | public static final float[] TEX_VERTEX = { 30 | 0, 1, 31 | 0, 0, 32 | 1, 0, 33 | 1, 1, 34 | }; 35 | 36 | protected int mProgram; 37 | protected int mPosition; 38 | protected int mTextureCoordinate; 39 | protected int mImageOESTexture; 40 | protected int uMvpMatrix; 41 | protected int uTexMatrix; 42 | protected float[] mMvpMatrix = new float[16]; 43 | protected Context mContext; 44 | 45 | public BaseFilter(Context context, int resFrgId) { 46 | this.mContext = context; 47 | mIndexSB = ShaderHelper.arrayToShortBuffer(VERTEX_INDEX); 48 | mPosFB = ShaderHelper.arrayToFloatBuffer(VERTEX_POS); 49 | mTexFB = ShaderHelper.arrayToFloatBuffer(TEX_VERTEX); 50 | mProgram = ShaderHelper.loadProgram(context, R.raw.process_ver, resFrgId); 51 | mPosition = GLES20.glGetAttribLocation(mProgram, "inputPosition"); 52 | mTextureCoordinate = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate"); 53 | mImageOESTexture = GLES20.glGetUniformLocation(mProgram, "inputImageOESTexture"); 54 | uMvpMatrix = GLES20.glGetUniformLocation(mProgram, "inputMatrix"); 55 | uTexMatrix = GLES20.glGetUniformLocation(mProgram, "uTexMatrix"); 56 | Matrix.setIdentityM(mMvpMatrix, 0); 57 | } 58 | 59 | @Override 60 | public void onChange(int width, int height) { 61 | } 62 | 63 | @Override 64 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 65 | onDraw(textureId, mMvpMatrix, texMatrix, x, y, width, height); 66 | } 67 | 68 | @Override 69 | public void onDraw(int textureId, float[] verMatrix, float[] texMatrix, int x, int y, int width, int height) { 70 | GLES20.glUseProgram(mProgram); 71 | GLES20.glEnableVertexAttribArray(mPosition); 72 | GLES20.glVertexAttribPointer(mPosition, 3, 73 | GLES20.GL_FLOAT, false, 0, mPosFB); 74 | GLES20.glEnableVertexAttribArray(mTextureCoordinate); 75 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2, 76 | GLES20.GL_FLOAT, false, 0, mTexFB); 77 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, verMatrix, 0); 78 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0); 79 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 80 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); 81 | GLES20.glUniform1i(mImageOESTexture, 0); 82 | GLES20.glViewport(x, y, width, height); 83 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 84 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 85 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 86 | GLES20.glDisableVertexAttribArray(mPosition); 87 | GLES20.glDisableVertexAttribArray(mTextureCoordinate); 88 | GLES20.glUseProgram(0); 89 | } 90 | 91 | @Override 92 | public void onDestroy() { 93 | GLES20.glDeleteProgram(mProgram); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/BlurFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLES20; 6 | import android.opengl.Matrix; 7 | 8 | import com.dming.testopengl.R; 9 | import com.dming.testopengl.utils.DLog; 10 | import com.dming.testopengl.utils.ShaderHelper; 11 | 12 | import java.nio.FloatBuffer; 13 | import java.nio.ShortBuffer; 14 | 15 | public class BlurFilter implements IShader { 16 | 17 | private final ShortBuffer mIndexSB; 18 | private FloatBuffer mTexFB; 19 | private final FloatBuffer mFBOTexFB; 20 | private FloatBuffer mPosFB; 21 | private FloatBuffer mFBOPosFB; 22 | private static final short[] VERTEX_INDEX = { 23 | 0, 1, 3, 24 | 2, 3, 1 25 | }; 26 | private int mOESProgram; 27 | private int mOESImageTexture; 28 | private int mOESPosition; 29 | private int mOESTextureCoordinate; 30 | private int mOESIsVertical; 31 | private int mOESMatrix; 32 | private int uTexOESMatrix; 33 | // FBO 34 | private int[] mFrameBuffer = new int[1]; 35 | private int[] mFrameBufferTexture = new int[1]; 36 | private boolean isCreateFBO = false; 37 | private int mFBOWidth; 38 | private int mFBOHeight; 39 | // 40 | private float[] mIdentityMatrix = new float[4 * 4]; 41 | // 42 | private int mProgram; 43 | private int mImageTexture; 44 | private int mPosition; 45 | private int mTextureCoordinate; 46 | private int mIsVertical; 47 | private int mMatrix; 48 | private int uTexMatrix; 49 | 50 | public BlurFilter(Context context) { 51 | mIndexSB = ShaderHelper.arrayToShortBuffer(VERTEX_INDEX); 52 | mOESProgram = ShaderHelper.loadProgram(context, R.raw.process_ver, R.raw.blur_frg); 53 | mOESPosition = GLES20.glGetAttribLocation(mOESProgram, "inputPosition"); 54 | mOESTextureCoordinate = GLES20.glGetAttribLocation(mOESProgram, "inputTextureCoordinate"); 55 | mOESImageTexture = GLES20.glGetUniformLocation(mOESProgram, "inputImageOESTexture"); 56 | mOESIsVertical = GLES20.glGetUniformLocation(mOESProgram, "isVertical"); 57 | mOESMatrix = GLES20.glGetUniformLocation(mOESProgram, "inputMatrix"); 58 | uTexOESMatrix = GLES20.glGetUniformLocation(mOESProgram, "uTexMatrix"); 59 | 60 | mProgram = ShaderHelper.loadProgram(context, R.raw.process_ver, R.raw.n_blur_frg); 61 | mPosition = GLES20.glGetAttribLocation(mProgram, "inputPosition"); 62 | mTextureCoordinate = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate"); 63 | mImageTexture = GLES20.glGetUniformLocation(mProgram, "inputImageTexture"); 64 | mIsVertical = GLES20.glGetUniformLocation(mProgram, "isVertical"); 65 | mMatrix = GLES20.glGetUniformLocation(mProgram, "inputMatrix"); 66 | uTexMatrix = GLES20.glGetUniformLocation(mProgram, "uTexMatrix"); 67 | mPosFB = ShaderHelper.arrayToFloatBuffer(new float[]{ 68 | -1, 1.0f, 0f, 69 | -1, -1.0f, 0f, 70 | 1, -1.0f, 0f, 71 | 1, 1.0f, 0f, 72 | }); 73 | mFBOPosFB = ShaderHelper.arrayToFloatBuffer(new float[]{ 74 | -1, 1.0f, 0f, 75 | -1, -1.0f, 0f, 76 | 1, -1.0f, 0f, 77 | 1, 1.0f, 0f, 78 | }); 79 | mTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{ 80 | 0, 1, 81 | 0, 0, 82 | 1, 0, 83 | 1, 1, 84 | }); 85 | mFBOTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{ 86 | 0, 1, 87 | 0, 0, 88 | 1, 0, 89 | 1, 1, 90 | }); 91 | Matrix.setIdentityM(mIdentityMatrix, 0); 92 | } 93 | 94 | @Override 95 | public void onChange(int width, int height) { 96 | isCreateFBO = createFBO(width, height); 97 | } 98 | 99 | @Override 100 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 101 | onDraw(textureId, mIdentityMatrix, texMatrix, x, y, width, height); 102 | } 103 | 104 | @Override 105 | public void onDraw(int textureId, float[] verMatrix, float[] texMatrix, int x, int y, int width, int height) { 106 | if (isCreateFBO) { 107 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 108 | drawOES(textureId, texMatrix, 0, 0, mFBOWidth, mFBOHeight); 109 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 110 | draw(mFrameBufferTexture[0], verMatrix, x, y, width, height); 111 | } else { 112 | drawOES(textureId, texMatrix, x, y, width, height); 113 | } 114 | } 115 | 116 | private void draw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 117 | GLES20.glUseProgram(mProgram); 118 | GLES20.glEnableVertexAttribArray(mPosition); 119 | GLES20.glVertexAttribPointer(mPosition, 3, 120 | GLES20.GL_FLOAT, false, 0, mPosFB); 121 | GLES20.glEnableVertexAttribArray(mTextureCoordinate); 122 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2, 123 | GLES20.GL_FLOAT, false, 0, mTexFB); 124 | GLES20.glUniformMatrix4fv(mMatrix, 1, false, mIdentityMatrix, 0); 125 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0); 126 | GLES20.glUniform1i(mIsVertical, 0); 127 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 128 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); 129 | GLES20.glUniform1i(mImageTexture, 0); 130 | GLES20.glViewport(x, y, width, height); 131 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 132 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 133 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 134 | GLES20.glDisableVertexAttribArray(mPosition); 135 | GLES20.glDisableVertexAttribArray(mTextureCoordinate); 136 | GLES20.glDisableVertexAttribArray(mImageTexture); 137 | GLES20.glUseProgram(0); 138 | } 139 | 140 | private void drawOES(int textureId, float[] texMatrix, int x, int y, int width, int height) { 141 | GLES20.glUseProgram(mOESProgram); 142 | GLES20.glEnableVertexAttribArray(mOESPosition); 143 | GLES20.glVertexAttribPointer(mOESPosition, 3, 144 | GLES20.GL_FLOAT, false, 0, mFBOPosFB); 145 | GLES20.glEnableVertexAttribArray(mOESTextureCoordinate); 146 | GLES20.glVertexAttribPointer(mOESTextureCoordinate, 2, 147 | GLES20.GL_FLOAT, false, 0, mFBOTexFB); 148 | GLES20.glUniformMatrix4fv(mOESMatrix, 1, false, mIdentityMatrix, 0); 149 | GLES20.glUniformMatrix4fv(uTexOESMatrix, 1, false, texMatrix, 0); 150 | GLES20.glUniform1i(mOESIsVertical, 1); 151 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 152 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); 153 | GLES20.glUniform1i(mOESImageTexture, 0); 154 | GLES20.glViewport(x, y, width, height); 155 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 156 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 157 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 158 | GLES20.glDisableVertexAttribArray(mOESPosition); 159 | GLES20.glDisableVertexAttribArray(mOESTextureCoordinate); 160 | GLES20.glDisableVertexAttribArray(mOESImageTexture); 161 | GLES20.glUseProgram(0); 162 | } 163 | 164 | private boolean createFBO(int width, int height) { 165 | mFBOWidth = width; 166 | mFBOHeight = height; 167 | GLES20.glGenFramebuffers(1, mFrameBuffer, 0); 168 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 169 | GLES20.glGenTextures(1, mFrameBufferTexture, 0); 170 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0]); 171 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 172 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 173 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 174 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 175 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, 176 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 177 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 178 | GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0], 0); 179 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 180 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 181 | if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) { 182 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); 183 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0); 184 | DLog.e("create framebuffer failed"); 185 | return false; 186 | } 187 | // DLog.i("Java create framebuffer success: (" + 188 | // width + ", " + height + "), FB: " + mFrameBuffer[0] + " , Tex: " + mFrameBufferTexture[0]); 189 | return true; 190 | } 191 | 192 | @Override 193 | public void onDestroy() { 194 | GLES20.glDeleteProgram(mOESProgram); 195 | if (isCreateFBO) { 196 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 197 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, 198 | GLES20.GL_COLOR_ATTACHMENT0, GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0, 0); 199 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 200 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); 201 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/BurrFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLES20; 6 | 7 | import com.dming.testopengl.R; 8 | import com.dming.testopengl.utils.GLInterpolator; 9 | 10 | public class BurrFilter extends BaseFilter { 11 | 12 | private int mTime; 13 | private float mCurTime = 0.0f; 14 | private GLInterpolator mGLInterpolator; 15 | 16 | public BurrFilter(Context context) { 17 | super(context, R.raw.burr_frg); 18 | mTime = GLES20.glGetUniformLocation(mProgram, "inputTime"); 19 | mGLInterpolator = new GLInterpolator(300, 1.0f); 20 | } 21 | 22 | @Override 23 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 24 | GLES20.glUseProgram(mProgram); 25 | GLES20.glEnableVertexAttribArray(mPosition); 26 | GLES20.glVertexAttribPointer(mPosition, 3, 27 | GLES20.GL_FLOAT, false, 0, mPosFB); 28 | GLES20.glEnableVertexAttribArray(mTextureCoordinate); 29 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2, 30 | GLES20.GL_FLOAT, false, 0, mTexFB); 31 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0); 32 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0); 33 | GLES20.glUniform1f(mTime, mCurTime); 34 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 35 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); 36 | GLES20.glUniform1i(mImageOESTexture, 0); 37 | GLES20.glViewport(x, y, width, height); 38 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 39 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 40 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 41 | GLES20.glDisableVertexAttribArray(mPosition); 42 | GLES20.glDisableVertexAttribArray(mTextureCoordinate); 43 | GLES20.glDisableVertexAttribArray(mImageOESTexture); 44 | GLES20.glUseProgram(0); 45 | mCurTime = mGLInterpolator.getValue(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/CutApartFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.Matrix; 5 | import android.view.animation.DecelerateInterpolator; 6 | 7 | import com.dming.testopengl.R; 8 | import com.dming.testopengl.utils.GLInterpolator; 9 | import com.dming.testopengl.utils.ShaderHelper; 10 | 11 | import java.nio.FloatBuffer; 12 | 13 | public class CutApartFilter extends BaseFilter { 14 | 15 | private GLInterpolator mGLInterpolator; 16 | private DecelerateInterpolator mDecelerateInterpolator; 17 | private FloatBuffer mTexFB1; 18 | private FloatBuffer mTexFB2; 19 | private FloatBuffer mTexFB3; 20 | private float mTranslateY; 21 | private float mTranslateYY; 22 | 23 | public CutApartFilter(Context context) { 24 | super(context, R.raw.multiple_frg); 25 | mDecelerateInterpolator = new DecelerateInterpolator(); 26 | mGLInterpolator = new GLInterpolator(4000, 1f, 0.0f); 27 | mTexFB1 = ShaderHelper.arrayToFloatBuffer(new float[]{ 28 | 0, 1, 29 | 0, 0, 30 | 0.333f, 0, 31 | 0.333f, 1, 32 | }); 33 | mTexFB2 = ShaderHelper.arrayToFloatBuffer(new float[]{ 34 | 0.333f, 1, 35 | 0.333f, 0, 36 | 0.666f, 0, 37 | 0.666f, 1, 38 | }); 39 | mTexFB3 = ShaderHelper.arrayToFloatBuffer(new float[]{ 40 | 0.666f, 1, 41 | 0.666f, 0, 42 | 1, 0, 43 | 1, 1, 44 | }); 45 | } 46 | 47 | @Override 48 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 49 | float value = mGLInterpolator.getValue(); 50 | if (value <= 0.25) { 51 | mTranslateY = mDecelerateInterpolator.getInterpolation(1 - value / 0.25f) * 2; 52 | mTranslateYY = -2 + mTranslateY; 53 | } else if (value >= 0.5 && value <= 0.75) { 54 | mTranslateY = -mDecelerateInterpolator.getInterpolation((value - 0.5f) / 0.25f) * 2; 55 | mTranslateYY = 2 + mTranslateY; 56 | } else { 57 | mTranslateY = 0; 58 | mTranslateYY = 0; 59 | } 60 | 61 | mTexFB = mTexFB1; 62 | int w = width / 3; 63 | Matrix.setIdentityM(mMvpMatrix, 0); 64 | super.onDraw(textureId, mMvpMatrix, texMatrix, x, y, w, height); 65 | // 66 | mTexFB = mTexFB2; 67 | if (mTranslateY != 0) { 68 | Matrix.translateM(mMvpMatrix, 0, 0, mTranslateYY, 0); 69 | super.onDraw(textureId, mMvpMatrix, texMatrix, x + w, y, w, height); 70 | } 71 | Matrix.setIdentityM(mMvpMatrix, 0); 72 | Matrix.translateM(mMvpMatrix, 0, 0, mTranslateY, 0); 73 | super.onDraw(textureId, mMvpMatrix, texMatrix, x + w, y, w, height); 74 | // 75 | mTexFB = mTexFB3; 76 | Matrix.setIdentityM(mMvpMatrix, 0); 77 | super.onDraw(textureId, mMvpMatrix, texMatrix, x + w + w, y, w, height); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/EdgeFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES20; 5 | 6 | import com.dming.testopengl.R; 7 | 8 | public class EdgeFilter extends BaseFilter { 9 | 10 | public EdgeFilter(Context context) { 11 | super(context, R.raw.edge_frg); 12 | } 13 | 14 | @Override 15 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 16 | GLES20.glEnable(GLES20.GL_BLEND); 17 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 18 | super.onDraw(textureId, texMatrix, x, y, width, height); 19 | GLES20.glDisable(GLES20.GL_BLEND); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/IShader.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | public interface IShader { 4 | 5 | void onChange(int width, int height); 6 | 7 | void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height); 8 | 9 | void onDraw(int textureId, float[] verMatrix, float[] texMatrix, int x, int y, int width, int height); 10 | 11 | void onDestroy(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/LuminanceFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | 5 | import com.dming.testopengl.R; 6 | 7 | public class LuminanceFilter extends BaseFilter { 8 | 9 | public LuminanceFilter(Context context) { 10 | super(context, R.raw.luminance_frg); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/MultipleFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | 5 | import com.dming.testopengl.R; 6 | import com.dming.testopengl.utils.ShaderHelper; 7 | 8 | public class MultipleFilter extends BaseFilter { 9 | 10 | public MultipleFilter(Context context) { 11 | super(context, R.raw.multiple_frg); 12 | mTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{ 13 | 0, 0.667f, 14 | 0, 0.334f, 15 | 1, 0.334f, 16 | 1, 0.667f, 17 | }); 18 | } 19 | 20 | 21 | @Override 22 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 23 | int h = height / 3; 24 | super.onDraw(textureId, texMatrix, x, y, width, h); 25 | super.onDraw(textureId, texMatrix, x, y + h, width, height - h - h); 26 | super.onDraw(textureId, texMatrix, x, y + height - h, width, h); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/ShowGifFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES20; 5 | 6 | import com.dming.testgif.DLog; 7 | import com.dming.testgif.FGLUtils; 8 | import com.dming.testgif.GifFilter; 9 | import com.dming.testgif.GifPlayer; 10 | import com.dming.testopengl.R; 11 | 12 | public class ShowGifFilter extends BaseFilter implements GifPlayer.OnGifListener { 13 | 14 | private GifPlayer mGifPlayer; 15 | private GifFilter mGifFilter; 16 | private int mTexture; 17 | private float mGifRatio; 18 | 19 | public ShowGifFilter(Context context) { 20 | super(context, R.raw.sharpen_frg); 21 | mTexture = FGLUtils.createTexture(); 22 | mGifFilter = new GifFilter(context); 23 | mGifPlayer = new GifPlayer(mTexture); 24 | mGifPlayer.setOnGifListener(this); 25 | mGifPlayer.assetPlay(mContext, "mogutou.gif"); 26 | } 27 | 28 | public void resume() { 29 | mGifPlayer.resume(); 30 | } 31 | 32 | public void pause() { 33 | mGifPlayer.pause(); 34 | } 35 | 36 | @Override 37 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 38 | GLES20.glEnable(GLES20.GL_BLEND); 39 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);// 后面透明 40 | super.onDraw(textureId, texMatrix, x, y, width, height); 41 | mGifFilter.onDraw(mTexture, x, y, (int) (mGifRatio * height / 3), height / 3); 42 | GLES20.glDisable(GLES20.GL_BLEND); 43 | } 44 | 45 | @Override 46 | public void onDestroy() { 47 | super.onDestroy(); 48 | mGifFilter.onDestroy(); 49 | mGifPlayer.destroy(); 50 | } 51 | 52 | @Override 53 | public void start() { 54 | DLog.i("start>>>"); 55 | } 56 | 57 | @Override 58 | public void size(int width, int height) { 59 | mGifRatio = 1.0f * width / height; 60 | } 61 | 62 | @Override 63 | public void update() { 64 | // DLog.i("update>>>"); 65 | } 66 | 67 | @Override 68 | public void end() { 69 | DLog.i("end>>>"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/ShowMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.res.AssetFileDescriptor; 4 | import android.graphics.SurfaceTexture; 5 | import android.media.MediaPlayer; 6 | import android.opengl.GLES11Ext; 7 | import android.opengl.GLES20; 8 | import android.opengl.GLSurfaceView; 9 | import android.opengl.Matrix; 10 | import android.view.Surface; 11 | 12 | import com.dming.testopengl.R; 13 | import com.dming.testopengl.utils.DLog; 14 | import com.dming.testopengl.utils.ShaderHelper; 15 | 16 | import java.io.IOException; 17 | import java.nio.FloatBuffer; 18 | 19 | import javax.microedition.khronos.opengles.GL10; 20 | 21 | public class ShowMovieFilter extends BaseFilter { 22 | 23 | private int mIsVideo; 24 | private FloatBuffer mVideoTexFB; 25 | // 26 | private MediaPlayer mPlayer; 27 | private Surface mSurface; 28 | private SurfaceTexture mSurfaceTexture; 29 | private int mOESVideoTexture = -1; 30 | private boolean mCanUpdate = false; 31 | private float[] mIdentityMatrix = new float[4 * 4]; 32 | 33 | public ShowMovieFilter(GLSurfaceView glSurfaceView) { 34 | super(glSurfaceView.getContext(), R.raw.animation_frg); 35 | mIsVideo = GLES20.glGetUniformLocation(mProgram, "isVideo"); 36 | // 一般编/解码器都有16位对齐的处理(有未经证实的说法,也存在32位、64位对齐的),否则会产生绿边问题。 37 | // 由于MediaPlayer在某些机型硬解码出现数据对齐问题,产生绿边,MediaPlayer是高级API,无法解决; 38 | // 这里投机不显示边缘,个人认为要更好解决就是算图像宽度是不是16的倍数,最好32倍数;然后截取 39 | // 这里就是简单截取,0 - 0.9 40 | mVideoTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{ 41 | 0f, 1f, 42 | 0.9f, 1f, 43 | 0.9f, 0f, 44 | 0f, 0f, 45 | }); 46 | initPlayer(glSurfaceView); 47 | Matrix.setIdentityM(mIdentityMatrix, 0); 48 | } 49 | 50 | @Override 51 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 52 | if (mCanUpdate) { 53 | GLES20.glEnable(GLES20.GL_BLEND); 54 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 55 | 56 | GLES20.glUseProgram(mProgram); 57 | GLES20.glEnableVertexAttribArray(mPosition); 58 | GLES20.glVertexAttribPointer(mPosition, 3, 59 | GLES20.GL_FLOAT, false, 0, mPosFB); 60 | GLES20.glEnableVertexAttribArray(mTextureCoordinate); 61 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2, 62 | GLES20.GL_FLOAT, false, 0, mTexFB); 63 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0); 64 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0); 65 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 66 | GLES20.glUniform1i(mImageOESTexture, 0); 67 | 68 | GLES20.glUniform1i(mIsVideo, 0); 69 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); 70 | 71 | GLES20.glViewport(x, y, width, height); 72 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 73 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 74 | 75 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2, 76 | GLES20.GL_FLOAT, false, 0, mVideoTexFB); 77 | GLES20.glUniform1i(mIsVideo, 1); 78 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, mIdentityMatrix, 0); 79 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESVideoTexture); 80 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 81 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 82 | 83 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 84 | 85 | GLES20.glDisableVertexAttribArray(mPosition); 86 | GLES20.glDisableVertexAttribArray(mTextureCoordinate); 87 | GLES20.glUseProgram(0); 88 | 89 | GLES20.glDisable(GLES20.GL_BLEND); 90 | } else { 91 | super.onDraw(textureId, texMatrix, x, y, width, height); 92 | } 93 | 94 | } 95 | 96 | @Override 97 | public void onDestroy() { 98 | release(); 99 | GLES20.glDeleteBuffers(1, new int[]{mOESVideoTexture}, 0); 100 | super.onDestroy(); 101 | } 102 | 103 | public void playVolume() { 104 | DLog.i("playVolume>>>"); 105 | if (mPlayer != null) { 106 | mPlayer.setVolume(1, 1); 107 | } 108 | } 109 | 110 | public void stopVolume() { 111 | DLog.i("stopVolume"); 112 | if (mPlayer != null) { 113 | mPlayer.setVolume(0, 0); 114 | } 115 | } 116 | 117 | 118 | private void initPlayer(final GLSurfaceView glSurfaceView) { 119 | DLog.i("initPlayer>>>"); 120 | mPlayer = new MediaPlayer(); 121 | mOESVideoTexture = createOESTexture(); 122 | mSurfaceTexture = new SurfaceTexture(mOESVideoTexture); 123 | mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { 124 | @Override 125 | public void onFrameAvailable(final SurfaceTexture surfaceTexture) { 126 | if (mSurfaceTexture != null) { 127 | glSurfaceView.queueEvent(new Runnable() { 128 | @Override 129 | public void run() { 130 | if (mSurfaceTexture != null) { 131 | mSurfaceTexture.updateTexImage(); 132 | mCanUpdate = true; 133 | } 134 | } 135 | }); 136 | } 137 | } 138 | }); 139 | mSurface = new Surface(mSurfaceTexture); 140 | mPlayer.setSurface(mSurface); 141 | DLog.i("Video oesTexture: " + mOESVideoTexture); 142 | mPlayer.reset(); 143 | try { 144 | AssetFileDescriptor afd = this.mContext.getAssets().openFd("animation.mp4"); 145 | mPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); 146 | mPlayer.prepare(); 147 | } catch (IOException e) { 148 | DLog.i("Play Error!!!"); 149 | } 150 | mPlayer.setLooping(true); 151 | // 152 | mPlayer.setVolume(0, 0); 153 | mPlayer.start(); 154 | } 155 | 156 | 157 | private void release() { 158 | DLog.i("release>>>" + mPlayer); 159 | mPlayer.release(); 160 | SurfaceTexture surfaceTexture = mSurfaceTexture; 161 | if (mSurfaceTexture != null) { 162 | mSurfaceTexture = null; 163 | surfaceTexture.setOnFrameAvailableListener(null); 164 | surfaceTexture.release(); 165 | } 166 | mSurface.release(); 167 | mPlayer = null; 168 | } 169 | 170 | 171 | public int createOESTexture() { 172 | int[] tex = new int[1]; 173 | //生成一个纹理 174 | GLES20.glGenTextures(1, tex, 0); 175 | //将此纹理绑定到外部纹理上 176 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); 177 | //设置纹理过滤参数 178 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 179 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 180 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 181 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 182 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 183 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 184 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 185 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 186 | //解除纹理绑定 187 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 188 | return tex[0]; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/filter/SoulFilter.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.filter; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLES20; 6 | import android.opengl.Matrix; 7 | 8 | import com.dming.testopengl.R; 9 | import com.dming.testopengl.utils.GLInterpolator; 10 | 11 | public class SoulFilter extends BaseFilter { 12 | 13 | private int mAlpha; 14 | private float mScaleRatio = 1.0f; 15 | private GLInterpolator mGLInterpolator; 16 | 17 | public SoulFilter(Context context) { 18 | super(context, R.raw.soul_frg); 19 | mGLInterpolator = new GLInterpolator(300, 0.3f,1.0f); 20 | mAlpha = GLES20.glGetUniformLocation(mProgram, "inputAlpha"); 21 | } 22 | 23 | @Override 24 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) { 25 | GLES20.glEnable(GLES20.GL_BLEND); 26 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 27 | 28 | Matrix.setIdentityM(mMvpMatrix, 0); 29 | 30 | GLES20.glUseProgram(mProgram); 31 | GLES20.glEnableVertexAttribArray(mPosition); 32 | GLES20.glVertexAttribPointer(mPosition, 3, 33 | GLES20.GL_FLOAT, false, 0, mPosFB); 34 | GLES20.glEnableVertexAttribArray(mTextureCoordinate); 35 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2, 36 | GLES20.GL_FLOAT, false, 0, mTexFB); 37 | 38 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 39 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); 40 | GLES20.glUniform1i(mImageOESTexture, 0); 41 | GLES20.glViewport(x, y, width, height); 42 | 43 | Matrix.scaleM(mMvpMatrix, 0, 1f, 1.0f, 1f); 44 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0); 45 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0); 46 | GLES20.glUniform1f(mAlpha, 1.0f); 47 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 48 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 49 | 50 | Matrix.scaleM(mMvpMatrix, 0, mScaleRatio, mScaleRatio, 1f); 51 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0); 52 | GLES20.glUniform1f(mAlpha, 0.3f); 53 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length, 54 | GLES20.GL_UNSIGNED_SHORT, mIndexSB); 55 | 56 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 57 | GLES20.glDisableVertexAttribArray(mPosition); 58 | GLES20.glDisableVertexAttribArray(mTextureCoordinate); 59 | GLES20.glDisableVertexAttribArray(mImageOESTexture); 60 | GLES20.glUseProgram(0); 61 | GLES20.glDisable(GLES20.GL_BLEND); 62 | 63 | mScaleRatio = mGLInterpolator.getValue(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/utils/DLog.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.utils; 2 | 3 | import android.util.Log; 4 | 5 | import com.dming.testopengl.BuildConfig; 6 | 7 | 8 | /** 9 | * 简单日志类,方便 10 | * Created by DMing on 2017/9/19. 11 | */ 12 | 13 | public class DLog { 14 | 15 | private static String TAG = "DMUI"; 16 | 17 | public static void d(String msg){ 18 | if (BuildConfig.DEBUG) Log.d(TAG,msg); 19 | } 20 | 21 | public static void i(String msg){ 22 | if (BuildConfig.DEBUG) Log.i(TAG,msg); 23 | } 24 | 25 | public static void e(String msg){ 26 | if (BuildConfig.DEBUG) Log.e(TAG,msg); 27 | } 28 | 29 | @SuppressWarnings("unused") 30 | public static void d(String tagNull, String msg) { 31 | d(msg); 32 | } 33 | 34 | @SuppressWarnings("unused") 35 | public static void i(String tagNull, String msg) { 36 | i(msg); 37 | } 38 | 39 | @SuppressWarnings("unused") 40 | public static void e(String tagNull, String msg) { 41 | e(msg); 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/utils/FGLUtils.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.utils; 2 | 3 | import android.opengl.GLES11Ext; 4 | import android.opengl.GLES20; 5 | 6 | import javax.microedition.khronos.opengles.GL10; 7 | 8 | public class FGLUtils { 9 | 10 | public static int[] createFBO(int width, int height) { 11 | int[] mFrameBuffer = new int[1]; 12 | int[] mFrameBufferTexture = new int[1]; 13 | GLES20.glGenFramebuffers(1, mFrameBuffer, 0); 14 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 15 | GLES20.glGenTextures(1, mFrameBufferTexture, 0); 16 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0]); 17 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 18 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 19 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 20 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 21 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, 22 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 23 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 24 | GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0], 0); 25 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 26 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 27 | if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) { 28 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); 29 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0); 30 | DLog.e("create framebuffer failed"); 31 | return null; 32 | } 33 | DLog.i("Java create framebuffer success: (" + 34 | width + ", " + height + "), FB: " + mFrameBuffer[0] + " , Tex: " + mFrameBufferTexture[0]); 35 | return new int[]{mFrameBuffer[0], mFrameBufferTexture[0]}; 36 | } 37 | 38 | public static int createOESTexture() { 39 | int[] tex = new int[1]; 40 | //生成一个纹理 41 | GLES20.glGenTextures(1, tex, 0); 42 | //将此纹理绑定到外部纹理上 43 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); 44 | //设置纹理过滤参数 45 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 46 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 47 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 48 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 49 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 50 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 51 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 52 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 53 | //解除纹理绑定 54 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 55 | return tex[0]; 56 | } 57 | 58 | public static int createTexture() { 59 | int[] tex = new int[1]; 60 | GLES20.glGenTextures(1, tex, 0); 61 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex[0]); 62 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 63 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 64 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 65 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 66 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 67 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 68 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 69 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 70 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 71 | return tex[0]; 72 | } 73 | 74 | public static void glCheckErr() { 75 | int err = GLES20.glGetError(); 76 | DLog.i("checkErr: " + err); 77 | } 78 | 79 | public static void glCheckErr(String tag) { 80 | int err = GLES20.glGetError(); 81 | if (err != 0) { 82 | DLog.i(tag + " > checkErr: " + err); 83 | } 84 | } 85 | 86 | public static void glCheckErr(int tag) { 87 | int err = GLES20.glGetError(); 88 | DLog.i(tag + " > checkErr: " + err); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/utils/GLInterpolator.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.utils; 2 | 3 | /** 4 | * ms 5 | */ 6 | public class GLInterpolator { 7 | 8 | private int mTimeSpan; 9 | private float mMaxValue = 1.0f; 10 | private float mMinValue = 0.0f; 11 | private long mLastTime = 0; 12 | 13 | public GLInterpolator(int timeSpan) { 14 | mTimeSpan = timeSpan; 15 | } 16 | 17 | public GLInterpolator(int timeSpan, float maxValue) { 18 | mTimeSpan = timeSpan; 19 | mMaxValue = maxValue; 20 | } 21 | 22 | public GLInterpolator(int timeSpan, float maxRelativeValue, float minValue) { 23 | mTimeSpan = timeSpan; 24 | mMaxValue = maxRelativeValue; 25 | mMinValue = minValue; 26 | } 27 | 28 | public float getValue() { 29 | long time = System.currentTimeMillis(); 30 | if (mLastTime == 0) { 31 | mLastTime = time; 32 | } 33 | long diff = time - mLastTime; 34 | if (diff >= mTimeSpan * 10) { 35 | mLastTime = time; 36 | } 37 | int t = (int) (diff % mTimeSpan); 38 | return mMinValue + mMaxValue * t / mTimeSpan; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/dming/testopengl/utils/ShaderHelper.java: -------------------------------------------------------------------------------- 1 | package com.dming.testopengl.utils; 2 | 3 | import android.content.Context; 4 | import android.opengl.GLES20; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.nio.ByteBuffer; 9 | import java.nio.ByteOrder; 10 | import java.nio.FloatBuffer; 11 | import java.nio.ShortBuffer; 12 | 13 | public class ShaderHelper { 14 | 15 | /** 16 | * 编译顶点着色器 17 | * 18 | * @param shaderCode 编译代码 19 | * @return 着色器对象ID 20 | */ 21 | public static int compileVertexShader(String shaderCode) { 22 | return compileShader(GLES20.GL_VERTEX_SHADER, shaderCode); 23 | } 24 | 25 | /** 26 | * 编译片段着色器 27 | * 28 | * @param shaderCode 编译代码 29 | * @return 着色器对象ID 30 | */ 31 | public static int compileFragmentShader(String shaderCode) { 32 | return compileShader(GLES20.GL_FRAGMENT_SHADER, shaderCode); 33 | } 34 | 35 | /** 36 | * 编译片段着色器 37 | * 38 | * @param type 着色器类型 39 | * @param shaderCode 编译代码 40 | * @return 着色器对象ID 41 | */ 42 | private static int compileShader(int type, String shaderCode) { 43 | // 1.创建一个新的着色器对象 44 | final int shaderObjectId = GLES20.glCreateShader(type); 45 | 46 | // 2.获取创建状态 47 | if (shaderObjectId == 0) { 48 | // 在OpenGL中,都是通过整型值去作为OpenGL对象的引用。之后进行操作的时候都是将这个整型值传回给OpenGL进行操作。 49 | // 返回值0代表着创建对象失败。 50 | DLog.e("Could not create new shader."); 51 | return 0; 52 | } 53 | 54 | // 3.将着色器代码上传到着色器对象中 55 | GLES20.glShaderSource(shaderObjectId, shaderCode); 56 | 57 | // 4.编译着色器对象 58 | GLES20.glCompileShader(shaderObjectId); 59 | 60 | // 5.获取编译状态:OpenGL将想要获取的值放入长度为1的数组的首位 61 | final int[] compileStatus = new int[1]; 62 | GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 63 | 64 | // 打印编译的着色器信息 65 | // DLog.i( "Results of compiling source:" + "\n" + shaderCode + "\n:" 66 | // + GLES20.glGetShaderInfoLog(shaderObjectId)); 67 | 68 | // 6.验证编译状态 69 | if (compileStatus[0] == 0) { 70 | // 如果编译失败,则删除创建的着色器对象 71 | GLES20.glDeleteShader(shaderObjectId); 72 | DLog.e("Compilation of shader failed."); 73 | // 7.返回着色器对象:失败,为0 74 | return 0; 75 | } 76 | 77 | // 7.返回着色器对象:成功,非0 78 | return shaderObjectId; 79 | } 80 | 81 | /** 82 | * 创建OpenGL程序:通过链接顶点着色器、片段着色器 83 | * 84 | * @param vertexShaderId 顶点着色器ID 85 | * @param fragmentShaderId 片段着色器ID 86 | * @return OpenGL程序ID 87 | */ 88 | public static int linkProgram(int vertexShaderId, int fragmentShaderId) { 89 | 90 | // 1.创建一个OpenGL程序对象 91 | final int programObjectId = GLES20.glCreateProgram(); 92 | 93 | // 2.获取创建状态 94 | if (programObjectId == 0) { 95 | DLog.e("Could not create new program"); 96 | return 0; 97 | } 98 | 99 | // 3.将顶点着色器依附到OpenGL程序对象 100 | GLES20.glAttachShader(programObjectId, vertexShaderId); 101 | // 3.将片段着色器依附到OpenGL程序对象 102 | GLES20.glAttachShader(programObjectId, fragmentShaderId); 103 | 104 | // 4.将两个着色器链接到OpenGL程序对象 105 | GLES20.glLinkProgram(programObjectId); 106 | 107 | // 5.获取链接状态:OpenGL将想要获取的值放入长度为1的数组的首位 108 | final int[] linkStatus = new int[1]; 109 | GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0); 110 | 111 | // 打印链接信息 112 | // DLog.i("Results of linking program:\n" 113 | // + GLES20.glGetProgramInfoLog(programObjectId)); 114 | 115 | // 6.验证链接状态 116 | if (linkStatus[0] == 0) { 117 | // 链接失败则删除程序对象 118 | GLES20.glDeleteProgram(programObjectId); 119 | DLog.e("Linking of program failed."); 120 | // 7.返回程序对象:失败,为0 121 | return 0; 122 | } 123 | GLES20.glDeleteShader(vertexShaderId); 124 | GLES20.glDeleteShader(fragmentShaderId); 125 | // 7.返回程序对象:成功,非0 126 | return programObjectId; 127 | } 128 | 129 | /** 130 | * 验证OpenGL程序对象状态 131 | * 132 | * @param programObjectId OpenGL程序ID 133 | * @return 是否可用 134 | */ 135 | private static boolean validateProgram(int programObjectId) { 136 | GLES20.glValidateProgram(programObjectId); 137 | 138 | final int[] validateStatus = new int[1]; 139 | GLES20.glGetProgramiv(programObjectId, GLES20.GL_VALIDATE_STATUS, validateStatus, 0); 140 | DLog.i("Results of validating program: " + validateStatus[0] 141 | + "\nLog:" + GLES20.glGetProgramInfoLog(programObjectId)); 142 | 143 | return validateStatus[0] != 0; 144 | } 145 | 146 | public static String readResource(Context context, int id) { 147 | InputStream inputStream = context.getResources().openRawResource(id); 148 | StringBuilder out = new StringBuilder(); 149 | byte[] b = new byte[4096]; 150 | try { 151 | for (int n; (n = inputStream.read(b)) != -1; ) { 152 | out.append(new String(b, 0, n)); 153 | } 154 | } catch (IOException io) { 155 | } 156 | return out.toString(); 157 | } 158 | 159 | /** 160 | * 创建OpenGL程序对象 161 | * 162 | * @param vertexShaderRes 顶点着色器代码 163 | * @param fragmentShaderRes 片段着色器代码 164 | */ 165 | public static int loadProgram(Context context, int vertexShaderRes, int fragmentShaderRes) { 166 | final int vertexShaderId = ShaderHelper.compileVertexShader(readResource(context, vertexShaderRes)); 167 | final int fragmentShaderId = ShaderHelper.compileFragmentShader(readResource(context, fragmentShaderRes)); 168 | return ShaderHelper.linkProgram(vertexShaderId, fragmentShaderId); 169 | } 170 | 171 | public static FloatBuffer arrayToFloatBuffer(float[] fArray) { 172 | FloatBuffer fBuffer = ByteBuffer.allocateDirect(fArray.length * 4) 173 | .order(ByteOrder.nativeOrder()) 174 | .asFloatBuffer() 175 | .put(fArray); 176 | fBuffer.position(0); 177 | return fBuffer; 178 | } 179 | 180 | public static ShortBuffer arrayToShortBuffer(short[] sArray) { 181 | ShortBuffer sBuffer = ByteBuffer.allocateDirect(sArray.length * 2) 182 | .order(ByteOrder.nativeOrder()) 183 | .asShortBuffer() 184 | .put(sArray); 185 | sBuffer.position(0); 186 | return sBuffer; 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/t_gl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/res/drawable-xxhdpi/t_gl.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/test_gl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/res/drawable-xxhdpi/test_gl.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/act_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 |