|
|
@ -1,8 +1,11 @@ |
|
|
|
package com.otaliastudios.cameraview.filters; |
|
|
|
package com.otaliastudios.cameraview.filters; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import android.opengl.GLES20; |
|
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull; |
|
|
|
import androidx.annotation.NonNull; |
|
|
|
|
|
|
|
|
|
|
|
import com.otaliastudios.cameraview.filter.BaseFilter; |
|
|
|
import com.otaliastudios.cameraview.filter.BaseFilter; |
|
|
|
|
|
|
|
import com.otaliastudios.cameraview.internal.GlUtils; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -10,10 +13,32 @@ import com.otaliastudios.cameraview.filter.BaseFilter; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class VignetteFilter extends BaseFilter { |
|
|
|
public class VignetteFilter 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 float range;\n" |
|
|
|
|
|
|
|
+ "uniform float inv_max_dist;\n" |
|
|
|
|
|
|
|
+ "uniform float shade;\n" |
|
|
|
|
|
|
|
+ "uniform vec2 scale;\n" |
|
|
|
|
|
|
|
+ "varying vec2 vTextureCoord;\n" |
|
|
|
|
|
|
|
+ "void main() {\n" |
|
|
|
|
|
|
|
+ " const float slope = 20.0;\n" |
|
|
|
|
|
|
|
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n" |
|
|
|
|
|
|
|
+ " float dist = length(coord * scale);\n" |
|
|
|
|
|
|
|
+ " float lumen = shade / (1.0 + exp((dist * inv_max_dist - range) * slope)) + (1.0 - shade);\n" |
|
|
|
|
|
|
|
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n" |
|
|
|
|
|
|
|
+ " gl_FragColor = vec4(color.rgb * lumen, color.a);\n" |
|
|
|
|
|
|
|
+ "}\n"; |
|
|
|
|
|
|
|
|
|
|
|
private float mScale = 0.85f; |
|
|
|
private float mScale = 0.85f; |
|
|
|
private float mShade = 0.5f; |
|
|
|
private float mShade = 0.5f; |
|
|
|
private int mOutputWidth = 1; |
|
|
|
private int mWidth = 1; |
|
|
|
private int mOutputHeight = 1; |
|
|
|
private int mHeight = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int mRangeLocation = -1; |
|
|
|
|
|
|
|
private int mMaxDistLocation = -1; |
|
|
|
|
|
|
|
private int mShadeLocation = -1; |
|
|
|
|
|
|
|
private int mScaleLocation = -1; |
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
public VignetteFilter() { } |
|
|
|
public VignetteFilter() { } |
|
|
@ -21,8 +46,8 @@ public class VignetteFilter extends BaseFilter { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void setSize(int width, int height) { |
|
|
|
public void setSize(int width, int height) { |
|
|
|
super.setSize(width, height); |
|
|
|
super.setSize(width, height); |
|
|
|
mOutputWidth = width; |
|
|
|
mWidth = width; |
|
|
|
mOutputHeight = height; |
|
|
|
mHeight = height; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -31,11 +56,9 @@ public class VignetteFilter extends BaseFilter { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
public void setVignetteScale(float scale) { |
|
|
|
public void setVignetteScale(float scale) { |
|
|
|
if (scale < 0.0f) |
|
|
|
if (scale < 0.0f) scale = 0.0f; |
|
|
|
scale = 0.0f; |
|
|
|
if (scale > 1.0f) scale = 1.0f; |
|
|
|
else if (scale > 1.0f) |
|
|
|
mScale = scale; |
|
|
|
scale = 1.0f; |
|
|
|
|
|
|
|
this.mScale = scale; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -71,61 +94,68 @@ public class VignetteFilter extends BaseFilter { |
|
|
|
return mShade; |
|
|
|
return mShade; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@NonNull |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected BaseFilter onCopy() { |
|
|
|
public String getFragmentShader() { |
|
|
|
VignetteFilter filter = new VignetteFilter(); |
|
|
|
return FRAGMENT_SHADER; |
|
|
|
filter.setVignetteScale(getVignetteScale()); |
|
|
|
|
|
|
|
filter.setVignetteShade(getVignetteShade()); |
|
|
|
|
|
|
|
return filter; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@NonNull |
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String getFragmentShader() { |
|
|
|
public void onCreate(int programHandle) { |
|
|
|
|
|
|
|
super.onCreate(programHandle); |
|
|
|
|
|
|
|
mRangeLocation = GLES20.glGetUniformLocation(programHandle, "range"); |
|
|
|
|
|
|
|
GlUtils.checkLocation(mRangeLocation, "range"); |
|
|
|
|
|
|
|
mMaxDistLocation = GLES20.glGetUniformLocation(programHandle, "inv_max_dist"); |
|
|
|
|
|
|
|
GlUtils.checkLocation(mMaxDistLocation, "inv_max_dist"); |
|
|
|
|
|
|
|
mShadeLocation = GLES20.glGetUniformLocation(programHandle, "shade"); |
|
|
|
|
|
|
|
GlUtils.checkLocation(mShadeLocation, "shade"); |
|
|
|
|
|
|
|
mScaleLocation = GLES20.glGetUniformLocation(programHandle, "scale"); |
|
|
|
|
|
|
|
GlUtils.checkLocation(mScaleLocation, "scale"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void onDestroy() { |
|
|
|
|
|
|
|
super.onDestroy(); |
|
|
|
|
|
|
|
mRangeLocation = -1; |
|
|
|
|
|
|
|
mMaxDistLocation = -1; |
|
|
|
|
|
|
|
mShadeLocation = -1; |
|
|
|
|
|
|
|
mScaleLocation = -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
protected void onPreDraw(float[] transformMatrix) { |
|
|
|
|
|
|
|
super.onPreDraw(transformMatrix); |
|
|
|
float[] scale = new float[2]; |
|
|
|
float[] scale = new float[2]; |
|
|
|
if (mOutputWidth > mOutputHeight) { |
|
|
|
if (mWidth > mHeight) { |
|
|
|
scale[0] = 1f; |
|
|
|
scale[0] = 1f; |
|
|
|
scale[1] = ((float) mOutputHeight) / mOutputWidth; |
|
|
|
scale[1] = ((float) mHeight) / mWidth; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
scale[0] = ((float) mOutputWidth) / mOutputHeight; |
|
|
|
scale[0] = ((float) mWidth) / mHeight; |
|
|
|
scale[1] = 1f; |
|
|
|
scale[1] = 1f; |
|
|
|
} |
|
|
|
} |
|
|
|
float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1] |
|
|
|
GLES20.glUniform2fv(mScaleLocation, 1, scale, 0); |
|
|
|
* scale[1])) * 0.5f; |
|
|
|
GlUtils.checkError("glUniform2fv"); |
|
|
|
|
|
|
|
|
|
|
|
String[] scaleString = new String[2]; |
|
|
|
float maxDist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1] * scale[1])) * 0.5f; |
|
|
|
scaleString[0] = "scale[0] = " + scale[0] + ";\n"; |
|
|
|
GLES20.glUniform1f(mMaxDistLocation, 1F / maxDist); |
|
|
|
scaleString[1] = "scale[1] = " + scale[1] + ";\n"; |
|
|
|
GlUtils.checkError("glUniform1f"); |
|
|
|
String inv_max_distString = "inv_max_dist = " + 1.0f / max_dist + ";\n"; |
|
|
|
|
|
|
|
String shadeString = "shade = " + mShade + ";\n"; |
|
|
|
GLES20.glUniform1f(mShadeLocation, mShade); |
|
|
|
|
|
|
|
GlUtils.checkError("glUniform1f"); |
|
|
|
|
|
|
|
|
|
|
|
// The 'range' is between 1.3 to 0.6. When scale is zero then range is 1.3
|
|
|
|
// The 'range' is between 1.3 to 0.6. When scale is zero then range is 1.3
|
|
|
|
// which means no vignette at all because the luminousity difference is
|
|
|
|
// which means no vignette at all because the luminousity difference is
|
|
|
|
// less than 1/256 and will cause nothing.
|
|
|
|
// less than 1/256 and will cause nothing.
|
|
|
|
String rangeString = "range = " |
|
|
|
float range = (1.30f - (float) Math.sqrt(mScale) * 0.7f); |
|
|
|
+ (1.30f - (float) Math.sqrt(mScale) * 0.7f) + ";\n"; |
|
|
|
GLES20.glUniform1f(mRangeLocation, range); |
|
|
|
|
|
|
|
GlUtils.checkError("glUniform1f"); |
|
|
|
return "#extension GL_OES_EGL_image_external : require\n" |
|
|
|
} |
|
|
|
+ "precision mediump float;\n" |
|
|
|
|
|
|
|
+ "uniform samplerExternalOES sTexture;\n" |
|
|
|
@Override |
|
|
|
+ " float range;\n" |
|
|
|
protected BaseFilter onCopy() { |
|
|
|
+ " float inv_max_dist;\n" |
|
|
|
VignetteFilter filter = new VignetteFilter(); |
|
|
|
+ " float shade;\n" |
|
|
|
filter.setVignetteScale(getVignetteScale()); |
|
|
|
+ " vec2 scale;\n" |
|
|
|
filter.setVignetteShade(getVignetteShade()); |
|
|
|
+ "varying vec2 vTextureCoord;\n" |
|
|
|
return filter; |
|
|
|
+ "void main() {\n" |
|
|
|
|
|
|
|
// Parameters that were created above
|
|
|
|
|
|
|
|
+ scaleString[0] |
|
|
|
|
|
|
|
+ scaleString[1] |
|
|
|
|
|
|
|
+ inv_max_distString |
|
|
|
|
|
|
|
+ shadeString |
|
|
|
|
|
|
|
+ rangeString |
|
|
|
|
|
|
|
+ " const float slope = 20.0;\n" |
|
|
|
|
|
|
|
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n" |
|
|
|
|
|
|
|
+ " float dist = length(coord * scale);\n" |
|
|
|
|
|
|
|
+ " float lumen = shade / (1.0 + exp((dist * inv_max_dist - range) * slope)) + (1.0 - shade);\n" |
|
|
|
|
|
|
|
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n" |
|
|
|
|
|
|
|
+ " gl_FragColor = vec4(color.rgb * lumen, color.a);\n" |
|
|
|
|
|
|
|
+ "}\n"; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|