Update DuotoneFilter with onPreDraw

pull/535/head
Mattia Iavarone 6 years ago
parent 5543b93545
commit fa6dfa1f2d
  1. 84
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/DocumentaryFilter.java
  2. 103
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/DuotoneFilter.java

@ -14,7 +14,48 @@ import java.util.Random;
*/
public class DocumentaryFilter extends BaseFilter {
private final Random mRandom = new Random();
private final static Random RANDOM = new Random();
private final static String FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "vec2 seed;\n"
+ "float stepsize;\n"
+ "uniform float inv_max_dist;\n"
+ "uniform vec2 scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "float rand(vec2 loc) {\n"
+ " float theta1 = dot(loc, vec2(0.9898, 0.233));\n"
+ " float theta2 = dot(loc, vec2(12.0, 78.0));\n"
+ " float value = cos(theta1) * sin(theta2) + sin(theta1) * cos(theta2);\n"
+
// keep value of part1 in range: (2^-14 to 2^14).
" float temp = mod(197.0 * value, 1.0) + value;\n"
+ " float part1 = mod(220.0 * temp, 1.0) + temp;\n"
+ " float part2 = value * 0.5453;\n"
+ " float part3 = cos(theta1 + theta2) * 0.43758;\n"
+ " return fract(part1 + part2 + part3);\n"
+ "}\n"
+ "void main() {\n"
+ " seed[0] = " + RANDOM.nextFloat() + ";\n"
+ " seed[1] = " + RANDOM.nextFloat() + ";\n"
+ " stepsize = " + 1.0f / 255.0f + ";\n"
// black white
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float dither = rand(vTextureCoord + seed);\n"
+ " vec3 xform = clamp(2.0 * color.rgb, 0.0, 1.0);\n"
+ " vec3 temp = clamp(2.0 * (color.rgb + stepsize), 0.0, 1.0);\n"
+ " vec3 new_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n"
// grayscale
+ " float gray = dot(new_color, vec3(0.299, 0.587, 0.114));\n"
+ " new_color = vec3(gray, gray, gray);\n"
// vignette
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = 0.85 / (1.0 + exp((dist * inv_max_dist - 0.83) * 20.0)) + 0.15;\n"
+ " gl_FragColor = vec4(new_color * lumen, color.a);\n"
+ "}\n";
private int mWidth = 1;
private int mHeight = 1;
private int mScaleLocation = -1;
@ -32,46 +73,7 @@ public class DocumentaryFilter extends BaseFilter {
@NonNull
@Override
public String getFragmentShader() {
return "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "vec2 seed;\n"
+ "float stepsize;\n"
+ "uniform float inv_max_dist;\n"
+ "uniform vec2 scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "float rand(vec2 loc) {\n"
+ " float theta1 = dot(loc, vec2(0.9898, 0.233));\n"
+ " float theta2 = dot(loc, vec2(12.0, 78.0));\n"
+ " float value = cos(theta1) * sin(theta2) + sin(theta1) * cos(theta2);\n"
+
// keep value of part1 in range: (2^-14 to 2^14).
" float temp = mod(197.0 * value, 1.0) + value;\n"
+ " float part1 = mod(220.0 * temp, 1.0) + temp;\n"
+ " float part2 = value * 0.5453;\n"
+ " float part3 = cos(theta1 + theta2) * 0.43758;\n"
+ " return fract(part1 + part2 + part3);\n"
+ "}\n"
+ "void main() {\n"
+ " seed[0] = " + mRandom.nextFloat() + ";\n"
+ " seed[1] = " + mRandom.nextFloat() + ";\n"
+ " stepsize = " + 1.0f / 255.0f + ";\n"
// black white
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float dither = rand(vTextureCoord + seed);\n"
+ " vec3 xform = clamp(2.0 * color.rgb, 0.0, 1.0);\n"
+ " vec3 temp = clamp(2.0 * (color.rgb + stepsize), 0.0, 1.0);\n"
+ " vec3 new_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n"
// grayscale
+ " float gray = dot(new_color, vec3(0.299, 0.587, 0.114));\n"
+ " new_color = vec3(gray, gray, gray);\n"
// vignette
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = 0.85 / (1.0 + exp((dist * inv_max_dist - 0.83) * 20.0)) + 0.15;\n"
+ " gl_FragColor = vec4(new_color * lumen, color.a);\n"
+ "}\n";
return FRAGMENT_SHADER;
}
@Override

@ -1,20 +1,37 @@
package com.otaliastudios.cameraview.filters;
import android.graphics.Color;
import android.opengl.GLES20;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import com.otaliastudios.cameraview.filter.BaseFilter;
import com.otaliastudios.cameraview.internal.GlUtils;
/**
* Representation of input frames using only two color tones.
*/
public class DuotoneFilter extends BaseFilter {
private final static String FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "uniform vec3 first;\n"
+ "uniform vec3 second;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float energy = (color.r + color.g + color.b) * 0.3333;\n"
+ " vec3 new_color = (1.0 - energy) * first + energy * second;\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n"
+ "}\n";
// Default values
private int mFirstColor = Color.MAGENTA;
private int mSecondColor = Color.YELLOW;
private int mFirstColorLocation = -1;
private int mSecondColorLocation = -1;
@SuppressWarnings("WeakerAccess")
public DuotoneFilter() { }
@ -58,7 +75,7 @@ public class DuotoneFilter extends BaseFilter {
* @see #setFirstColor(int)
* @return first
*/
@SuppressWarnings("unused")
@SuppressWarnings({"unused", "WeakerAccess"})
@ColorInt
public int getFirstColor() {
return mFirstColor;
@ -70,57 +87,57 @@ public class DuotoneFilter extends BaseFilter {
* @see #setSecondColor(int)
* @return second
*/
@SuppressWarnings("unused")
@SuppressWarnings({"unused", "WeakerAccess"})
@ColorInt
public int getSecondColor() {
return mSecondColor;
}
@Override
protected BaseFilter onCopy() {
DuotoneFilter filter = new DuotoneFilter();
filter.setColors(mFirstColor, mSecondColor);
return filter;
}
@NonNull
@Override
public String getFragmentShader() {
float[] first = {Color.red(mFirstColor) / 255f,
Color.green(mFirstColor) / 255f, Color.blue(mFirstColor) / 255f};
float[] second = {Color.red(mSecondColor) / 255f,
return FRAGMENT_SHADER;
}
@Override
public void onCreate(int programHandle) {
super.onCreate(programHandle);
mFirstColorLocation = GLES20.glGetUniformLocation(programHandle, "first");
GlUtils.checkLocation(mFirstColorLocation, "first");
mSecondColorLocation = GLES20.glGetUniformLocation(programHandle, "second");
GlUtils.checkLocation(mSecondColorLocation, "second");
}
@Override
protected void onPreDraw(float[] transformMatrix) {
super.onPreDraw(transformMatrix);
float[] first = new float[]{
Color.red(mFirstColor) / 255f,
Color.green(mFirstColor) / 255f,
Color.blue(mFirstColor) / 255f
};
float[] second = new float[]{
Color.red(mSecondColor) / 255f,
Color.green(mSecondColor) / 255f,
Color.blue(mSecondColor) / 255f};
String[] firstColorString = new String[3];
String[] secondColorString = new String[3];
firstColorString[0] = "first[0] = " + first[0] + ";\n";
firstColorString[1] = "first[1] = " + first[1] + ";\n";
firstColorString[2] = "first[2] = " + first[2] + ";\n";
secondColorString[0] = "second[0] = " + second[0] + ";\n";
secondColorString[1] = "second[1] = " + second[1] + ";\n";
secondColorString[2] = "second[2] = " + second[2] + ";\n";
return "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "vec3 first;\n"
+ "vec3 second;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ firstColorString[0]
+ firstColorString[1]
+ firstColorString[2]
+ secondColorString[0]
+ secondColorString[1]
+ secondColorString[2]
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float energy = (color.r + color.g + color.b) * 0.3333;\n"
+ " vec3 new_color = (1.0 - energy) * first + energy * second;\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n"
+ "}\n";
Color.blue(mSecondColor) / 255f
};
GLES20.glUniform3fv(mFirstColorLocation, 1, first, 0);
GLES20.glUniform3fv(mSecondColorLocation, 1, second, 0);
GlUtils.checkError("glUniform3fv");
}
@Override
public void onDestroy() {
super.onDestroy();
mFirstColorLocation = -1;
mSecondColorLocation = -1;
}
@Override
protected BaseFilter onCopy() {
DuotoneFilter filter = new DuotoneFilter();
filter.setColors(getFirstColor(), getSecondColor());
return filter;
}
}

Loading…
Cancel
Save