parent
							
								
									569e57eac8
								
							
						
					
					
						commit
						8875c7bff3
					
				| @ -0,0 +1,14 @@ | ||||
| package com.otaliastudios.cameraview.filter; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| 
 | ||||
| public interface ContextParameterFilter { | ||||
|     /** | ||||
|      * Sets the parameter. | ||||
|      * The value should always be between 0 and 1. | ||||
|      * | ||||
|      * @param value parameter | ||||
|      */ | ||||
|     void setContext(Context value); | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,140 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class AirsolidGlitchFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "float rand(vec2 p)\n" + | ||||
|                     "{\n" + | ||||
|                     "    float t = floor(iTime * 50.) / 10.;  //speed \n" + | ||||
|                     "    return fract(sin(dot(p, vec2(t * 12.9898, t * 78.233))) * 43758.5453);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float noise(vec2 uv, float blockiness)\n" + | ||||
|                     "{   \n" + | ||||
|                     "    vec2 lv = fract(uv);\n" + | ||||
|                     "    vec2 id = floor(uv);\n" + | ||||
|                     "    \n" + | ||||
|                     "    float n1 = rand(id);\n" + | ||||
|                     "    float n2 = rand(id+vec2(1,0));\n" + | ||||
|                     "    float n3 = rand(id+vec2(0,1));\n" + | ||||
|                     "    float n4 = rand(id+vec2(1,1));\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec2 u = smoothstep(0.0, 1.0 + blockiness, lv);\n" + | ||||
|                     "\n" + | ||||
|                     "    return mix(mix(n1, n2, u.x), mix(n3, n4, u.x), u.y);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float fbm(vec2 uv, int count, float blockiness, float complexity)\n" + | ||||
|                     "{\n" + | ||||
|                     "    float val = 0.0;\n" + | ||||
|                     "    float amp = 0.5;\n" + | ||||
|                     "    \n" + | ||||
|                     "    while(count != 0)\n" + | ||||
|                     "    {\n" + | ||||
|                     "    \tval += amp * noise(uv, blockiness);\n" + | ||||
|                     "        amp *= 0.5;\n" + | ||||
|                     "        uv *= complexity;    \n" + | ||||
|                     "        count--;\n" + | ||||
|                     "    }\n" + | ||||
|                     "    \n" + | ||||
|                     "    return val;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "const float glitchAmplitude = 0.9; // increase this\n" + | ||||
|                     "const float glitchNarrowness = 400.0;\n" + | ||||
|                     "const float glitchBlockiness = 10000.0;\n" + | ||||
|                     "const float glitchMinimizer = 10.0; // decrease this\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    // Normalized pixel coordinates (from 0 to 1)\n" + | ||||
|                     "    vec2 uv = fragCoord/iResolution.xy;\n" + | ||||
|                     "    vec2 a = vec2(uv.x * (iResolution.x / iResolution.y), uv.y);\n" + | ||||
|                     "    vec2 uv2 = vec2(a.x / iResolution.x, exp(a.y));\n" + | ||||
|                     "\tvec2 id = floor(uv * 20.0);                           // size noise\n" + | ||||
|                     "    //id.x /= floor(texture(iChannel0, vec2(id / 8.0)).r * 8.0);\n" + | ||||
|                     "\n" + | ||||
|                     "    // Generate shift amplitude\n" + | ||||
|                     "    float shift = glitchAmplitude * pow(fbm(uv2, int(rand(id) * 6.), glitchBlockiness, glitchNarrowness), glitchMinimizer);\n" + | ||||
|                     "    \n" + | ||||
|                     "    // Create a scanline effect\n" + | ||||
|                     "    float scanline = abs(cos(uv.y * 400.));      //scanline intensite\n" + | ||||
|                     "    scanline = smoothstep(0.0, 2.0, scanline);\n" + | ||||
|                     "    shift = smoothstep(0.00001, 0.2, shift);\n" + | ||||
|                     "    \n" + | ||||
|                     "    // Apply glitch and RGB shift\n" + | ||||
|                     "    float colR = texture2D(iChannel0, vec2(uv.x + shift, uv.y)).r * (1. - shift) ;\n" + | ||||
|                     "    float colG = texture2D(iChannel0, vec2(uv.x - shift, uv.y)).g * (1. - shift) + rand(id) * shift;\n" + | ||||
|                     "    float colB = texture2D(iChannel0, vec2(uv.x - shift, uv.y)).b * (1. - shift);\n" + | ||||
|                     "    // Mix with the scanline effect\n" + | ||||
|                     "    vec3 f = vec3(colR, colG, colB) - (0.1 * scanline); //scanline intensite\n" + | ||||
|                     "    \n" + | ||||
|                     "    // Output to screen\n" + | ||||
|                     "    fragColor = vec4(f, 1.0);\n" + | ||||
|                     "}" + | ||||
|                     "\nvoid main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iResolutionLocation = -1; | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         float time = (((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f) + 1; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,81 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class AnaglyphFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "\tvec2 uv = fragCoord.xy / iResolution.xy;\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec4 left = texture2D(iChannel0, uv);\n" + | ||||
|                     "    vec4 right = texture2D(iChannel0, uv + vec2(0.015, 0.0));\n" + | ||||
|                     "\t\n" + | ||||
|                     "    vec3 color = vec3(left.r, right.gb);\n" + | ||||
|                     "    color = clamp(color, 0.0, 1.0);\n" + | ||||
|                     "    fragColor = vec4(color, 1.0);\n" + | ||||
|                     "}\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iResolutionLocation = -1; | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
| //        Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime");
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,93 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class AsciiFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "float character(int n, vec2 p)\n" + | ||||
|                     "{\n" + | ||||
|                     "\tp = floor(p*vec2(4.0, -4.0) + 2.5);\n" + | ||||
|                     "    if (clamp(p.x, 0.0, 4.0) == p.x)\n" + | ||||
|                     "\t{\n" + | ||||
|                     "        if (clamp(p.y, 0.0, 4.0) == p.y)\t\n" + | ||||
|                     "\t\t{\n" + | ||||
|                     "        \tint a = int(round(p.x) + 5.0 * round(p.y));\n" + | ||||
|                     "\t\t\tif (((n >> a) & 1) == 1) return 1.0;\n" + | ||||
|                     "\t\t}\t\n" + | ||||
|                     "    }\n" + | ||||
|                     "\treturn 0.0;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "\tvec2 pix = fragCoord.xy;\n" + | ||||
|                     "\tvec3 col = texture2D(iChannel0, floor(pix/8.0)*8.0/iResolution.xy).rgb;\t\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tfloat gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tint n =  4096;                // .\n" + | ||||
|                     "\tif (gray > 0.2) n = 65600;    // :\n" + | ||||
|                     "\tif (gray > 0.3) n = 332772;   // *\n" + | ||||
|                     "\tif (gray > 0.4) n = 15255086; // o \n" + | ||||
|                     "\tif (gray > 0.5) n = 23385164; // &\n" + | ||||
|                     "\tif (gray > 0.6) n = 15252014; // 8\n" + | ||||
|                     "\tif (gray > 0.7) n = 13199452; // @\n" + | ||||
|                     "\tif (gray > 0.8) n = 11512810; // #\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tvec2 p = mod(pix/4.0, 2.0) - vec2(1.0);\n" + | ||||
|                     "    \n" + | ||||
|                     "\tif (iMouse.z > 0.5)\tcol = gray*vec3(character(n, p));\n" + | ||||
|                     "\telse col = col*character(n, p);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tfragColor = vec4(col, 1.0);\n" + | ||||
|                     "}" + | ||||
|                     "\nvoid main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iResolutionLocation = -1; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,79 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| public class ChromaticAberrationFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision mediump float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iGlobalTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                "+DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME+";\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    vec2 uv = fragCoord.xy;\n" + | ||||
|                     "\n" + | ||||
|                     "\tfloat amount = 0.0;\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tamount = (1.0 + sin(iGlobalTime*6.0)) * 0.5;\n" + | ||||
|                     "\tamount *= 1.0 + sin(iGlobalTime*16.0) * 0.5;\n" + | ||||
|                     "\tamount *= 1.0 + sin(iGlobalTime*19.0) * 0.5;\n" + | ||||
|                     "\tamount *= 1.0 + sin(iGlobalTime*27.0) * 0.5;\n" + | ||||
|                     "\tamount = pow(amount, 3.0);\n" + | ||||
|                     "\n" + | ||||
|                     "\tamount *= 0.05;\n" + | ||||
|                     "\t\n" + | ||||
|                     "    vec3 col;\n" + | ||||
|                     "    col.r = texture2D( iChannel0, vec2(uv.x+amount,uv.y) ).r;\n" + | ||||
|                     "    col.g = texture2D( iChannel0, uv ).g;\n" + | ||||
|                     "    col.b = texture2D( iChannel0, vec2(uv.x-amount,uv.y) ).b;\n" + | ||||
|                     "\n" + | ||||
|                     "\tcol *= (1.0 - amount * 0.5);\n" + | ||||
|                     "\t\n" + | ||||
|                     "    fragColor = vec4(col,1.0);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     " \tmainImage(gl_FragColor, "+DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME+");\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iGlobalTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iGlobalTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,56 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.OneParameterFilter; | ||||
| 
 | ||||
| public class ColorspaceFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision mediump float;\n" + | ||||
| 
 | ||||
|                     "varying vec2 vTextureCoord;" + | ||||
|                     "uniform samplerExternalOES sTexture;" + | ||||
| 
 | ||||
|                     "void main() {" + | ||||
|                     "highp vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0);" + | ||||
| 
 | ||||
|                     "highp vec2 samplePos = vTextureCoord - mod(vTextureCoord, sampleDivisor);" + | ||||
|                     "highp vec4 color = texture2D(sTexture, samplePos);" + | ||||
| 
 | ||||
|                     "mediump vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0);" + | ||||
|                     "mediump vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0);" + | ||||
|                     "mediump vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0);" + | ||||
|                     "mediump vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0);" + | ||||
| 
 | ||||
|                     "mediump vec4 endColor;" + | ||||
|                     "highp float blackDistance = distance(color, colorBlack);" + | ||||
|                     "highp float whiteDistance = distance(color, colorWhite);" + | ||||
|                     "highp float magentaDistance = distance(color, colorMagenta);" + | ||||
|                     "highp float cyanDistance = distance(color, colorCyan);" + | ||||
| 
 | ||||
|                     "mediump vec4 finalColor;" + | ||||
| 
 | ||||
|                     "highp float colorDistance = min(magentaDistance, cyanDistance);" + | ||||
|                     "colorDistance = min(colorDistance, whiteDistance);" + | ||||
|                     "colorDistance = min(colorDistance, blackDistance);" + | ||||
| 
 | ||||
|                     "if (colorDistance == blackDistance) {" + | ||||
|                     "finalColor = colorBlack;" + | ||||
|                     "} else if (colorDistance == whiteDistance) {" + | ||||
|                     "finalColor = colorWhite;" + | ||||
|                     "} else if (colorDistance == cyanDistance) {" + | ||||
|                     "finalColor = colorCyan;" + | ||||
|                     "} else {" + | ||||
|                     "finalColor = colorMagenta;" + | ||||
|                     "}" + | ||||
| 
 | ||||
|                     "gl_FragColor = finalColor;" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,109 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class CrackedFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "#extension GL_OES_standard_derivatives : enable\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
| //                    "uniform float               iGlobalTime;\n" +
 | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "float rnd(vec2 s)\n" + | ||||
|                     "{\n" + | ||||
|                     "    return 1.-2.*fract(sin(s.x*253.13+s.y*341.41)*589.19);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "\tvec2 p=(fragCoord.xy*2.-iResolution.xy)/iResolution.x;\n" + | ||||
|                     "\n" + | ||||
|                     "    vec2 v=vec2(1E3);\n" + | ||||
|                     "    vec2 v2=vec2(1E4);\n" + | ||||
|                     "    vec2 center=vec2(.1,-.5);\n" + | ||||
|                     "    for(int c=0;c<30;c++)\n" + | ||||
|                     "    {\n" + | ||||
|                     "        float angle=floor(rnd(vec2(float(c),387.44))*16.)*3.1415*.4-.5;\n" + | ||||
|                     "        float dist=pow(rnd(vec2(float(c),78.21)),2.)*.5;\n" + | ||||
|                     "        vec2 vc=vec2(center.x+cos(angle)*dist+rnd(vec2(float(c),349.3))*7E-3,\n" + | ||||
|                     "                     center.y+sin(angle)*dist+rnd(vec2(float(c),912.7))*7E-3);\n" + | ||||
|                     "        if(length(vc-p)<length(v-p))\n" + | ||||
|                     "        {\n" + | ||||
|                     "\t        v2=v;\n" + | ||||
|                     "\t        v=vc;\n" + | ||||
|                     "        }\n" + | ||||
|                     "        else if(length(vc-p)<length(v2-p))\n" + | ||||
|                     "        {\n" + | ||||
|                     "            v2=vc;\n" + | ||||
|                     "        }\n" + | ||||
|                     "    }\n" + | ||||
|                     "\n" + | ||||
|                     "    float col=abs(length(dot(p-v,normalize(v-v2)))-length(dot(p-v2,normalize(v-v2))))+.002*length(p-center);\n" + | ||||
|                     "    col=7E-4/col;\n" + | ||||
|                     "    if(length(v-v2)<4E-3)col=0.;\n" + | ||||
|                     "//    if(length(v-p)<4E-3)col=1E-6;\n" + | ||||
|                     "    if(col<.3)col=0.;\n" + | ||||
|                     "    vec4 tex=texture2D(iChannel0,(fragCoord.xy)/iResolution.xy+rnd(v)*.02);\n" + | ||||
|                     "    fragColor=col*vec4(vec3(1.-tex.xyz),1.)+(1.-col)*tex;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
| //    private int iGlobalTimeLocation = -1;
 | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
| //        iGlobalTimeLocation = -1;
 | ||||
| //        START_TIME = System.currentTimeMillis();
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
| //        iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iGlobalTime");
 | ||||
| //        Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iGlobalTime");
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
| //        GLES20.glUniform1f(iGlobalTimeLocation, time);
 | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,128 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.TwoParameterFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| public class CrosshatchFilter extends BaseFilter implements TwoParameterFilter { | ||||
|     private static final String CROSSHATCH_FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision mediump float;" + | ||||
|             "varying vec2 vTextureCoord;\n" + | ||||
|             " uniform samplerExternalOES sTexture;\n" + | ||||
|             "uniform highp float crossHatchSpacing;\n" + | ||||
|             "uniform highp float lineWidth;\n" + | ||||
|             "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + | ||||
|             "void main()\n" + | ||||
|             "{\n" + | ||||
|             "highp float luminance = dot(texture2D(sTexture, vTextureCoord).rgb, W);\n" + | ||||
|             "lowp vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0);\n" + | ||||
|             "if (luminance < 1.00)\n" + | ||||
|             "{\n" + | ||||
|             "if (mod(vTextureCoord.x + vTextureCoord.y, crossHatchSpacing) <= lineWidth)\n" + | ||||
|             "{\n" + | ||||
|             "colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);\n" + | ||||
|             "}\n" + | ||||
|             "}\n" + | ||||
|             "if (luminance < 0.75)\n" + | ||||
|             "{\n" + | ||||
|             "if (mod(vTextureCoord.x - vTextureCoord.y, crossHatchSpacing) <= lineWidth)\n" + | ||||
|             "{\n" + | ||||
|             "colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);\n" + | ||||
|             "}\n" + | ||||
|             "}\n" + | ||||
|             "if (luminance < 0.50)\n" + | ||||
|             "{\n" + | ||||
|             "if (mod(vTextureCoord.x + vTextureCoord.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)\n" + | ||||
|             "{\n" + | ||||
|             "colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);\n" + | ||||
|             "}\n" + | ||||
|             "}\n" + | ||||
|             "if (luminance < 0.3)\n" + | ||||
|             "{\n" + | ||||
|             "if (mod(vTextureCoord.x - vTextureCoord.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)\n" + | ||||
|             "{\n" + | ||||
|             "colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);\n" + | ||||
|             "}\n" + | ||||
|             "}\n" + | ||||
|             "gl_FragColor = colorToDisplay;\n" + | ||||
|             "}\n"; | ||||
| 
 | ||||
|     private float crossHatchSpacing = 0.03f; | ||||
|     private int crossHatchSpacingLocation = -1; | ||||
| 
 | ||||
|     private float lineWidth = 0.003f; | ||||
|     private int lineWidthLocation = -1; | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         crossHatchSpacingLocation = GLES20.glGetUniformLocation(programHandle, "crossHatchSpacing"); | ||||
|         Egloo.checkGlProgramLocation(crossHatchSpacingLocation, "crossHatchSpacing"); | ||||
| 
 | ||||
|         lineWidthLocation = GLES20.glGetUniformLocation(programHandle, "lineWidth"); | ||||
|         Egloo.checkGlProgramLocation(lineWidthLocation, "lineWidth"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         GLES20.glUniform1f(crossHatchSpacingLocation, crossHatchSpacing); | ||||
|         GLES20.glUniform1f(lineWidthLocation, lineWidth); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         crossHatchSpacing = 0.03f; | ||||
|         crossHatchSpacingLocation = -1; | ||||
|         lineWidth = 0.003f; | ||||
|         lineWidthLocation = -1; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return CROSSHATCH_FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter1(float value) { | ||||
|         setCrossHatchSpacing(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter1() { | ||||
|         return getCrossHatchSpacing(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter2(float value) { | ||||
|         setLineWidth(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter2() { | ||||
|         return getLineWidth(); | ||||
|     } | ||||
| 
 | ||||
|     public float getLineWidth() { | ||||
|         return lineWidth; | ||||
|     } | ||||
| 
 | ||||
|     public void setLineWidth(float lineWidth) { | ||||
|         this.lineWidth = lineWidth; | ||||
|     } | ||||
| 
 | ||||
|     public float getCrossHatchSpacing() { | ||||
|         return crossHatchSpacing; | ||||
|     } | ||||
| 
 | ||||
|     public void setCrossHatchSpacing(float crossHatchSpacing) { | ||||
|         this.crossHatchSpacing = crossHatchSpacing; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,134 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class Day41GlitchFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                    "float rand(vec2 p)\n" + | ||||
|                     "{\n" + | ||||
|                     "    float t = floor(iTime * 20.) / 10.;\n" + | ||||
|                     "    return fract(sin(dot(p, vec2(t * 12.9898, t * 78.233))) * 43758.5453);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float noise(vec2 uv, float blockiness)\n" + | ||||
|                     "{   \n" + | ||||
|                     "    vec2 lv = fract(uv);\n" + | ||||
|                     "    vec2 id = floor(uv);\n" + | ||||
|                     "    \n" + | ||||
|                     "    float n1 = rand(id);\n" + | ||||
|                     "    float n2 = rand(id+vec2(1,0));\n" + | ||||
|                     "    float n3 = rand(id+vec2(0,1));\n" + | ||||
|                     "    float n4 = rand(id+vec2(1,1));\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec2 u = smoothstep(0.0, 1.0 + blockiness, lv);\n" + | ||||
|                     "\n" + | ||||
|                     "    return mix(mix(n1, n2, u.x), mix(n3, n4, u.x), u.y);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float fbm(vec2 uv, int count, float blockiness, float complexity)\n" + | ||||
|                     "{\n" + | ||||
|                     "    float val = 0.0;\n" + | ||||
|                     "    float amp = 0.5;\n" + | ||||
|                     "    \n" + | ||||
|                     "    while(count != 0)\n" + | ||||
|                     "    {\n" + | ||||
|                     "    \tval += amp * noise(uv, blockiness);\n" + | ||||
|                     "        amp *= 0.5;\n" + | ||||
|                     "        uv *= complexity;    \n" + | ||||
|                     "        count--;\n" + | ||||
|                     "    }\n" + | ||||
|                     "    \n" + | ||||
|                     "    return val;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "const float glitchAmplitude = 0.2; // increase this\n" + | ||||
|                     "const float glitchNarrowness = 4.0;\n" + | ||||
|                     "const float glitchBlockiness = 2.0;\n" + | ||||
|                     "const float glitchMinimizer = 8.0; // decrease this\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec2 uv = fragCoord/iResolution.xy;\n" + | ||||
|                     "    float aspect = iResolution.x / iResolution.y;\n" + | ||||
|                     "    vec2 a = vec2(uv.x * aspect , uv.y);\n" + | ||||
|                     "    vec2 uv2 = vec2(a.x / iResolution.x, exp(a.y));\n" + | ||||
|                     "\n" + | ||||
|                     "    \n" + | ||||
|                     "    float shift = glitchAmplitude * pow(fbm(uv2, 4, glitchBlockiness, glitchNarrowness), glitchMinimizer);\n" + | ||||
|                     "    \n" + | ||||
|                     "    float colR = texture2D(iChannel0, vec2(uv.x + shift, uv.y)).r * (1. - shift);\n" + | ||||
|                     "    float colG = texture2D(iChannel0, vec2(uv.x - shift, uv.y)).g * (1. - shift);\n" + | ||||
|                     "    float colB = texture2D(iChannel0, vec2(uv.x - shift, uv.y)).b * (1. - shift);\n" + | ||||
|                     "    \n" + | ||||
|                     "    // Mix with the scanline effect\n" + | ||||
|                     "    vec3 f = vec3(colR, colG, colB);\n" + | ||||
|                     "\n" + | ||||
|                     "    \n" + | ||||
|                     "    fragColor = vec4(f, 1.);\n" + | ||||
|                     "}" + | ||||
|                     "\nvoid main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iResolutionLocation = -1; | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         float time = (((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f) + 1; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,108 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class DrunkDialFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                  "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "\t// Just playing around with shaders for my first time.\n" + | ||||
|                     "\t// Pardon the unoptimized mess.\n" + | ||||
|                     "\t// -Dan\n" + | ||||
|                     "\tfloat drunk = sin(iTime*2.0)*6.0;\n" + | ||||
|                     "\tfloat unitDrunk1 = (sin(iTime*1.2)+1.0)/2.0;\n" + | ||||
|                     "\tfloat unitDrunk2 = (sin(iTime*1.8)+1.0)/2.0;\n" + | ||||
|                     "\n" + | ||||
|                     "\tvec2 normalizedCoord = mod((fragCoord.xy + vec2(0, drunk)) / iResolution.xy, 1.0);\n" + | ||||
|                     "\tnormalizedCoord.x = pow(normalizedCoord.x, mix(1.25, 0.85, unitDrunk1));\n" + | ||||
|                     "\tnormalizedCoord.y = pow(normalizedCoord.y, mix(0.85, 1.25, unitDrunk2));\n" + | ||||
|                     "\n" + | ||||
|                     "\tvec2 normalizedCoord2 = mod((fragCoord.xy + vec2(drunk, 0)) / iResolution.xy, 1.0);\t\n" + | ||||
|                     "\tnormalizedCoord2.x = pow(normalizedCoord2.x, mix(0.95, 1.1, unitDrunk2));\n" + | ||||
|                     "\tnormalizedCoord2.y = pow(normalizedCoord2.y, mix(1.1, 0.95, unitDrunk1));\n" + | ||||
|                     "\n" + | ||||
|                     "\tvec2 normalizedCoord3 = fragCoord.xy/iResolution.xy;\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tvec4 color = texture2D(iChannel0, normalizedCoord);\t\n" + | ||||
|                     "\tvec4 color2 = texture2D(iChannel0, normalizedCoord2);\n" + | ||||
|                     "\tvec4 color3 = texture2D(iChannel0, normalizedCoord3);\n" + | ||||
|                     "\n" + | ||||
|                     "\t// Mess with colors and test swizzling\n" + | ||||
|                     "\tcolor.x = sqrt(color2.x);\n" + | ||||
|                     "\tcolor2.x = sqrt(color2.x);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tvec4 finalColor = mix( mix(color, color2, mix(0.4, 0.6, unitDrunk1)), color3, 0.4);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\t// \n" + | ||||
|                     "\tif (length(finalColor) > 1.4)\n" + | ||||
|                     "\t\tfinalColor.xy = mix(finalColor.xy, normalizedCoord3, 0.5);\n" + | ||||
|                     "\telse if (length(finalColor) < 0.4)\n" + | ||||
|                     "\t\tfinalColor.yz = mix(finalColor.yz, normalizedCoord3, 0.5);\n" + | ||||
|                     "\t\t\n" + | ||||
|                     "\tfragColor = finalColor;\t\t\n" + | ||||
|                     "}\n"+ | ||||
|                     "\nvoid main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iResolutionLocation = -1; | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         float time = (((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f) + 1; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,83 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class EMInterferenceFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform float               iGlobalTime;\n" + | ||||
|                     "uniform samplerExternalOES  iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "float rng2(vec2 seed)\n" + | ||||
|                     "{\n" + | ||||
|                     "    return fract(sin(dot(seed * floor(iGlobalTime * 12.), vec2(127.1,311.7))) * 43758.5453123);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float rng(float seed)\n" + | ||||
|                     "{\n" + | ||||
|                     "    return rng2(vec2(seed, 1.0));\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "\tvec2 uv = fragCoord.xy;\n" + | ||||
|                     "    vec2 blockS = floor(uv * vec2(24., 9.));\n" + | ||||
|                     "    vec2 blockL = floor(uv * vec2(8., 4.));\n" + | ||||
|                     "\n" + | ||||
|                     "    float r = rng2(uv);\n" + | ||||
|                     "    vec3 noise = (vec3(r, 1. - r, r / 2. + 0.5) * 1.0 - 2.0) * 0.08;\n" + | ||||
|                     "\n" + | ||||
|                     "    float lineNoise = pow(rng2(blockS), 8.0) * pow(rng2(blockL), 3.0) - pow(rng(7.2341), 17.0) * 2.;\n" + | ||||
|                     "\n" + | ||||
|                     "    vec4 col1 = texture2D(iChannel0, uv);\n" + | ||||
|                     "    vec4 col2 = texture2D(iChannel0, uv + vec2(lineNoise * 0.05 * rng(5.0), 0));\n" + | ||||
|                     "    vec4 col3 = texture2D(iChannel0, uv - vec2(lineNoise * 0.05 * rng(31.0), 0));\n" + | ||||
|                     "\n" + | ||||
|                     "\tfragColor = vec4(vec3(col1.x, col2.y, col3.z) + noise, 1.0);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ");\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iGlobalTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iGlobalTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,106 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.R; | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.ContextParameterFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class EarlybirdFilter extends BaseFilter implements ContextParameterFilter { | ||||
| 
 | ||||
| 
 | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision mediump float; \n" + | ||||
|                     "uniform samplerExternalOES sTexture; \n" + | ||||
|                     "varying vec2 " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + "; \n" + | ||||
|                     "const vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + | ||||
|                     "\n" + | ||||
|                     "vec3 BrightnessContrastSaturation(vec3 color, float brt, float con, float sat)\n" + | ||||
|                     "{\n" + | ||||
|                     "\tvec3 black = vec3(0., 0., 0.);\n" + | ||||
|                     "\tvec3 middle = vec3(0.5, 0.5, 0.5);\n" + | ||||
|                     "\tfloat luminance = dot(color, W);\n" + | ||||
|                     "\tvec3 gray = vec3(luminance, luminance, luminance);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tvec3 brtColor = mix(black, color, brt);\n" + | ||||
|                     "\tvec3 conColor = mix(middle, brtColor, con);\n" + | ||||
|                     "\tvec3 satColor = mix(gray, conColor, sat);\n" + | ||||
|                     "\treturn satColor;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "vec3 ovelayBlender(vec3 Color, vec3 filter){\n" + | ||||
|                     "\tvec3 filter_result;\n" + | ||||
|                     "\tfloat luminance = dot(filter, W);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tif(luminance < 0.5)\n" + | ||||
|                     "\t\tfilter_result = 2. * filter * Color;\n" + | ||||
|                     "\telse\n" + | ||||
|                     "\t\tfilter_result = 1. - (1. - (2. *(filter - 0.5)))*(1. - Color);\n" + | ||||
|                     "\t\t\n" + | ||||
|                     "\treturn filter_result;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "vec3 multiplyBlender(vec3 Color, vec3 filter){\n" + | ||||
|                     "\tvec3 filter_result;\n" + | ||||
|                     "\tfloat luminance = dot(filter, W);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tif(luminance < 0.5)\n" + | ||||
|                     "\t\tfilter_result = 2. * filter * Color;\n" + | ||||
|                     "\telse\n" + | ||||
|                     "\t\tfilter_result = Color;\n" + | ||||
|                     "\t\t\t\n" + | ||||
|                     "\treturn filter_result;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void main()\n" + | ||||
|                     "{\n" + | ||||
|                     "\t //get the pixel\n" + | ||||
|                     "     vec2 st = " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ".st;\n" + | ||||
|                     "     vec3 irgb = texture2D(sTexture, st).rgb;\n" + | ||||
|                     "     \n" + | ||||
|                     "     //adjust the brightness/contrast/saturation\n" + | ||||
|                     "     float T_bright = 1.2;\n" + | ||||
|                     "     float T_contrast = 1.1;\n" + | ||||
|                     "     float T_saturation = 1.2;\n" + | ||||
|                     "     vec3 bcs_result = BrightnessContrastSaturation(irgb, T_bright, T_contrast, T_saturation);\n" + | ||||
|                     "     \n" + | ||||
|                     "     //more red, less blue\n" + | ||||
|                     "     vec3 rb_result = vec3(bcs_result.r*1.1, bcs_result.g, bcs_result.b*0.9);\n" + | ||||
|                     "     \n" + | ||||
|                     "     gl_FragColor = vec4(rb_result, 1.);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setContext(Context value) { | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,48 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| 
 | ||||
| public class EdgeDetectionFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "#extension GL_OES_standard_derivatives : enable\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    vec2 uv = fragCoord.xy;\n" + | ||||
|                     "    vec4 color =  texture2D(iChannel0, fragCoord);\n" + | ||||
|                     "    float gray = length(color.rgb);\n" + | ||||
|                     "    fragColor = vec4(vec3(step(0.06, length(vec2(dFdx(gray), dFdy(gray))))), 1.0);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "    mainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ");\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,143 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class EdgeGlowFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "/* Returns rgb vec from input 0-1 */\n" + | ||||
|                     "vec3 getRainbowColor(in float val) {\n" + | ||||
|                     "    /*convert to rainbow RGB*/\n" + | ||||
|                     "    float a = (1.0 - val) * 6.0;\n" + | ||||
|                     "    int X = int(floor(a));\n" + | ||||
|                     "    float Y = a - float(X);\n" + | ||||
|                     "    float r = 0.;\n" + | ||||
|                     "    float g = 0.;\n" + | ||||
|                     "    float b = 0.;\n" + | ||||
|                     "    if (X == 0) {\n" + | ||||
|                     "        r = 1.; g = Y; b = 0.;\n" + | ||||
|                     "    } else if (X == 1) {\n" + | ||||
|                     "        r = 1. - Y; g = 1.; b = 0.;\n" + | ||||
|                     "    } else if (X == 2) {\n" + | ||||
|                     "        r = 0.; g = 1.; b = Y;\n" + | ||||
|                     "    } else if (X == 3) {\n" + | ||||
|                     "        r = 0.; g = 1. - Y; b = 1.;\n" + | ||||
|                     "    } else if (X == 4) {\n" + | ||||
|                     "        r = Y; g = 0.; b = 1.;\n" + | ||||
|                     "    } else if (X == 5) {\n" + | ||||
|                     "        r = 1.; g = 0.; b = 1. - Y;\n" + | ||||
|                     "    } else {\n" + | ||||
|                     "        r = 0.; g = 0.; b = 0.;\n" + | ||||
|                     "    }\n" + | ||||
|                     "    return vec3(r, g, b);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float d;\n" + | ||||
|                     "\n" + | ||||
|                     "float lookup(vec2 p, float dx, float dy, float edgeIntensity)\n" + | ||||
|                     "{\n" + | ||||
|                     "    vec2 uv = (p.xy + vec2(dx * edgeIntensity, dy * edgeIntensity)) / iResolution.xy;\n" + | ||||
|                     "    vec4 c = texture2D(iChannel0, uv.xy);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\t// return as luma\n" + | ||||
|                     "    return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    float timeNorm = mod(iTime, 5.) / 5.;\n" + | ||||
|                     "    vec3 glowCol = getRainbowColor(timeNorm);\n" + | ||||
|                     "    float edgeIntensity = 1.;\n" + | ||||
|                     "    if (timeNorm < .5) { edgeIntensity += (4. * timeNorm);}\n" + | ||||
|                     "    else { edgeIntensity += -4. * (timeNorm - 1.); }\n" + | ||||
|                     "    vec2 p = fragCoord.xy;\n" + | ||||
|                     "    \n" + | ||||
|                     "\t// simple sobel edge detection\n" + | ||||
|                     "    float gx = 0.0;\n" + | ||||
|                     "    gx += -1.0 * lookup(p, -1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gx += -2.0 * lookup(p, -1.0,  0.0, edgeIntensity);\n" + | ||||
|                     "    gx += -1.0 * lookup(p, -1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  1.0 * lookup(p,  1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  2.0 * lookup(p,  1.0,  0.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  1.0 * lookup(p,  1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    \n" + | ||||
|                     "    float gy = 0.0;\n" + | ||||
|                     "    gy += -1.0 * lookup(p, -1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy += -2.0 * lookup(p,  0.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy += -1.0 * lookup(p,  1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  1.0 * lookup(p, -1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  2.0 * lookup(p,  0.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  1.0 * lookup(p,  1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    \n" + | ||||
|                     "\t// hack: use g^2 to conceal noise in the video\n" + | ||||
|                     "    float g = gx*gx + gy*gy;\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec4 col = texture2D(iChannel0, p / iResolution.xy);\n" + | ||||
|                     "    col += vec4(g * glowCol, 1.0);\n" + | ||||
|                     "    \n" + | ||||
|                     "    fragColor = col;\n" + | ||||
|                     "}" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,77 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.OneParameterFilter; | ||||
| import com.otaliastudios.cameraview.filter.TwoParameterFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| /** | ||||
|  * exposure: The adjusted exposure (-1 - 0 - 1 as the default) | ||||
|  */ | ||||
| public class ExposureFilter extends BaseFilter implements OneParameterFilter { | ||||
|     private static final String EXPOSURE_FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision mediump float;\n" + | ||||
|             "uniform samplerExternalOES sTexture;\n" + | ||||
|             "uniform float exposure;\n" + | ||||
|             "varying vec2 "+DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME+";\n" + | ||||
|             "void main()\n" + | ||||
|             "{\n" + | ||||
|             "   vec4 textureColor = texture2D(sTexture, "+DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME+");\n" + | ||||
|             "   gl_FragColor = vec4(textureColor.rgb * pow(2.0, exposure), textureColor.w);\n" + | ||||
|             "}"; | ||||
| 
 | ||||
|     private float exposure = 1f; | ||||
|     private int exposureLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return EXPOSURE_FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         exposureLocation = GLES20.glGetUniformLocation(programHandle, "exposure"); | ||||
|         Egloo.checkGlProgramLocation(exposureLocation, "exposure"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         GLES20.glUniform1f(exposureLocation, exposure); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         exposure = 1f; | ||||
|         exposureLocation = -1; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter1(float value) { | ||||
|         setExposure(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter1() { | ||||
|         return getExposure(); | ||||
|     } | ||||
| 
 | ||||
|     public float getExposure() { | ||||
|         return exposure; | ||||
|     } | ||||
|     /** | ||||
|      * exposure: The adjusted exposure (-10.0 - 10.0, with 0.0 as the default) | ||||
|      */ | ||||
|     public void setExposure(float exposure) { | ||||
|         this.exposure = exposure; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,115 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.OneParameterFilter; | ||||
| import com.otaliastudios.cameraview.filter.TwoParameterFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| /** | ||||
|  * exposure: The adjusted exposure (-10.0 - 10.0, with 0.0 as the default) | ||||
|  */ | ||||
| public class HalftoneFilter extends BaseFilter implements TwoParameterFilter { | ||||
|     private static final String EXPOSURE_FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision mediump float;" + | ||||
|             "varying vec2 vTextureCoord;\n" + | ||||
| 
 | ||||
|             "uniform samplerExternalOES sTexture;\n" + | ||||
| 
 | ||||
|             "uniform highp float fractionalWidthOfPixel;\n" + | ||||
|             "uniform highp float aspectRatio;\n" + | ||||
| 
 | ||||
|             "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + | ||||
| 
 | ||||
|             "void main()\n" + | ||||
|             "{\n" + | ||||
|             "  highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio);\n" + | ||||
|             "  highp vec2 samplePos = vTextureCoord - mod(vTextureCoord, sampleDivisor) + 0.5 * sampleDivisor;\n" + | ||||
|             "  highp vec2 textureCoordinateToUse = vec2(vTextureCoord.x, (vTextureCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));\n" + | ||||
|             "  highp vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio));\n" + | ||||
|             "  highp float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse);\n" + | ||||
|             "  lowp vec3 sampledColor = texture2D(sTexture, samplePos).rgb;\n" + | ||||
|             "  highp float dotScaling = 1.0 - dot(sampledColor, W);\n" + | ||||
|             "  lowp float checkForPresenceWithinDot = 1.0 - step(distanceFromSamplePoint, (fractionalWidthOfPixel * 0.5) * dotScaling);\n" + | ||||
|             "  gl_FragColor = vec4(vec3(checkForPresenceWithinDot), 1.0);\n" + | ||||
|             "}"; | ||||
| 
 | ||||
|     private float fractionalWidthOfPixel = 0.01f; | ||||
|     private int fractionalWidthOfPixelLocation = -1; | ||||
|     private float aspectRatio = 1f; | ||||
|     private int aspectRatioLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return EXPOSURE_FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
| 
 | ||||
|         fractionalWidthOfPixelLocation = GLES20.glGetUniformLocation(programHandle, "fractionalWidthOfPixel"); | ||||
|         Egloo.checkGlProgramLocation(fractionalWidthOfPixelLocation, "fractionalWidthOfPixel"); | ||||
| 
 | ||||
|         aspectRatioLocation = GLES20.glGetUniformLocation(programHandle, "aspectRatio"); | ||||
|         Egloo.checkGlProgramLocation(aspectRatioLocation, "aspectRatio"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         GLES20.glUniform1f(fractionalWidthOfPixelLocation, fractionalWidthOfPixel); | ||||
|         GLES20.glUniform1f(aspectRatioLocation, aspectRatio); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         fractionalWidthOfPixel = 0.01f; | ||||
|         fractionalWidthOfPixelLocation = -1; | ||||
|         aspectRatio = 1f; | ||||
|         aspectRatioLocation = -1; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter1(float value) { | ||||
|         setFractionalWidthOfPixel(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter1() { | ||||
|         return getFractionalWidthOfPixel(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter2(float value) { | ||||
|         setAspectRatio(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter2() { | ||||
|         return getAspectRatio(); | ||||
|     } | ||||
| 
 | ||||
|     public float getFractionalWidthOfPixel() { | ||||
|         return fractionalWidthOfPixel; | ||||
|     } | ||||
| 
 | ||||
|     public void setFractionalWidthOfPixel(float fractionalWidthOfPixel) { | ||||
|         this.fractionalWidthOfPixel = fractionalWidthOfPixel; | ||||
|     } | ||||
| 
 | ||||
|     public float getAspectRatio() { | ||||
|         return aspectRatio; | ||||
|     } | ||||
| 
 | ||||
|     public void setAspectRatio(float aspectRatio) { | ||||
|         this.aspectRatio = aspectRatio; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,141 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class HighEdgeGlowFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "/* Returns rgb vec from input 0-1 */\n" + | ||||
|                     "vec3 getRainbowColor(in float val) {\n" + | ||||
|                     "    /*convert to rainbow RGB*/\n" + | ||||
|                     "    float a = (1.0 - val) * 6.0;\n" + | ||||
|                     "    int X = int(floor(a));\n" + | ||||
|                     "    float Y = a - float(X);\n" + | ||||
|                     "    float r = 0.;\n" + | ||||
|                     "    float g = 0.;\n" + | ||||
|                     "    float b = 0.;\n" + | ||||
|                     "    if (X == 0) {\n" + | ||||
|                     "        r = 1.; g = Y; b = 0.;\n" + | ||||
|                     "    } else if (X == 1) {\n" + | ||||
|                     "        r = 1. - Y; g = 1.; b = 0.;\n" + | ||||
|                     "    } else if (X == 2) {\n" + | ||||
|                     "        r = 0.; g = 1.; b = Y;\n" + | ||||
|                     "    } else if (X == 3) {\n" + | ||||
|                     "        r = 0.; g = 1. - Y; b = 1.;\n" + | ||||
|                     "    } else if (X == 4) {\n" + | ||||
|                     "        r = Y; g = 0.; b = 1.;\n" + | ||||
|                     "    } else if (X == 5) {\n" + | ||||
|                     "        r = 1.; g = 0.; b = 1. - Y;\n" + | ||||
|                     "    } else {\n" + | ||||
|                     "        r = 0.; g = 0.; b = 0.;\n" + | ||||
|                     "    }\n" + | ||||
|                     "    return vec3(r, g, b);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float d;\n" + | ||||
|                     "\n" + | ||||
|                     "float lookup(vec2 p, float dx, float dy, float edgeIntensity)\n" + | ||||
|                     "{\n" + | ||||
|                     "    vec2 uv = (p.xy + vec2(dx * edgeIntensity, dy * edgeIntensity)) / iResolution.xy;\n" + | ||||
|                     "    vec4 c = texture2D(iChannel0, uv.xy);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\t// return as luma\n" + | ||||
|                     "    return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    float timeNorm = mod(iTime, 5.) / 5.;\n" + | ||||
|                     "    vec3 glowCol = getRainbowColor(timeNorm);\n" + | ||||
|                     "    float edgeIntensity = 10.;\n" + | ||||
|                     "    vec2 p = fragCoord.xy;\n" + | ||||
|                     "    \n" + | ||||
|                     "\t// simple sobel edge detection\n" + | ||||
|                     "    float gx = 0.0;\n" + | ||||
|                     "    gx += -1.0 * lookup(p, -1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gx += -2.0 * lookup(p, -1.0,  0.0, edgeIntensity);\n" + | ||||
|                     "    gx += -1.0 * lookup(p, -1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  1.0 * lookup(p,  1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  2.0 * lookup(p,  1.0,  0.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  1.0 * lookup(p,  1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    \n" + | ||||
|                     "    float gy = 0.0;\n" + | ||||
|                     "    gy += -1.0 * lookup(p, -1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy += -2.0 * lookup(p,  0.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy += -1.0 * lookup(p,  1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  1.0 * lookup(p, -1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  2.0 * lookup(p,  0.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  1.0 * lookup(p,  1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    \n" + | ||||
|                     "\t// hack: use g^2 to conceal noise in the video\n" + | ||||
|                     "    float g = gx*gx + gy*gy;\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec4 col = texture2D(iChannel0, p / iResolution.xy);\n" + | ||||
|                     "    col += vec4(g * glowCol, 1.0);\n" + | ||||
|                     "    \n" + | ||||
|                     "    fragColor = col;\n" + | ||||
|                     "}" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,112 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.TwoParameterFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| /** | ||||
|  * between 0.0 to 1.0 | ||||
|  */ | ||||
| public class HighlightShadowFilter extends BaseFilter implements TwoParameterFilter { | ||||
|     private static final String EXPOSURE_FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision mediump float;" + | ||||
|             " uniform samplerExternalOES sTexture;\n" + | ||||
|             " uniform float shadows;\n" + | ||||
|             " uniform float highlights;\n" + | ||||
|             " varying vec2 vTextureCoord;\n" + | ||||
|             " \n" + | ||||
|             " const mediump vec3 luminanceWeighting = vec3(0.3, 0.3, 0.3);\n" + | ||||
|             " \n" + | ||||
|             " void main()\n" + | ||||
|             " {\n" + | ||||
|             " 	vec4 source = texture2D(sTexture, vTextureCoord);\n" + | ||||
|             " 	mediump float luminance = dot(source.rgb, luminanceWeighting);\n" + | ||||
|             " \n" + | ||||
|             " 	mediump float shadow = clamp((pow(luminance, 1.0/(shadows+1.0)) + (-0.76)*pow(luminance, 2.0/(shadows+1.0))) - luminance, 0.0, 1.0);\n" + | ||||
|             " 	mediump float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0);\n" + | ||||
|             " 	lowp vec3 result = vec3(0.0, 0.0, 0.0) + ((luminance + shadow + highlight) - 0.0) * ((source.rgb - vec3(0.0, 0.0, 0.0))/(luminance - 0.0));\n" + | ||||
|             " \n" + | ||||
|             " 	gl_FragColor = vec4(result.rgb, source.a);\n" + | ||||
|             " }"; | ||||
| 
 | ||||
|     private float shadows = 1f; | ||||
|     private int shadowsLocation = -1; | ||||
| 
 | ||||
|     private float highlights = 0f; | ||||
|     private int highlightsLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return EXPOSURE_FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
| 
 | ||||
|         shadowsLocation = GLES20.glGetUniformLocation(programHandle, "shadows"); | ||||
|         Egloo.checkGlProgramLocation(shadowsLocation, "shadows"); | ||||
| 
 | ||||
|         highlightsLocation = GLES20.glGetUniformLocation(programHandle, "highlights"); | ||||
|         Egloo.checkGlProgramLocation(highlightsLocation, "highlights"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         GLES20.glUniform1f(shadowsLocation, shadows); | ||||
|         GLES20.glUniform1f(highlightsLocation, highlights); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         shadows = 1f; | ||||
|         shadowsLocation = -1; | ||||
|         highlights = 0f; | ||||
|         highlightsLocation = -1; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter1(float value) { | ||||
|         setShadows(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter1() { | ||||
|         return getShadows(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter2(float value) { | ||||
|         setHighlights(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter2() { | ||||
|         return getHighlights(); | ||||
|     } | ||||
| 
 | ||||
|     public float getShadows() { | ||||
|         return shadows; | ||||
|     } | ||||
| 
 | ||||
|     public void setShadows(float shadows) { | ||||
|         this.shadows = shadows; | ||||
|     } | ||||
| 
 | ||||
|     public float getHighlights() { | ||||
|         return highlights; | ||||
|     } | ||||
| 
 | ||||
|     public void setHighlights(float highlights) { | ||||
|         this.highlights = highlights; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,82 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.filter.OneParameterFilter; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| /** | ||||
|  * exposure: The adjusted exposure (-10.0 - 10.0, with 0.0 as the default) | ||||
|  */ | ||||
| public class LuminanceThresholdFilter extends BaseFilter implements OneParameterFilter { | ||||
|     private static final String EXPOSURE_FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision mediump float;" + | ||||
|             "varying highp vec2 vTextureCoord;\n" + | ||||
|             "\n" + | ||||
|             "uniform samplerExternalOES sTexture;\n" + | ||||
|             "uniform highp float threshold;\n" + | ||||
|             "\n" + | ||||
|             "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + | ||||
|             "\n" + | ||||
|             "void main()\n" + | ||||
|             "{\n" + | ||||
|             "    highp vec4 textureColor = texture2D(sTexture, vTextureCoord);\n" + | ||||
|             "    highp float luminance = dot(textureColor.rgb, W);\n" + | ||||
|             "    highp float thresholdResult = step(threshold, luminance);\n" + | ||||
|             "    \n" + | ||||
|             "    gl_FragColor = vec4(vec3(thresholdResult), textureColor.w);\n" + | ||||
|             "}"; | ||||
| 
 | ||||
| 
 | ||||
|     private float threshold = 0.5f; | ||||
|     private int thresholdLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return EXPOSURE_FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         thresholdLocation = GLES20.glGetUniformLocation(programHandle, "threshold"); | ||||
|         Egloo.checkGlProgramLocation(thresholdLocation, "threshold"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|         GLES20.glUniform1f(thresholdLocation, threshold); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         threshold = 0.5f; | ||||
|         thresholdLocation = -1; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParameter1(float value) { | ||||
|         setThreshold(value); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getParameter1() { | ||||
|         return getThreshold(); | ||||
|     } | ||||
| 
 | ||||
|     public float getThreshold() { | ||||
|         return threshold; | ||||
|     } | ||||
| 
 | ||||
|     public void setThreshold(float threshold) { | ||||
|         this.threshold = threshold; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,49 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| 
 | ||||
| public class MirrorFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "  {\n" + | ||||
|                     "    vec2 flipCoord = vec2(1.0-fragCoord.x, fragCoord.y);\n" + | ||||
|                     "    if(flipCoord.x >= 0.5){\n" + | ||||
|                     "    \tfragColor = texture2D(iChannel0, vec2( flipCoord.x - 0.5, flipCoord.y ));\n" + | ||||
|                     "    } else {\n" + | ||||
|                     "    \tfragColor = texture2D(iChannel0, vec2(  0.5 - flipCoord.x,flipCoord.y ));\n" + | ||||
|                     "    }\n" + | ||||
|                     "   }\n" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     " \tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ");\n" + | ||||
|                     " }"; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,143 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class NeonEdgeGlowFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "/* Returns rgb vec from input 0-1 */\n" + | ||||
|                     "vec3 getRainbowColor(in float val) {\n" + | ||||
|                     "    /*convert to rainbow RGB*/\n" + | ||||
|                     "    float a = (1.0 - val) * 6.0;\n" + | ||||
|                     "    int X = int(floor(a));\n" + | ||||
|                     "    float Y = a - float(X);\n" + | ||||
|                     "    float r = 0.;\n" + | ||||
|                     "    float g = 0.;\n" + | ||||
|                     "    float b = 0.;\n" + | ||||
|                     "    if (X == 0) {\n" + | ||||
|                     "        r = 1.; g = Y; b = 0.;\n" + | ||||
|                     "    } else if (X == 1) {\n" + | ||||
|                     "        r = 1. - Y; g = 1.; b = 0.;\n" + | ||||
|                     "    } else if (X == 2) {\n" + | ||||
|                     "        r = 0.; g = 1.; b = Y;\n" + | ||||
|                     "    } else if (X == 3) {\n" + | ||||
|                     "        r = 0.; g = 1. - Y; b = 1.;\n" + | ||||
|                     "    } else if (X == 4) {\n" + | ||||
|                     "        r = Y; g = 0.; b = 1.;\n" + | ||||
|                     "    } else if (X == 5) {\n" + | ||||
|                     "        r = 1.; g = 0.; b = 1. - Y;\n" + | ||||
|                     "    } else {\n" + | ||||
|                     "        r = 0.; g = 0.; b = 0.;\n" + | ||||
|                     "    }\n" + | ||||
|                     "    return vec3(57,255,20);\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "float d;\n" + | ||||
|                     "\n" + | ||||
|                     "float lookup(vec2 p, float dx, float dy, float edgeIntensity)\n" + | ||||
|                     "{\n" + | ||||
|                     "    vec2 uv = (p.xy + vec2(dx * edgeIntensity, dy * edgeIntensity)) / iResolution.xy;\n" + | ||||
|                     "    vec4 c = texture2D(iChannel0, uv.xy);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\t// return as luma\n" + | ||||
|                     "    return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "    float timeNorm = mod(iTime, 5.) / 5.;\n" + | ||||
|                     "    vec3 glowCol = getRainbowColor(timeNorm);\n" + | ||||
|                     "    float edgeIntensity = 1.;\n" + | ||||
|                     "    if (timeNorm < .5) { edgeIntensity += (4. * timeNorm);}\n" + | ||||
|                     "    else { edgeIntensity += -4. * (timeNorm - 1.); }\n" + | ||||
|                     "    vec2 p = fragCoord.xy;\n" + | ||||
|                     "    \n" + | ||||
|                     "\t// simple sobel edge detection\n" + | ||||
|                     "    float gx = 0.0;\n" + | ||||
|                     "    gx += -1.0 * lookup(p, -1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gx += -2.0 * lookup(p, -1.0,  0.0, edgeIntensity);\n" + | ||||
|                     "    gx += -1.0 * lookup(p, -1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  1.0 * lookup(p,  1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  2.0 * lookup(p,  1.0,  0.0, edgeIntensity);\n" + | ||||
|                     "    gx +=  1.0 * lookup(p,  1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    \n" + | ||||
|                     "    float gy = 0.0;\n" + | ||||
|                     "    gy += -1.0 * lookup(p, -1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy += -2.0 * lookup(p,  0.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy += -1.0 * lookup(p,  1.0, -1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  1.0 * lookup(p, -1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  2.0 * lookup(p,  0.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    gy +=  1.0 * lookup(p,  1.0,  1.0, edgeIntensity);\n" + | ||||
|                     "    \n" + | ||||
|                     "\t// hack: use g^2 to conceal noise in the video\n" + | ||||
|                     "    float g = gx*gx + gy*gy;\n" + | ||||
|                     "    \n" + | ||||
|                     "    vec4 col = texture2D(iChannel0, p / iResolution.xy);\n" + | ||||
|                     "    col += vec4(g * glowCol, 1.0);\n" + | ||||
|                     "    \n" + | ||||
|                     "    fragColor = col;\n" + | ||||
|                     "}" + | ||||
|                     "\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "\tmainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + " * iResolution.xy);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
|         float time = (((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f) + 1; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,88 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class RainbowFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                     "precision highp float;\n" + | ||||
|                     "\n" + | ||||
|                     "uniform vec3                iResolution;\n" + | ||||
|                     "uniform samplerExternalOES           iChannel0;\n" + | ||||
|                     "uniform float               iTime;\n" + | ||||
|                     "varying vec2                " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ";\n" + | ||||
|                     "\n" + | ||||
|                     "vec2 size = vec2(50.0, 50.0);\n" + | ||||
|                     "vec2 distortion = vec2(20.0, 20.0);\n" + | ||||
|                     "float speed = 0.75;" + | ||||
|                     "\n" + | ||||
|                     "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|                     "{\n" + | ||||
|                     "   vec2 transformed = vec2(\n" + | ||||
|                     "       fragCoord.x + sin(fragCoord.y / size.x + iTime * speed) * distortion.x,\n" + | ||||
|                     "       fragCoord.y + cos(fragCoord.x / size.y + iTime * speed) * distortion.y\n" + | ||||
|                     "   );\n" + | ||||
|                     "   vec2 relCoord = fragCoord.xy / iResolution.xy;\n" + | ||||
|                     "   fragColor = texture2D(iChannel0, fragCoord/iResolution.xy) + vec4(\n" + | ||||
|                         "        (cos(relCoord.x + iTime * speed * 4.0) + 1.0) / 2.0,\n" + | ||||
|                         "        (relCoord.x + relCoord.y) / 2.0,\n" + | ||||
|                         "        (sin(relCoord.y + iTime * speed) + 1.0) / 2.0,\n" + | ||||
|                         "        0\n" + | ||||
|                     "           );\n" + | ||||
|                     "}\n" + | ||||
|                     "void main() {\n" + | ||||
|                     "    mainImage(gl_FragColor, " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ");\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     long START_TIME = System.currentTimeMillis(); | ||||
|     private int iGlobalTimeLocation = -1; | ||||
|     private int iResolutionLocation = -1; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         iGlobalTimeLocation = -1; | ||||
|         START_TIME = System.currentTimeMillis(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|         iResolutionLocation = GLES20.glGetUniformLocation(programHandle, "iResolution"); | ||||
|         Egloo.checkGlProgramLocation(iResolutionLocation, "iResolution"); | ||||
| 
 | ||||
|         iGlobalTimeLocation = GLES20.glGetUniformLocation(programHandle, "iTime"); | ||||
|         Egloo.checkGlProgramLocation(iGlobalTimeLocation, "iTime"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
| 
 | ||||
|         Size size = getSize(); | ||||
|         if (size != null) { | ||||
|             GLES20.glUniform3fv(iResolutionLocation, 1, | ||||
|                     FloatBuffer.wrap(new float[]{(float) size.getWidth(), (float) size.getHeight(), 1.0f})); | ||||
|             Egloo.checkGlError("glUniform3fv"); | ||||
|         } | ||||
| 
 | ||||
|         float time = ((float) (System.currentTimeMillis() - START_TIME)) / 1000.0f; | ||||
|         GLES20.glUniform1f(iGlobalTimeLocation, time); | ||||
|         Egloo.checkGlError("glUniform1f"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,46 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.res.Resources; | ||||
| import android.graphics.Bitmap; | ||||
| import android.graphics.BitmapFactory; | ||||
| import android.opengl.GLES20; | ||||
| import android.opengl.GLUtils; | ||||
| 
 | ||||
| public class TextureHelper { | ||||
|     public static int loadTexture(final Context context, final int resourceId) | ||||
|     { | ||||
|         final int[] textureHandle = new int[1]; | ||||
| 
 | ||||
|         GLES20.glGenTextures(1, textureHandle, 0); | ||||
| 
 | ||||
|         if (textureHandle[0] != 0) | ||||
|         { | ||||
|             final BitmapFactory.Options options = new BitmapFactory.Options(); | ||||
|             options.inScaled = false;	// No pre-scaling
 | ||||
| 
 | ||||
|             // Read in the resource
 | ||||
|             final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options); | ||||
| 
 | ||||
|             // Bind to the texture in OpenGL
 | ||||
|             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]); | ||||
| 
 | ||||
|             // Set filtering
 | ||||
|             GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); | ||||
|             GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); | ||||
| 
 | ||||
|             // Load the bitmap into the bound texture.
 | ||||
|             GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); | ||||
| 
 | ||||
|             // Recycle the bitmap, since its data has been loaded into OpenGL.
 | ||||
|             bitmap.recycle(); | ||||
|         } | ||||
| 
 | ||||
|         if (textureHandle[0] == 0) | ||||
|         { | ||||
|             throw new RuntimeException("Error loading texture."); | ||||
|         } | ||||
| 
 | ||||
|         return textureHandle[0]; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,90 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import android.opengl.GLES20; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.opengl.core.Egloo; | ||||
| 
 | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| public class ToasterFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|                    "precision mediump float; \n" + | ||||
|                     "uniform samplerExternalOES u_Texture0; \n" + | ||||
| //                    "uniform sampler2D u_Texture4;\n" +
 | ||||
|                     "varying vec2 " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + "; \n" + | ||||
|                     "const vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + | ||||
|                     "\n" + | ||||
|                     "vec3 BrightnessContrastSaturation(vec3 color, float brt, float con, float sat)\n" + | ||||
|                     "{\n" + | ||||
|                     "\tvec3 black = vec3(0., 0., 0.);\n" + | ||||
|                     "\tvec3 middle = vec3(0.5, 0.5, 0.5);\n" + | ||||
|                     "\tfloat luminance = dot(color, W);\n" + | ||||
|                     "\tvec3 gray = vec3(luminance, luminance, luminance);\n" + | ||||
|                     "\t\n" + | ||||
|                     "\tvec3 brtColor = mix(black, color, brt);\n" + | ||||
|                     "\tvec3 conColor = mix(middle, brtColor, con);\n" + | ||||
|                     "\tvec3 satColor = mix(gray, conColor, sat);\n" + | ||||
|                     "\treturn satColor;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "vec3 ovelayBlender(vec3 Color, vec3 filter){\n" + | ||||
|                     "\tvec3 filter_result;\n" + | ||||
|                     "\t\n" + | ||||
|                     "\t//if(luminance < 0.5)\n" + | ||||
|                     "\t//\tfilter_result = 2. * trans_filter * Color;\n" + | ||||
|                     "\t//else\n" + | ||||
|                     "\t\tfilter_result = 1. - (1. - (2. *(filter - 0.5)))*(1. - Color);\n" + | ||||
|                     "\t\t\n" + | ||||
|                     "\treturn filter_result;\n" + | ||||
|                     "}\n" + | ||||
|                     "\n" + | ||||
|                     "void main()\n" + | ||||
|                     "{\n" + | ||||
|                     "\t //get the pixel\n" + | ||||
|                     "     vec2 st = " + DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME + ".st;\n" + | ||||
|                     "     vec3 irgb = texture2D(u_Texture0, st).rgb;\n" + | ||||
| //                    "     vec3 filter = texture2D(u_Texture4, st).rgb;\n" +
 | ||||
|                     "     \n" + | ||||
|                     "     //adjust the brightness/contrast/saturation\n" + | ||||
|                     "     float T_bright = 1.0;\n" + | ||||
|                     "     float T_contrast = 1.0;\n" + | ||||
|                     "     float T_saturation = 1.0;\n" + | ||||
|                     "     vec3 bcs_result = BrightnessContrastSaturation(irgb, T_bright, T_contrast, T_saturation);\n" + | ||||
|                     "     \n" + | ||||
|                     "     //more red\n" + | ||||
|                     "     vec3 rb_result = vec3(bcs_result.r*1.3, bcs_result.g, bcs_result.b*0.9);\n" + | ||||
|                     "     \n" + | ||||
| //                    "     //add filter (overlay blending)\n" +
 | ||||
| //                    "     vec3 after_filter = mix(bcs_result, ovelayBlender(bcs_result, filter), 0.55);\n" +
 | ||||
|                     "     \t\n" + | ||||
|                     "     gl_FragColor = vec4(rb_result, 1.);\n" + | ||||
|                     "}"; | ||||
| 
 | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(int programHandle) { | ||||
|         super.onCreate(programHandle); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onPreDraw(long timestampUs, @NonNull float[] transformMatrix) { | ||||
|         super.onPreDraw(timestampUs, transformMatrix); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| package com.otaliastudios.cameraview.filters; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.filter.BaseFilter; | ||||
| 
 | ||||
| public class WavesReflectionFilter extends BaseFilter { | ||||
|     private static final String FRAGMENT_SHADER = | ||||
|             "#extension GL_OES_EGL_image_external : require\n" + | ||||
|             "precision highp float;\n" + | ||||
|             "\n" + | ||||
|             "uniform vec3                iResolution;\n" + | ||||
|             "uniform samplerExternalOES  iChannel0;\n" + | ||||
|             "varying vec2                "+DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME+";\n" + | ||||
|             "\n" + | ||||
|             "float waterLevel = 0.5;\n" + | ||||
|             "float waveAmplitude = 0.01;\n" + | ||||
|             "\n" + | ||||
|             "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" + | ||||
|             "  {\n" + | ||||
|             "     if(fragCoord.y >= waterLevel){\n" + | ||||
|             "        fragColor = texture2D(iChannel0, fragCoord);\n" + | ||||
|             "     }else{\n" + | ||||
|             "        fragColor = texture2D(iChannel0,vec2(fragCoord.x + fract(sin(dot(fragCoord.xy ,vec2(12.9898,78.233))) * 43758.5453) * waveAmplitude,\n" + | ||||
|             "       \t\t\t\t2.0 * waterLevel - fragCoord.y));\n" + | ||||
|             "     }\n" + | ||||
|             "   }\n" + | ||||
|             "\n" + | ||||
|             "void main() {\n" + | ||||
|             " \tmainImage(gl_FragColor, "+DEFAULT_FRAGMENT_TEXTURE_COORDINATE_NAME+");\n" + | ||||
|             " }"; | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public String getFragmentShader() { | ||||
|         return FRAGMENT_SHADER; | ||||
|     } | ||||
| } | ||||
| After Width: | Height: | Size: 519 KiB | 
					Loading…
					
					
				
		Reference in new issue